[FFmpeg-devel] [PATCH v2] libavcodec/mpeg12dec.c: append CC data to a53_buf_ref

Scott Theisen scott.the.elm at gmail.com
Sat Dec 14 23:49:16 EET 2024


In mpeg_decode_a53_cc() only the A/53 part 4 CC data ("GA94") is saved between
frames.  The other formats incorrectly created a larger buffer than they use
since a705bcd763e344fac191e157ffeddc285388b7fa because they did not append to
the previous data.

A/53 and SCTE-20 specify a maximum of one CC user data per picture header.
(I assume the same is true for DVD and DVB 0502.)

The a53_buf_ref is added to the frame in mpeg_field_start() which will only be
called in decode_chunks() if not all of the picture data slices are skipped.

I have observed the A/53 code create a larger buffer at the start of a file or
after skipping; presumably the I-frame following a GOP header is the first
frame, then one or more B-frames have all of their slices skipped.  Otherwise,
old_size is always 0.
---
 libavcodec/mpeg12dec.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 208ee28b04..3ab626accd 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1971,9 +1971,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
             ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
             if (ret >= 0) {
                 uint8_t field, cc1, cc2;
-                uint8_t *cap = s1->a53_buf_ref->data;
+                uint8_t *cap = s1->a53_buf_ref->data + old_size;
 
-                memset(s1->a53_buf_ref->data + old_size, 0, cc_count * 3);
+                memset(cap, 0, cc_count * 3);
                 for (i = 0; i < cc_count && get_bits_left(&gb) >= 26; i++) {
                     skip_bits(&gb, 2); // priority
                     field = get_bits(&gb, 2);
@@ -2043,7 +2043,7 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
             ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
             if (ret >= 0) {
                 uint8_t field1 = !!(p[4] & 0x80);
-                uint8_t *cap = s1->a53_buf_ref->data;
+                uint8_t *cap = s1->a53_buf_ref->data + old_size;
                 p += 5;
                 for (i = 0; i < cc_count; i++) {
                     cap[0] = (p[0] == 0xff && field1) ? 0xfc : 0xfd;
@@ -2109,13 +2109,14 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
 
             ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
             if (ret >= 0) {
-                s1->a53_buf_ref->data[0] = cc_header;
-                s1->a53_buf_ref->data[1] = cc_data[0];
-                s1->a53_buf_ref->data[2] = cc_data[1];
+                uint8_t* cap = s1->a53_buf_ref->data + old_size;
+                cap[0] = cc_header;
+                cap[1] = cc_data[0];
+                cap[2] = cc_data[1];
                 if (cc_count == 2) {
-                    s1->a53_buf_ref->data[3] = cc_header;
-                    s1->a53_buf_ref->data[4] = cc_data[2];
-                    s1->a53_buf_ref->data[5] = cc_data[3];
+                    cap[3] = cc_header;
+                    cap[4] = cc_data[2];
+                    cap[5] = cc_data[3];
                 }
             }
 
-- 
2.43.0



More information about the ffmpeg-devel mailing list