]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/oggparsevorbis.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / oggparsevorbis.c
index f762c940f0a3ec929ccc77a8d313d973094119a3..38eb4b0b1c80c6f2cce15a230b08a2aff94d6ea9 100644 (file)
@@ -203,12 +203,12 @@ vorbis_header (AVFormatContext * s, int idx)
     int pkt_type = os->buf[os->pstart];
 
     if (!(pkt_type & 1))
-        return 0;
+        return os->private ? 0 : -1;
 
     if (!os->private) {
         os->private = av_mallocz(sizeof(struct oggvorbis_private));
         if (!os->private)
-            return 0;
+            return -1;
     }
 
     if (os->psize < 1 || pkt_type > 5)
@@ -223,6 +223,8 @@ vorbis_header (AVFormatContext * s, int idx)
 
     priv->len[pkt_type >> 1] = os->psize;
     priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
+    if (!priv->packet[pkt_type >> 1])
+        return AVERROR(ENOMEM);
     memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
     if (os->buf[os->pstart] == 1) {
         const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
@@ -296,33 +298,39 @@ static int vorbis_packet(AVFormatContext *s, int idx)
        here we parse the duration of each packet in the first page and compare
        the total duration to the page granule to find the encoder delay and
        set the first timestamp */
-    if (!os->lastpts) {
-        int seg;
+    if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
+        int seg, d;
         uint8_t *last_pkt = os->buf + os->pstart;
         uint8_t *next_pkt = last_pkt;
-        int first_duration = 0;
 
         avpriv_vorbis_parse_reset(&priv->vp);
         duration = 0;
-        for (seg = 0; seg < os->nsegs; seg++) {
+        seg = os->segp;
+        d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
+        if (d < 0) {
+            os->pflags |= AV_PKT_FLAG_CORRUPT;
+            return 0;
+        }
+        duration += d;
+        last_pkt = next_pkt =  next_pkt + os->psize;
+        for (; seg < os->nsegs; seg++) {
             if (os->segments[seg] < 255) {
                 int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
                 if (d < 0) {
                     duration = os->granule;
                     break;
                 }
-                if (!duration)
-                    first_duration = d;
                 duration += d;
                 last_pkt = next_pkt + os->segments[seg];
             }
             next_pkt += os->segments[seg];
         }
         os->lastpts = os->lastdts   = os->granule - duration;
-        s->streams[idx]->start_time = os->lastpts + first_duration;
-        if (s->streams[idx]->duration)
-            s->streams[idx]->duration -= s->streams[idx]->start_time;
-        s->streams[idx]->cur_dts    = AV_NOPTS_VALUE;
+        if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
+            s->streams[idx]->start_time = FFMAX(os->lastpts, 0);
+            if (s->streams[idx]->duration)
+                s->streams[idx]->duration -= s->streams[idx]->start_time;
+        }
         priv->final_pts             = AV_NOPTS_VALUE;
         avpriv_vorbis_parse_reset(&priv->vp);
     }
@@ -330,7 +338,7 @@ static int vorbis_packet(AVFormatContext *s, int idx)
     /* parse packet duration */
     if (os->psize > 0) {
         duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
-        if (duration <= 0) {
+        if (duration < 0) {
             os->pflags |= AV_PKT_FLAG_CORRUPT;
             return 0;
         }