]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/asfdec.c
latm: Always reconfigure if no extradata was set previously
[ffmpeg] / libavformat / asfdec.c
index d4694310fc2338eb2275532417c0dde9cd49faf0..28a403aeb01c7e92b11584506748c9a0995a5bf5 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-//#define DEBUG
-
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/bswap.h"
 #include "libavutil/common.h"
 #include "libavutil/dict.h"
+#include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "avformat.h"
@@ -152,12 +151,6 @@ static void print_guid(ff_asf_guid *g)
 #define print_guid(g)
 #endif
 
-void ff_get_guid(AVIOContext *s, ff_asf_guid *g)
-{
-    assert(sizeof(*g) == 16);
-    avio_read(s, *g, sizeof(*g));
-}
-
 static int asf_probe(AVProbeData *pd)
 {
     /* check file header */
@@ -679,6 +672,7 @@ static int asf_read_metadata(AVFormatContext *s, int64_t size)
 static int asf_read_marker(AVFormatContext *s, int64_t size)
 {
     AVIOContext *pb = s->pb;
+    ASFContext *asf = s->priv_data;
     int i, count, name_len, ret;
     char name[1024];
 
@@ -696,6 +690,7 @@ static int asf_read_marker(AVFormatContext *s, int64_t size)
 
         avio_rl64(pb);             // offset, 8 bytes
         pres_time = avio_rl64(pb); // presentation time
+        pres_time -= asf->hdr.preroll * 10000;
         avio_rl16(pb);             // entry length
         avio_rl32(pb);             // send time
         avio_rl32(pb);             // flags
@@ -748,7 +743,9 @@ static int asf_read_header(AVFormatContext *s)
             if (ret < 0)
                 return ret;
         } else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
-            asf_read_stream_properties(s, gsize);
+            int ret = asf_read_stream_properties(s, gsize);
+            if (ret < 0)
+                return ret;
         } else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
             asf_read_content_desc(s, gsize);
         } else if (!ff_guidcmp(&g, &ff_asf_language_guid)) {
@@ -867,7 +864,7 @@ static int asf_read_header(AVFormatContext *s)
  * @param pb context to read data from
  * @return 0 on success, <0 on error
  */
-static int ff_asf_get_packet(AVFormatContext *s, AVIOContext *pb)
+static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
 {
     ASFContext *asf = s->priv_data;
     uint32_t packet_length, padsize;
@@ -1059,7 +1056,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb)
  * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF
  *          packets need to be loaded (through asf_get_packet())
  */
-static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
+static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
 {
     ASFContext *asf   = s->priv_data;
     ASFStream *asf_st = 0;
@@ -1106,6 +1103,16 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk
         asf_st = asf->asf_st;
         av_assert0(asf_st);
 
+        if (!asf_st->frag_offset && asf->packet_frag_offset) {
+            av_dlog(s, "skipping asf data pkt with fragment offset for "
+                    "stream:%d, expected:%d but got %d from pkt)\n",
+                    asf->stream_index, asf_st->frag_offset,
+                    asf->packet_frag_offset);
+            avio_skip(pb, asf->packet_frag_size);
+            asf->packet_size_left -= asf->packet_frag_size;
+            continue;
+        }
+
         if (asf->packet_replic_size == 1) {
             // frag_offset is here used as the beginning timestamp
             asf->packet_frag_timestamp = asf->packet_time_start;
@@ -1232,9 +1239,10 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk
                            asf_st->ds_span);
                 } else {
                     /* packet descrambling */
-                    uint8_t *newdata = av_malloc(asf_st->pkt.size +
-                                                 FF_INPUT_BUFFER_PADDING_SIZE);
-                    if (newdata) {
+                    AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size +
+                                                       FF_INPUT_BUFFER_PADDING_SIZE);
+                    if (buf) {
+                        uint8_t *newdata = buf->data;
                         int offset = 0;
                         memset(newdata + asf_st->pkt.size, 0,
                                FF_INPUT_BUFFER_PADDING_SIZE);
@@ -1250,13 +1258,20 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk
                                    asf_st->ds_chunk_size);
                             offset += asf_st->ds_chunk_size;
                         }
-                        av_free(asf_st->pkt.data);
-                        asf_st->pkt.data = newdata;
+                        av_buffer_unref(&asf_st->pkt.buf);
+                        asf_st->pkt.buf  = buf;
+                        asf_st->pkt.data = buf->data;
                     }
                 }
             }
             asf_st->frag_offset         = 0;
             *pkt                        = asf_st->pkt;
