forked from FFmpeg/FFmpeg
oggdec: Seek to keyframes
Originally committed as revision 22463 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
873d117e4b
commit
d8b91fae1d
2 changed files with 34 additions and 3 deletions
|
@ -531,9 +531,10 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
|
||||||
struct ogg_stream *os;
|
struct ogg_stream *os;
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
int pstart, psize;
|
int pstart, psize;
|
||||||
int64_t fpos;
|
int64_t fpos, pts, dts;
|
||||||
|
|
||||||
//Get an ogg packet
|
//Get an ogg packet
|
||||||
|
retry:
|
||||||
do{
|
do{
|
||||||
if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
|
if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
|
||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
|
@ -542,13 +543,21 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
|
||||||
ogg = s->priv_data;
|
ogg = s->priv_data;
|
||||||
os = ogg->streams + idx;
|
os = ogg->streams + idx;
|
||||||
|
|
||||||
|
// pflags might not be set until after this
|
||||||
|
pts = ogg_calc_pts(s, idx, &dts);
|
||||||
|
|
||||||
|
if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
|
||||||
|
goto retry;
|
||||||
|
os->keyframe_seek = 0;
|
||||||
|
|
||||||
//Alloc a pkt
|
//Alloc a pkt
|
||||||
if (av_new_packet (pkt, psize) < 0)
|
if (av_new_packet (pkt, psize) < 0)
|
||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
pkt->stream_index = idx;
|
pkt->stream_index = idx;
|
||||||
memcpy (pkt->data, os->buf + pstart, psize);
|
memcpy (pkt->data, os->buf + pstart, psize);
|
||||||
|
|
||||||
pkt->pts = ogg_calc_pts(s, idx, &pkt->dts);
|
pkt->pts = pts;
|
||||||
|
pkt->dts = dts;
|
||||||
pkt->flags = os->pflags;
|
pkt->flags = os->pflags;
|
||||||
pkt->duration = os->pduration;
|
pkt->duration = os->pduration;
|
||||||
pkt->pos = fpos;
|
pkt->pos = fpos;
|
||||||
|
@ -577,6 +586,7 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
|
||||||
int64_t pos_limit)
|
int64_t pos_limit)
|
||||||
{
|
{
|
||||||
struct ogg *ogg = s->priv_data;
|
struct ogg *ogg = s->priv_data;
|
||||||
|
struct ogg_stream *os = ogg->streams + stream_index;
|
||||||
ByteIOContext *bc = s->pb;
|
ByteIOContext *bc = s->pb;
|
||||||
int64_t pts = AV_NOPTS_VALUE;
|
int64_t pts = AV_NOPTS_VALUE;
|
||||||
int i;
|
int i;
|
||||||
|
@ -586,6 +596,8 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
|
||||||
while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
|
while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
|
||||||
if (i == stream_index) {
|
if (i == stream_index) {
|
||||||
pts = ogg_calc_pts(s, i, NULL);
|
pts = ogg_calc_pts(s, i, NULL);
|
||||||
|
if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
|
||||||
|
pts = AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
if (pts != AV_NOPTS_VALUE)
|
if (pts != AV_NOPTS_VALUE)
|
||||||
break;
|
break;
|
||||||
|
@ -594,6 +606,24 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
|
||||||
|
{
|
||||||
|
struct ogg *ogg = s->priv_data;
|
||||||
|
struct ogg_stream *os = ogg->streams + stream_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
// Try seeking to a keyframe first. If this fails (very possible),
|
||||||
|
// av_seek_frame will fall back to ignoring keyframes
|
||||||
|
if (s->streams[stream_index]->codec->codec_type == CODEC_TYPE_VIDEO
|
||||||
|
&& !(flags & AVSEEK_FLAG_ANY))
|
||||||
|
os->keyframe_seek = 1;
|
||||||
|
|
||||||
|
ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
|
||||||
|
if (ret < 0)
|
||||||
|
os->keyframe_seek = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int ogg_probe(AVProbeData *p)
|
static int ogg_probe(AVProbeData *p)
|
||||||
{
|
{
|
||||||
if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
|
if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
|
||||||
|
@ -612,7 +642,7 @@ AVInputFormat ogg_demuxer = {
|
||||||
ogg_read_header,
|
ogg_read_header,
|
||||||
ogg_read_packet,
|
ogg_read_packet,
|
||||||
ogg_read_close,
|
ogg_read_close,
|
||||||
NULL,
|
ogg_read_seek,
|
||||||
ogg_read_timestamp,
|
ogg_read_timestamp,
|
||||||
.extensions = "ogg",
|
.extensions = "ogg",
|
||||||
.metadata_conv = ff_vorbiscomment_metadata_conv,
|
.metadata_conv = ff_vorbiscomment_metadata_conv,
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct ogg_stream {
|
||||||
uint8_t segments[255];
|
uint8_t segments[255];
|
||||||
int incomplete; ///< whether we're expecting a continuation in the next page
|
int incomplete; ///< whether we're expecting a continuation in the next page
|
||||||
int page_end; ///< current packet is the last one completed in the page
|
int page_end; ///< current packet is the last one completed in the page
|
||||||
|
int keyframe_seek;
|
||||||
void *private;
|
void *private;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue