From: Will Kelleher Date: Fri, 6 Nov 2015 20:48:46 +0000 (-0600) Subject: hevc: extract SEI caption data X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=7f7fa90f7b7fccecff98bb1cef307e093dac1d29;p=ffmpeg hevc: extract SEI caption data Signed-off-by: Will Kelleher Signed-off-by: Michael Niedermayer --- diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 4b3f19998ce..1fa5283da3c 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -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; } diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 66b9a2f0fcb..6d8f7039005 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -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, diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 179b0458640..e853067cc4f 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -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);