+#if FF_API_DESTRUCT_PACKET
+FF_DISABLE_DEPRECATION_WARNINGS
+            asf_st->pkt.destruct        = NULL;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+            asf_st->pkt.buf             = 0;
             asf_st->pkt.size            = 0;
             asf_st->pkt.data            = 0;
             asf_st->pkt.side_data_elems = 0;
@@ -1275,9 +1290,9 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
         int ret;
 
         /* parse cached packets, if any */
-        if ((ret = ff_asf_parse_packet(s, s->pb, pkt)) <= 0)
+        if ((ret = asf_parse_packet(s, s->pb, pkt)) <= 0)
             return ret;
-        if ((ret = ff_asf_get_packet(s, s->pb)) < 0)
+        if ((ret = asf_get_packet(s, s->pb)) < 0)
             assert(asf->packet_size_left < FRAME_HEADER_SIZE ||
                    asf->packet_segments < 1);
         asf->packet_time_start = 0;
@@ -1382,33 +1397,35 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
     return pts;
 }
 
-static void asf_build_simple_index(AVFormatContext *s, int stream_index)
+static int asf_build_simple_index(AVFormatContext *s, int stream_index)
 {
     ff_asf_guid g;
     ASFContext *asf     = s->priv_data;
     int64_t current_pos = avio_tell(s->pb);
-    int i;
+    int i, ret = 0;
 
     avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
-    ff_get_guid(s->pb, &g);
+    if ((ret = ff_get_guid(s->pb, &g)) < 0)
+        goto end;
 
     /* the data object can be followed by other top-level objects,
      * skip them until the simple index object is reached */
     while (ff_guidcmp(&g, &index_guid)) {
         int64_t gsize = avio_rl64(s->pb);
         if (gsize < 24 || s->pb->eof_reached) {
-            avio_seek(s->pb, current_pos, SEEK_SET);
-            return;
+            goto end;
         }
         avio_skip(s->pb, gsize - 24);
-        ff_get_guid(s->pb, &g);
+        if ((ret = ff_get_guid(s->pb, &g)) < 0)
+            goto end;
     }
 
     {
         int64_t itime, last_pos = -1;
         int pct, ict;
         int64_t av_unused gsize = avio_rl64(s->pb);
-        ff_get_guid(s->pb, &g);
+        if ((ret = ff_get_guid(s->pb, &g)) < 0)
+            goto end;
         itime = avio_rl64(s->pb);
         pct   = avio_rl32(s->pb);
         ict   = avio_rl32(s->pb);
@@ -1431,7 +1448,11 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
         }
         asf->index_read = ict > 0;
     }
+end:
+    if (s->pb->eof_reached)
+        ret = 0;
     avio_seek(s->pb, current_pos, SEEK_SET);
+    return ret;
 }
 
 static int asf_read_seek(AVFormatContext *s, int stream_index,
@@ -1440,7 +1461,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
     ASFContext *asf = s->priv_data;
     AVStream *st    = s->streams[stream_index];
     int64_t pos;
-    int index;
+    int index, ret = 0;
 
     if (s->packet_size <= 0)
         return -1;
@@ -1454,10 +1475,17 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
             return ret;
     }
 
+    /* explicitly handle the case of seeking to 0 */
+    if (!pts) {
+        asf_reset_header(s);
+        avio_seek(s->pb, s->data_offset, SEEK_SET);
+        return 0;
+    }
+
     if (!asf->index_read)
-        asf_build_simple_index(s, stream_index);
+        ret = asf_build_simple_index(s, stream_index);
 
-    if ((asf->index_read && st->index_entries)) {
+    if (!ret && asf->index_read && st->index_entries) {
         index = av_index_search_timestamp(st, pts, flags);
         if (index >= 0) {
             /* find the position */