hevc: extract SEI caption data

Signed-off-by: Will Kelleher <wkelleher@gogoair.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Will Kelleher 2015-11-06 14:48:46 -06:00 committed by Michael Niedermayer
parent 43492ff3ab
commit 7f7fa90f7b
3 changed files with 93 additions and 0 deletions

View File

@ -2566,6 +2566,16 @@ static int set_side_data(HEVCContext *s)
s->sei_hflip, s->sei_vflip);
}
if (s->a53_caption) {
AVFrameSideData* sd = av_frame_new_side_data(out,
AV_FRAME_DATA_A53_CC,
s->a53_caption_size);
if (sd)
memcpy(sd->data, s->a53_caption, s->a53_caption_size);
av_freep(&s->a53_caption);
s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
}
return 0;
}

View File

@ -937,6 +937,10 @@ typedef struct HEVCContext {
int sei_hflip, sei_vflip;
int picture_struct;
uint8_t* a53_caption;
int a53_caption_size;
} HEVCContext;
int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx,

View File

@ -146,6 +146,83 @@ static int decode_pic_timing(HEVCContext *s)
return 1;
}
static int decode_registered_user_data_closed_caption(HEVCContext *s, int size)
{
int flag;
int user_data_type_code;
int cc_count;
int i;
GetBitContext *gb = &s->HEVClc->gb;
if (size < 3)
return AVERROR(EINVAL);
user_data_type_code = get_bits(gb, 8);
if (user_data_type_code == 0x3) {
skip_bits(gb, 1); // reserved
flag = get_bits(gb, 1); // process_cc_data_flag
if (flag) {
skip_bits(gb, 1);
cc_count = get_bits(gb, 5);
skip_bits(gb, 8); // reserved
size -= 2;
if (cc_count && size >= cc_count * 3) {
av_freep(&s->a53_caption);
s->a53_caption_size = cc_count * 3;
s->a53_caption = av_malloc(s->a53_caption_size);
if (!s->a53_caption)
return(AVERROR(ENOMEM));
for (i = 0; i < s->a53_caption_size; i++) {
s->a53_caption[i++] = get_bits(gb, 8);
}
skip_bits(gb, 8); // marker_bits
}
}
} else {
for (i = 0; i < size - 1; i++)
skip_bits(gb, 8);
}
return 0;
}
static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCContext *s, int size)
{
uint32_t country_code;
uint32_t user_identifier;
GetBitContext *gb = &s->HEVClc->gb;
if (size < 7)
return AVERROR(EINVAL);
size -= 7;
country_code = get_bits(gb, 8);
if (country_code == 0xFF) {
skip_bits(gb, 8);
size--;
}
skip_bits(gb, 8);
skip_bits(gb, 8);
user_identifier = get_bits_long(gb, 32);
switch (user_identifier) {
case MKBETAG('G', 'A', '9', '4'):
return decode_registered_user_data_closed_caption(s, size);
default:
skip_bits_long(gb, size * 8);
break;
}
return 0;
}
static int active_parameter_sets(HEVCContext *s)
{
GetBitContext *gb = &s->HEVClc->gb;
@ -198,6 +275,8 @@ static int decode_nal_sei_prefix(HEVCContext *s, int type, int size)
active_parameter_sets(s);
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
return 0;
case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35:
return decode_nal_sei_user_data_registered_itu_t_t35(s, size);
default:
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
skip_bits_long(gb, 8 * size);