]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mov.c
avformat/mov: Avoid allocation when reading ddts atom
[ffmpeg] / libavformat / mov.c
index 4e68532b69c40ade6f6f370f3870ed82c85d476a..6b464a8f6ed6afd4ae8c53b66a124c8f098eb283 100644 (file)
@@ -181,7 +181,6 @@ static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
 
 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
 {
-    AVPacket pkt;
     AVStream *st;
     MOVStreamContext *sc;
     enum AVCodecID id;
@@ -205,12 +204,12 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
         return AVERROR(ENOMEM);
     st->priv_data = sc;
 
-    ret = av_get_packet(pb, &pkt, len);
+    ret = av_get_packet(pb, &st->attached_pic, len);
     if (ret < 0)
         return ret;
 
-    if (pkt.size >= 8 && id != AV_CODEC_ID_BMP) {
-        if (AV_RB64(pkt.data) == 0x89504e470d0a1a0a) {
+    if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
+        if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
             id = AV_CODEC_ID_PNG;
         } else {
             id = AV_CODEC_ID_MJPEG;
@@ -219,7 +218,6 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
 
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
 
-    st->attached_pic              = pkt;
     st->attached_pic.stream_index = st->index;
     st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
 
@@ -859,26 +857,20 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
-    const uint32_t ddts_size = 20;
+#define DDTS_SIZE 20
+    uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
     AVStream *st = NULL;
-    uint8_t *buf = NULL;
     uint32_t frame_duration_code = 0;
     uint32_t channel_layout_code = 0;
     GetBitContext gb;
+    int ret;
 
-    buf = av_malloc(ddts_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!buf) {
-        return AVERROR(ENOMEM);
-    }
-    if (avio_read(pb, buf, ddts_size) < ddts_size) {
-        av_free(buf);
-        return AVERROR_INVALIDDATA;
-    }
+    if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
+        return ret;
 
-    init_get_bits(&gb, buf, 8*ddts_size);
+    init_get_bits(&gb, buf, 8 * DDTS_SIZE);
 
     if (c->fc->nb_streams < 1) {
-        av_free(buf);
         return 0;
     }
     st = c->fc->streams[c->fc->nb_streams-1];
@@ -886,7 +878,6 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     st->codecpar->sample_rate = get_bits_long(&gb, 32);
     if (st->codecpar->sample_rate <= 0) {
         av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
-        av_free(buf);
         return AVERROR_INVALIDDATA;
     }
     skip_bits_long(&gb, 32); /* max bitrate */
@@ -914,7 +905,6 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0);
 
     st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
-    av_free(buf);
 
     return 0;
 }
@@ -2342,18 +2332,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
                 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
                 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
                     uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
-                    if (str_size > 0 && size >= (int)str_size + 30) {
+                    if (str_size > 0 && size >= (int)str_size + 30 &&
+                        st->codecpar->extradata[30] /* Don't add empty string */) {
                         char *reel_name = av_malloc(str_size + 1);
                         if (!reel_name)
                             return AVERROR(ENOMEM);
                         memcpy(reel_name, st->codecpar->extradata + 30, str_size);
                         reel_name[str_size] = 0; /* Add null terminator */
-                        /* don't add reel_name if emtpy string */
-                        if (*reel_name == 0) {
-                            av_free(reel_name);
-                        } else {
-                            av_dict_set(&st->metadata, "reel_name", reel_name,  AV_DICT_DONT_STRDUP_VAL);
-                        }
+                        av_dict_set(&st->metadata, "reel_name", reel_name,
+                                    AV_DICT_DONT_STRDUP_VAL);
                     }
                 }
             }
@@ -2550,11 +2537,8 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
 
             /* Move the current stream extradata to the stream context one. */
             sc->extradata_size[pseudo_stream_id] = extra_size;
-            sc->extradata[pseudo_stream_id] = av_malloc(extra_size + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!sc->extradata[pseudo_stream_id])
-                return AVERROR(ENOMEM);
-            memcpy(sc->extradata[pseudo_stream_id], st->codecpar->extradata, extra_size);
-            av_freep(&st->codecpar->extradata);
+            sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
+            st->codecpar->extradata      = NULL;
             st->codecpar->extradata_size = 0;
         }
         sc->stsd_count++;
