mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
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
@ -531,9 +531,10 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
|
||||
struct ogg_stream *os;
|
||||
int idx = -1;
|
||||
int pstart, psize;
|
||||
int64_t fpos;
|
||||
int64_t fpos, pts, dts;
|
||||
|
||||
//Get an ogg packet
|
||||
retry:
|
||||
do{
|
||||
if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
|
||||
return AVERROR(EIO);
|
||||
@ -542,13 +543,21 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
|
||||
ogg = s->priv_data;
|
||||
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
|
||||
if (av_new_packet (pkt, psize) < 0)
|
||||
return AVERROR(EIO);
|
||||
pkt->stream_index = idx;
|
||||
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->duration = os->pduration;
|
||||
pkt->pos = fpos;
|
||||
@ -577,6 +586,7 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
|
||||
int64_t pos_limit)
|
||||
{
|
||||
struct ogg *ogg = s->priv_data;
|
||||
struct ogg_stream *os = ogg->streams + stream_index;
|
||||
ByteIOContext *bc = s->pb;
|
||||
int64_t pts = AV_NOPTS_VALUE;
|
||||
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)) {
|
||||
if (i == stream_index) {
|
||||
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)
|
||||
break;
|
||||
@ -594,6 +606,24 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
|
||||
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)
|
||||
{
|
||||
if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
|
||||
@ -612,7 +642,7 @@ AVInputFormat ogg_demuxer = {
|
||||
ogg_read_header,
|
||||
ogg_read_packet,
|
||||
ogg_read_close,
|
||||
NULL,
|
||||
ogg_read_seek,
|
||||
ogg_read_timestamp,
|
||||
.extensions = "ogg",
|
||||
.metadata_conv = ff_vorbiscomment_metadata_conv,
|
||||
|
@ -75,6 +75,7 @@ struct ogg_stream {
|
||||
uint8_t segments[255];
|
||||
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 keyframe_seek;
|
||||
void *private;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user