diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 33b453c584..26a6af20cb 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -119,6 +119,7 @@ ogg_reset (struct ogg * ogg) os->psize = 0; os->granule = -1; os->lastpts = AV_NOPTS_VALUE; + os->lastdts = AV_NOPTS_VALUE; os->nsegs = 0; os->segp = 0; } @@ -428,16 +429,18 @@ ogg_get_headers (AVFormatContext * s) } static uint64_t -ogg_gptopts (AVFormatContext * s, int i, uint64_t gp) +ogg_gptopts (AVFormatContext * s, int i, uint64_t gp, int64_t *dts) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + i; uint64_t pts = AV_NOPTS_VALUE; if(os->codec->gptopts){ - pts = os->codec->gptopts(s, i, gp); + pts = os->codec->gptopts(s, i, gp, dts); } else { pts = gp; + if (dts) + *dts = pts; } return pts; @@ -474,7 +477,7 @@ ogg_get_length (AVFormatContext * s) if (idx != -1){ s->streams[idx]->duration = - ogg_gptopts (s, idx, ogg->streams[idx].granule); + ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL); } ogg->size = size; @@ -534,12 +537,16 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt) pkt->pts = os->lastpts; os->lastpts = AV_NOPTS_VALUE; } + if (os->lastdts != AV_NOPTS_VALUE) { + pkt->dts = os->lastdts; + os->lastdts = AV_NOPTS_VALUE; + } if (os->page_end) { if (os->granule != -1LL) { if (os->codec && os->codec->granule_is_start) - pkt->pts = ogg_gptopts(s, idx, os->granule); + pkt->pts = ogg_gptopts(s, idx, os->granule, &pkt->dts); else - os->lastpts = ogg_gptopts(s, idx, os->granule); + os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts); os->granule = -1LL; } else av_log(s, AV_LOG_WARNING, "Packet is missing granule\n"); @@ -579,7 +586,7 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg, while (url_ftell(bc) < pos_limit && !ogg_read_page (s, &i)) { if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && ogg->streams[i].codec && i == stream_index) { - pts = ogg_gptopts(s, i, ogg->streams[i].granule); + pts = ogg_gptopts(s, i, ogg->streams[i].granule, NULL); // FIXME: this is the position of the packet after the one with above // pts. *pos_arg = url_ftell(bc); diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index 4db3fa6132..7c677a1de4 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -40,7 +40,12 @@ struct ogg_codec { */ int (*header)(AVFormatContext *, int); int (*packet)(AVFormatContext *, int); - uint64_t (*gptopts)(AVFormatContext *, int, uint64_t); + /** + * Translate a granule into a timestamp. + * Will set dts if non-null and known. + * @return pts + */ + uint64_t (*gptopts)(AVFormatContext *, int, uint64_t, int64_t *dts); /** * 1 if granule is the start time of the associated packet. * 0 if granule is the end time of the associated packet. @@ -60,6 +65,7 @@ struct ogg_stream { uint32_t seq; uint64_t granule; int64_t lastpts; + int64_t lastdts; int flags; const struct ogg_codec *codec; int header; diff --git a/libavformat/oggparsedirac.c b/libavformat/oggparsedirac.c index fc1a193205..5a907ec178 100644 --- a/libavformat/oggparsedirac.c +++ b/libavformat/oggparsedirac.c @@ -47,7 +47,8 @@ static int dirac_header(AVFormatContext *s, int idx) } // various undocument things: granule is signed (only for dirac!) -static uint64_t dirac_gptopts(AVFormatContext *s, int idx, int64_t gp) +static uint64_t dirac_gptopts(AVFormatContext *s, int idx, int64_t gp, + int64_t *dts_out) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -59,6 +60,9 @@ static uint64_t dirac_gptopts(AVFormatContext *s, int idx, int64_t gp) if (!dist) os->pflags |= PKT_FLAG_KEY; + if (dts_out) + *dts_out = dts; + return pts; } @@ -79,7 +83,8 @@ static int old_dirac_header(AVFormatContext *s, int idx) return 1; } -static uint64_t old_dirac_gptopts(AVFormatContext *s, int idx, uint64_t gp) +static uint64_t old_dirac_gptopts(AVFormatContext *s, int idx, uint64_t gp, + int64_t *dts) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index 0d74116d17..8b35a47224 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -123,7 +123,7 @@ theora_header (AVFormatContext * s, int idx) } static uint64_t -theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp) +theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts) { struct ogg *ogg = ctx->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -137,6 +137,9 @@ theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp) if(!pframe) os->pflags |= PKT_FLAG_KEY; + if (dts) + *dts = iframe + pframe; + return iframe + pframe; }