@@ -5773,12 +5757,9 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     st = c->fc->streams[c->fc->nb_streams - 1];
     sc = st->priv_data;
 
-    ret = avio_read(pb, uuid, sizeof(uuid));
-    if (ret < 0) {
+    ret = ffio_read_size(pb, uuid, sizeof(uuid));
+    if (ret < 0)
         return ret;
-    } else if (ret != sizeof(uuid)) {
-        return AVERROR_INVALIDDATA;
-    }
     if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
         uint8_t *buffer, *ptr;
         char *endptr;
@@ -5794,13 +5775,10 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         if (!buffer) {
             return AVERROR(ENOMEM);
         }
-        ret = avio_read(pb, buffer, len);
+        ret = ffio_read_size(pb, buffer, len);
         if (ret < 0) {
             av_free(buffer);
             return ret;
-        } else if (ret != len) {
-            av_free(buffer);
-            return AVERROR_INVALIDDATA;
         }
 
         ptr = buffer;
@@ -5831,13 +5809,10 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             if (!buffer) {
                 return AVERROR(ENOMEM);
             }
-            ret = avio_read(pb, buffer, len);
+            ret = ffio_read_size(pb, buffer, len);
             if (ret < 0) {
                 av_free(buffer);
                 return ret;
-            } else if (ret != len) {
-                av_free(buffer);
-                return AVERROR_INVALIDDATA;
             }
             buffer[len] = '\0';
             av_dict_set(&c->fc->metadata, "xmp",
@@ -5981,7 +5956,7 @@ static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encry
 
 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
 {
-    int i;
+    int i, ret;
     unsigned int subsample_count;
     AVSubsampleEncryptionInfo *subsamples;
 
@@ -5995,11 +5970,11 @@ static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVSt
         return AVERROR(ENOMEM);
 
     if (sc->cenc.per_sample_iv_size != 0) {
-        if (avio_read(pb, (*sample)->iv, sc->cenc.per_sample_iv_size) != sc->cenc.per_sample_iv_size) {
+        if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
             av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
             av_encryption_info_free(*sample);
             *sample = NULL;
-            return AVERROR_INVALIDDATA;
+            return ret;
         }
     }
 
@@ -6367,9 +6342,8 @@ static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if (!info)
         return AVERROR(ENOMEM);
 
-    if (avio_read(pb, info->system_id, 16) != 16) {
+    if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
         av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
-        ret = AVERROR_INVALIDDATA;
         goto finish;
     }
 
@@ -6397,9 +6371,8 @@ static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             }
             info->num_key_ids = i + 1;
 
-            if (avio_read(pb, info->key_ids[i], 16) != 16) {
+            if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
                 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
-                ret = AVERROR_INVALIDDATA;
                 goto finish;
             }
         }
@@ -7187,17 +7160,15 @@ static void mov_read_chapters(AVFormatContext *s)
             st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
             if (st->nb_index_entries) {
                 // Retrieve the first frame, if possible
-                AVPacket pkt;
                 AVIndexEntry *sample = &st->index_entries[0];
                 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
                     av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
                     goto finish;
                 }
 
-                if (av_get_packet(sc->pb, &pkt, sample->size) < 0)
+                if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0)
                     goto finish;
 
-                st->attached_pic              = pkt;
                 st->attached_pic.stream_index = st->index;
                 st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
             }
@@ -7858,6 +7829,27 @@ static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt)
     return 0;
 }
 
+static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
+{
+    int new_size, ret;
+
+    if (size <= 8)
+        return AVERROR_INVALIDDATA;
+    new_size = ((size - 8) / 2) * 3;
+    ret = av_new_packet(pkt, new_size);
+    if (ret < 0)
+        return ret;
+
+    avio_skip(pb, 8);
+    for (int j = 0; j < new_size; j += 3) {
+        pkt->data[j] = 0xFC;
+        pkt->data[j+1] = avio_r8(pb);
+        pkt->data[j+2] = avio_r8(pb);
+    }
+
+    return 0;
+}
+
 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     MOVContext *mov = s->priv_data;
@@ -7902,6 +7894,9 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
             goto retry;
         }
 
+        if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
+            ret = get_eia608_packet(sc->pb, pkt, sample->size);
+        else
         ret = av_get_packet(sc->pb, pkt, sample->size);
         if (ret < 0) {
             if (should_retry(sc->pb, ret)) {