mirror of https://git.ffmpeg.org/ffmpeg.git
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:
parent
43492ff3ab
commit
7f7fa90f7b
|
@ -2566,6 +2566,16 @@ static int set_side_data(HEVCContext *s)
|
||||||
s->sei_hflip, s->sei_vflip);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -937,6 +937,10 @@ typedef struct HEVCContext {
|
||||||
int sei_hflip, sei_vflip;
|
int sei_hflip, sei_vflip;
|
||||||
|
|
||||||
int picture_struct;
|
int picture_struct;
|
||||||
|
|
||||||
|
uint8_t* a53_caption;
|
||||||
|
int a53_caption_size;
|
||||||
|
|
||||||
} HEVCContext;
|
} HEVCContext;
|
||||||
|
|
||||||
int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx,
|
int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx,
|
||||||
|
|
|
@ -146,6 +146,83 @@ static int decode_pic_timing(HEVCContext *s)
|
||||||
return 1;
|
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)
|
static int active_parameter_sets(HEVCContext *s)
|
||||||
{
|
{
|
||||||
GetBitContext *gb = &s->HEVClc->gb;
|
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);
|
active_parameter_sets(s);
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
|
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
|
||||||
return 0;
|
return 0;
|
||||||
|
case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35:
|
||||||
|
return decode_nal_sei_user_data_registered_itu_t_t35(s, size);
|
||||||
default:
|
default:
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
|
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
|
||||||
skip_bits_long(gb, 8 * size);
|
skip_bits_long(gb, 8 * size);
|
||||||
|
|
Loading…
Reference in New Issue