[FFmpeg-devel] [PATCH] avformat/matroskadec: Output palette as stream side data

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Thu Oct 5 15:36:52 EEST 2023


This is simpler implementation-wise (it avoids an almost-always-false
check in read_packet and decreases sizeof(MatroskaTrack) by about 2/3)
and makes the side-data available directly after read_header.

It also fixes the Matroska analog of ticket #10602: If a Matroska track
has a palette, said palette will be attached as side-data to the
first packet of said track and most likely, this is one read during
avformat_find_stream_info(). Yet if this packet is discarded because
of a seek performed immediately after avformat_find_stream_info(),
the information about the global palette will never reach the user.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
Ticket #10602 can unfortunately not be fixed in this way,
because avi allows to update the palette mid-stream,
so that the palette contained in extradata must not be
exported via global side data due to the semantics of the latter.

 libavformat/matroskadec.c | 39 ++++++++++++---------------------------
 1 file changed, 12 insertions(+), 27 deletions(-)

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 941c0bcdc9..74f3fc7ae7 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -285,9 +285,6 @@ typedef struct MatroskaTrack {
     int needs_decoding;
     uint64_t max_block_additional_id;
     EbmlList block_addition_mappings;
-
-    uint32_t palette[AVPALETTE_COUNT];
-    int has_palette;
 } MatroskaTrack;
 
 typedef struct MatroskaAttachment {
@@ -2852,7 +2849,8 @@ static int mka_parse_audio(MatroskaTrack *track, AVStream *st,
 }
 
 /* Performs the codec-specific part of parsing a video track. */
-static int mkv_parse_video_codec(MatroskaTrack *track, AVCodecParameters *par,
+static int mkv_parse_video_codec(AVStream *st, MatroskaTrack *track,
+                                 AVCodecParameters *par,
                                  const MatroskaDemuxContext *matroska,
                                  int *extradata_offset)
 {
@@ -2886,11 +2884,15 @@ static int mkv_parse_video_codec(MatroskaTrack *track, AVCodecParameters *par,
         if (track->codec_priv.size >= 86) {
             FFIOContext b;
             unsigned bit_depth = AV_RB16(track->codec_priv.data + 82);
+            uint32_t palette[256] = { 0 };
             ffio_init_read_context(&b, track->codec_priv.data,
                                    track->codec_priv.size);
-            if (ff_get_qtpalette(codec_id, &b.pub, track->palette)) {
+            if (ff_get_qtpalette(codec_id, &b.pub, palette)) {
+                void *side_data = av_stream_new_side_data(st, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
+                if (!side_data)
+                    return AVERROR(ENOMEM);
+                memcpy(side_data, palette, AVPALETTE_SIZE);
                 bit_depth         &= 0x1F;
-                track->has_palette = 1;
             }
             par->bits_per_coded_sample = bit_depth;
         }
@@ -2934,7 +2936,7 @@ static int mkv_parse_video(MatroskaTrack *track, AVStream *st,
     if (track->video.color_space.size == 4)
         par->codec_tag = AV_RL32(track->video.color_space.data);
 
-    ret = mkv_parse_video_codec(track, par, matroska,
+    ret = mkv_parse_video_codec(st, track, par, matroska,
                                 extradata_offset);
     if (ret < 0)
         return ret;
@@ -3398,30 +3400,13 @@ static int matroska_read_header(AVFormatContext *s)
 
 /*
  * Put one packet in an application-supplied AVPacket struct.
- * Returns 0 on success or -1 on failure.
+ * Returns 0 on success or < 0 (most likely AVERROR(EAGAIN)
+ * if no packet was available.
  */
 static int matroska_deliver_packet(MatroskaDemuxContext *matroska,
                                    AVPacket *pkt)
 {
-    if (matroska->queue.head) {
-        MatroskaTrack *tracks = matroska->tracks.elem;
-        MatroskaTrack *track;
-
-        avpriv_packet_list_get(&matroska->queue, pkt);
-        track = &tracks[pkt->stream_index];
-        if (track->has_palette) {
-            uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
-            if (!pal) {
-                av_log(matroska->ctx, AV_LOG_ERROR, "Cannot append palette to packet\n");
-            } else {
-                memcpy(pal, track->palette, AVPALETTE_SIZE);
-            }
-            track->has_palette = 0;
-        }
-        return 0;
-    }
-
-    return -1;
+    return avpriv_packet_list_get(&matroska->queue, pkt);
 }
 
 /*
-- 
2.34.1



More information about the ffmpeg-devel mailing list