|
|
|
@ -66,7 +66,8 @@ enum Mpeg2ClosedCaptionsFormat { |
|
|
|
|
CC_FORMAT_AUTO, |
|
|
|
|
CC_FORMAT_A53_PART4, |
|
|
|
|
CC_FORMAT_SCTE20, |
|
|
|
|
CC_FORMAT_DVD |
|
|
|
|
CC_FORMAT_DVD, |
|
|
|
|
CC_FORMAT_DVB_0502 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
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_DVB_0502) && |
|
|
|
|
buf_size >= 12 && |
|
|
|
|
p[0] == 0x05 && p[1] == 0x02) { |
|
|
|
|
/* extract DVB 0502 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_DVB_0502, "DVB 0502"); |
|
|
|
|
} |
|
|
|
|
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" }, |
|
|
|
|
{ "dvb_0502", "pick DVB 0502 CC substream", 0, AV_OPT_TYPE_CONST, |
|
|
|
|
{ .i64 = CC_FORMAT_DVB_0502 }, .flags = M2V_PARAM, .unit = "cc_format" }, |
|
|
|
|
{ NULL } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|