[FFmpeg-devel] [PATCH] libavcodec/mpeg12dec.c: add CC format for user_data 0x05 0x02

Scott Theisen scott.the.elm at gmail.com
Thu Nov 14 07:28:39 EET 2024


Originally from:
Fixes #2481, by applying patch from kenny at the-b org. This adds dec…
https://github.com/MythTV/mythtv/commit/49d3294c9a4ef20a699c2bb2da08f33b294c86b3

Referencing:
Trac #2481 (Closed Captioning contained in MPEG user data fields) – MythTV
https://code.mythtv.org/trac/ticket/2481

Modified in:
Simplify DTV CEA-608 handling a bit & add some range checking.
https://github.com/MythTV/mythtv/commit/be6a2b4e4b90717924aea69f09baf49b168b745a

Some tweaks to cc implementation in mpeg12.c: make the C ANSI compati…
https://github.com/MythTV/mythtv/commit/77cff32fb074d974b8e10361834efece3694f00f

See also:
https://github.com/CCExtractor/ccextractor/blob/master/src/lib_ccx/es_userdata.c
---
 libavcodec/mpeg12dec.c | 67 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index c0ed6a9d5b..e1503a9df8 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -66,7 +66,8 @@ enum Mpeg2ClosedCaptionsFormat {
     CC_FORMAT_AUTO,
     CC_FORMAT_A53_PART4,
     CC_FORMAT_SCTE20,
-    CC_FORMAT_DVD
+    CC_FORMAT_DVD,
+    CC_FORMAT_DISH
 };
 
 typedef struct Mpeg1Context {
@@ -2059,6 +2060,68 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
             mpeg_set_cc_format(avctx, CC_FORMAT_DVD, "DVD");
         }
         return 1;
+    } else if ((!s1->cc_format || s1->cc_format == CC_FORMAT_DISH) &&
+               buf_size >= 12 &&
+               p[0] == 0x05 && p[1] == 0x02) {
+        /* extract Dish Network DVB CC data */
+        const uint8_t cc_header = 0xf8 | 0x04 /* valid */ | 0x00 /* line 21 field 1 */;
+        uint8_t cc_data[4] = {0};
+        int cc_count = 0;
+        uint8_t dvb_cc_type = p[7];
+        p += 8;
+        buf_size -= 8;
+
+        if (dvb_cc_type == 0x05 && buf_size >= 7) {
+            dvb_cc_type = p[6];
+            p += 7;
+            buf_size -= 7;
+        }
+
+        if (dvb_cc_type == 0x02 && buf_size >= 4) { /* 2-byte caption, can be repeated */
+            cc_count = 1;
+            cc_data[0] = p[1];
+            cc_data[1] = p[2];
+            dvb_cc_type = p[3];
+
+            /* Only repeat characters when the next type flag
+             * is 0x04 and the characters are repeatable (i.e., less than
+             * 32 with the parity stripped).
+             */
+            if (dvb_cc_type == 0x04 && (cc_data[0] & 0x7f) < 32) {
+                cc_count = 2;
+                cc_data[2] = cc_data[0];
+                cc_data[3] = cc_data[1];
+            }
+        } else if (dvb_cc_type == 0x04 && buf_size >= 5) { /* 4-byte caption, not repeated */
+            cc_count = 2;
+            cc_data[0] = p[1];
+            cc_data[1] = p[2];
+            cc_data[2] = p[3];
+            cc_data[3] = p[4];
+        }
+
+        if (cc_count > 0) {
+            int ret;
+            int old_size = s1->a53_buf_ref ? s1->a53_buf_ref->size : 0;
+            const uint64_t new_size = (old_size + cc_count * UINT64_C(3));
+            if (new_size > 3 * A53_MAX_CC_COUNT)
+                return AVERROR(EINVAL);
+
+            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];
+                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];
+                }
+            }
+
+            mpeg_set_cc_format(avctx, CC_FORMAT_DISH, "Dish Network DVB");
+        }
+        return 1;
     }
     return 0;
 }
@@ -2629,6 +2692,8 @@ static const AVOption mpeg2video_options[] = {
         { .i64 =   CC_FORMAT_SCTE20 },              .flags = M2V_PARAM, .unit = "cc_format" },
        { "dvd",    "pick DVD CC substream",         0, AV_OPT_TYPE_CONST,
         { .i64 =   CC_FORMAT_DVD },                 .flags = M2V_PARAM, .unit = "cc_format" },
+       { "dish",   "pick Dish Network DVB CC substream", 0, AV_OPT_TYPE_CONST,
+        { .i64 =   CC_FORMAT_DISH },                 .flags = M2V_PARAM, .unit = "cc_format" },
     { NULL }
 };
 
-- 
2.43.0



More information about the ffmpeg-devel mailing list