diff mbox series

[FFmpeg-devel,04/20] avformat/matroskadec: Redo handling extradata allocation

Message ID AS8P250MB074422E739036D97D081CA6D8FE9A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM
State Accepted
Commit 7c95dbd94e7982ed9188ab91e3497c1fc2714c09
Headers show
Series [FFmpeg-devel,01/20] fate/matroska: Add test for remuxing non-rotation displaymatrix | expand

Commit Message

Andreas Rheinhardt Sept. 4, 2023, 11:27 a.m. UTC
Up until now, matroska_parse_tracks() has two main ways
to set AVCodecParameters.extradata: A generic way via CodecPrivate
(possibly with an offset) and by allocating a buffer manually;
the pointer to this buffer is stored in a stack pointer.

In particular, the latter method is problematic, as the buffer
needs to be freed manually in case of error (currently there
are no error conditions between the place where it is set
to AVCodecParameters.extradata).

Most of these buffers are very small (<= 22B), so replace
the pointer to an allocated buffer with a stack buffer
and set the extradata directly for the one place where
the buffer may not be small.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavformat/matroskadec.c | 60 ++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 33 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index fd28ff8ab2..50a159460d 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2501,6 +2501,10 @@  static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *
     return 0;
 }
 
+#define AAC_MAX_EXTRADATA_SIZE     5
+#define TTA_EXTRADATA_SIZE        22
+#define WAVPACK_EXTRADATA_SIZE     2
+
 static int matroska_parse_tracks(AVFormatContext *s)
 {
     MatroskaDemuxContext *matroska = s->priv_data;
@@ -2514,8 +2518,10 @@  static int matroska_parse_tracks(AVFormatContext *s)
         EbmlList *encodings_list = &track->encodings;
         MatroskaTrackEncoding *encodings = encodings_list->elem;
         AVCodecParameters *par;
-        uint8_t *extradata = NULL;
-        int extradata_size = 0;
+        uint8_t extradata[FFMAX3(AAC_MAX_EXTRADATA_SIZE,
+                                 TTA_EXTRADATA_SIZE,
+                                 WAVPACK_EXTRADATA_SIZE)];
+        int extradata_size = 0; // > 0 means that the extradata buffer is used
         int extradata_offset = 0;
         uint32_t fourcc = 0;
         FFIOContext b;
@@ -2795,9 +2801,7 @@  static int matroska_parse_tracks(AVFormatContext *s)
         } else if (codec_id == AV_CODEC_ID_AAC && !track->codec_priv.size) {
             int profile = matroska_aac_profile(track->codec_id);
             int sri     = matroska_aac_sri(track->audio.samplerate);
-            extradata   = av_mallocz(5 + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!extradata)
-                return AVERROR(ENOMEM);
+
             extradata[0] = (profile << 3) | ((sri & 0x0E) >> 1);
             extradata[1] = ((sri & 0x01) << 7) | (track->audio.channels << 3);
             if (strstr(track->codec_id, "SBR")) {
@@ -2812,15 +2816,13 @@  static int matroska_parse_tracks(AVFormatContext *s)
             /* Only ALAC's magic cookie is stored in Matroska's track headers.
              * Create the "atom size", "tag", and "tag version" fields the
              * decoder expects manually. */
-            extradata_size = 12 + track->codec_priv.size;
-            extradata      = av_mallocz(extradata_size +
-                                        AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!extradata)
-                return AVERROR(ENOMEM);
-            AV_WB32(extradata, extradata_size);
-            memcpy(&extradata[4], "alac", 4);
-            AV_WB32(&extradata[8], 0);
-            memcpy(&extradata[12], track->codec_priv.data,
+            ret = ff_alloc_extradata(par, 12 + track->codec_priv.size);
+            if (ret < 0)
+                return ret;
+            AV_WB32(par->extradata, par->extradata_size);
+            AV_WB32(&par->extradata[4], MKBETAG('a', 'l', 'a', 'c'));
+            AV_WB32(&par->extradata[8], 0);
+            memcpy(&par->extradata[12], track->codec_priv.data,
                    track->codec_priv.size);
         } else if (codec_id == AV_CODEC_ID_TTA) {
             uint8_t *ptr;
@@ -2837,10 +2839,7 @@  static int matroska_parse_tracks(AVFormatContext *s)
             }
             if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX)
                 return AVERROR_INVALIDDATA;
-            extradata_size = 22;
-            extradata      = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!extradata)
-                return AVERROR(ENOMEM);
+            extradata_size = TTA_EXTRADATA_SIZE;
             ptr = extradata;
             bytestream_put_be32(&ptr, AV_RB32("TTA1"));
             bytestream_put_le16(&ptr, 1);
@@ -2910,10 +2909,7 @@  static int matroska_parse_tracks(AVFormatContext *s)
         } else if (codec_id == AV_CODEC_ID_WAVPACK && track->codec_priv.size < 2) {
             av_log(matroska->ctx, AV_LOG_INFO, "Assuming WavPack version 4.10 "
                    "in absence of valid CodecPrivate.\n");
-            extradata_size = 2;
-            extradata = av_mallocz(2 + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!extradata)
-                return AVERROR(ENOMEM);
+            extradata_size = WAVPACK_EXTRADATA_SIZE;
             AV_WL16(extradata, 0x410);
         } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) {
             fourcc = AV_RL32(track->codec_priv.data);
@@ -2959,17 +2955,15 @@  static int matroska_parse_tracks(AVFormatContext *s)
 
         par->codec_id = codec_id;
 
-        if (!par->extradata) {
-            if (extradata) {
-                par->extradata      = extradata;
-                par->extradata_size = extradata_size;
-            } else if (track->codec_priv.data && track->codec_priv.size > 0) {
-                if (ff_alloc_extradata(par, track->codec_priv.size))
-                    return AVERROR(ENOMEM);
-                memcpy(par->extradata,
-                       track->codec_priv.data + extradata_offset,
-                       track->codec_priv.size);
-            }
+        if (!par->extradata && (extradata_size > 0 || track->codec_priv.size > 0)) {
+            const uint8_t *src = extradata_size > 0 ? extradata :
+                                     track->codec_priv.data + extradata_offset;
+            unsigned extra_size = extradata_size > 0 ? extradata_size :
+                                                       track->codec_priv.size;
+            ret = ff_alloc_extradata(par, extra_size);
+            if (ret < 0)
+                return ret;
+            memcpy(par->extradata, src, extra_size);
         }
 
         if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {