changeset 5434:68c8e7affd44 libavformat

Fix PTS for OGM codecs. Fixes issue251
author conrad
date Sat, 12 Dec 2009 20:18:43 +0000
parents 3e568c0b36d3
children d6371dd2bec4
files oggdec.c oggdec.h oggparseogm.c oggparsespeex.c
diffstat 4 files changed, 45 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/oggdec.c	Sat Dec 12 15:26:33 2009 +0000
+++ b/oggdec.c	Sat Dec 12 20:18:43 2009 +0000
@@ -116,7 +116,7 @@
         os->pstart = 0;
         os->psize = 0;
         os->granule = -1;
-        os->lastgp = -1;
+        os->lastpts = AV_NOPTS_VALUE;
         os->nsegs = 0;
         os->segp = 0;
     }
@@ -288,7 +288,6 @@
     if (get_buffer (bc, os->buf + os->bufpos, size) < size)
         return -1;
 
-    os->lastgp = os->granule;
     os->bufpos += size;
     os->granule = gp;
     os->flags = flags;
@@ -303,7 +302,7 @@
 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
 {
     struct ogg *ogg = s->priv_data;
-    int idx;
+    int idx, i;
     struct ogg_stream *os;
     int complete = 0;
     int segp = 0, psize = 0;
@@ -393,6 +392,15 @@
         os->psize = 0;
     }
 
+    // determine whether there are more complete packets in this page
+    // if not, the page's granule will apply to this packet
+    os->page_end = 1;
+    for (i = os->segp; i < os->nsegs; i++)
+        if (os->segments[i] < 255) {
+            os->page_end = 0;
+            break;
+        }
+
     os->seq++;
     if (os->segp == os->nsegs)
         ogg->curidx = -1;
@@ -519,9 +527,20 @@
         return AVERROR(EIO);
     pkt->stream_index = idx;
     memcpy (pkt->data, os->buf + pstart, psize);
-    if (os->lastgp != -1LL){
-        pkt->pts = ogg_gptopts (s, idx, os->lastgp);
-        os->lastgp = -1;
+
+    if (os->lastpts != AV_NOPTS_VALUE) {
+        pkt->pts = os->lastpts;
+        os->lastpts = 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);
+            else
+                os->lastpts = ogg_gptopts(s, idx, os->granule);
+            os->granule = -1LL;
+        } else
+            av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
     }
 
     pkt->flags = os->pflags;
--- a/oggdec.h	Sat Dec 12 15:26:33 2009 +0000
+++ b/oggdec.h	Sat Dec 12 20:18:43 2009 +0000
@@ -41,6 +41,11 @@
     int (*header)(AVFormatContext *, int);
     int (*packet)(AVFormatContext *, int);
     uint64_t (*gptopts)(AVFormatContext *, int, uint64_t);
+    /**
+     * 1 if granule is the start time of the associated packet.
+     * 0 if granule is the end time of the associated packet.
+     */
+    int granule_is_start;
 };
 
 struct ogg_stream {
@@ -53,12 +58,14 @@
     unsigned int pduration;
     uint32_t serial;
     uint32_t seq;
-    uint64_t granule, lastgp;
+    uint64_t granule;
+    int64_t lastpts;
     int flags;
     const struct ogg_codec *codec;
     int header;
     int nsegs, segp;
     uint8_t segments[255];
+    int page_end;   ///< current packet is the last one completed in the page
     void *private;
 };
 
--- a/oggparseogm.c	Sat Dec 12 15:26:33 2009 +0000
+++ b/oggparseogm.c	Sat Dec 12 20:18:43 2009 +0000
@@ -153,26 +153,30 @@
     .magic = "\001video",
     .magicsize = 6,
     .header = ogm_header,
-    .packet = ogm_packet
+    .packet = ogm_packet,
+    .granule_is_start = 1,
 };
 
 const struct ogg_codec ff_ogm_audio_codec = {
     .magic = "\001audio",
     .magicsize = 6,
     .header = ogm_header,
-    .packet = ogm_packet
+    .packet = ogm_packet,
+    .granule_is_start = 1,
 };
 
 const struct ogg_codec ff_ogm_text_codec = {
     .magic = "\001text",
     .magicsize = 5,
     .header = ogm_header,
-    .packet = ogm_packet
+    .packet = ogm_packet,
+    .granule_is_start = 1,
 };
 
 const struct ogg_codec ff_ogm_old_codec = {
     .magic = "\001Direct Show Samples embedded in Ogg",
     .magicsize = 35,
     .header = ogm_dshow_header,
-    .packet = ogm_packet
+    .packet = ogm_packet,
+    .granule_is_start = 1,
 };
--- a/oggparsespeex.c	Sat Dec 12 15:26:33 2009 +0000
+++ b/oggparsespeex.c	Sat Dec 12 20:18:43 2009 +0000
@@ -95,15 +95,16 @@
         os->private = spxp;
     }
 
-    if (os->flags & OGG_FLAG_EOS && os->lastgp != -1 && os->granule > 0) {
+    if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE &&
+        os->granule > 0) {
         /* first packet of final page. we have to calculate the final packet
            duration here because it is the only place we know the next-to-last
            granule position. */
-        spxp->final_packet_duration = os->granule - os->lastgp -
+        spxp->final_packet_duration = os->granule - os->lastpts -
                                       packet_size * (ogg_page_packets(os) - 1);
     }
 
-    if (!os->lastgp && os->granule > 0)
+    if (!os->lastpts && os->granule > 0)
         /* first packet */
         os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1);
     else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs &&