[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