X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fhevc_sei.c;h=3b0fa434391f740fc8b6d307d939d57b63a709d9;hb=494f868e93d1d671497d0d0884368f015eb7d31e;hp=a4ec65dc1a9b3c43d5434d7ccbb30a1c4900bd01;hpb=78f787c2e7fdf6416866ba8ca7a5eaff7f0f8c23;p=ffmpeg diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index a4ec65dc1a9..3b0fa434391 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "atsc_a53.h" +#include "dynamic_hdr10_plus.h" #include "golomb.h" #include "hevc_ps.h" #include "hevc_sei.h" @@ -164,51 +166,17 @@ static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, const HEVCPa static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetBitContext *gb, int size) { - int flag; - int user_data_type_code; - int cc_count; + int ret; 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) { - int old_size = s->buf_ref ? s->buf_ref->size : 0; - const uint64_t new_size = (old_size + cc_count - * UINT64_C(3)); - int i, ret; - - if (new_size > INT_MAX) - return AVERROR(EINVAL); - - /* Allow merging of the cc data from two fields. */ - ret = av_buffer_realloc(&s->buf_ref, new_size); - if (ret < 0) - return ret; - - for (i = 0; i < cc_count; i++) { - s->buf_ref->data[old_size++] = get_bits(gb, 8); - s->buf_ref->data[old_size++] = get_bits(gb, 8); - s->buf_ref->data[old_size++] = get_bits(gb, 8); - } - skip_bits(gb, 8); // marker_bits - } - } - } else { - int i; - for (i = 0; i < size - 1; i++) - skip_bits(gb, 8); - } + ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer + get_bits_count(gb) / 8, size); + + if (ret < 0) + return ret; + + skip_bits_long(gb, size * 8); return 0; } @@ -239,15 +207,46 @@ static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, GetBitC return 0; } +static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s, + GetBitContext *gb, int size) +{ + size_t meta_size; + int err; + AVDynamicHDRPlus *metadata = av_dynamic_hdr_plus_alloc(&meta_size); + if (!metadata) + return AVERROR(ENOMEM); + + err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, + gb->buffer + get_bits_count(gb) / 8, size); + if (err < 0) { + av_free(metadata); + return err; + } + + av_buffer_unref(&s->info); + s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); + if (!s->info) { + av_free(metadata); + return AVERROR(ENOMEM); + } + + skip_bits_long(gb, size * 8); + + return 0; +} + static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitContext *gb, int size) { - uint32_t country_code; - uint32_t user_identifier; + const uint8_t usa_country_code = 0xB5; + const uint16_t smpte_provider_code = 0x003C; + + uint8_t country_code = 0; + uint16_t provider_code = 0; - if (size < 7) + if (size < 3) return AVERROR(EINVAL); - size -= 7; + size -= 3; country_code = get_bits(gb, 8); if (country_code == 0xFF) { @@ -255,18 +254,42 @@ static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitConte size--; } - skip_bits(gb, 8); - skip_bits(gb, 8); + provider_code = get_bits(gb, 16); + + if (country_code == usa_country_code && + provider_code == smpte_provider_code) { + // A/341 Amendment - 2094-40 + const uint16_t smpte2094_40_provider_oriented_code = 0x0001; + const uint8_t smpte2094_40_application_identifier = 0x04; + uint16_t provider_oriented_code; + uint8_t application_identifier; + + if (size < 3) + return AVERROR(EINVAL); + size -= 3; + + provider_oriented_code = get_bits(gb, 16); + application_identifier = get_bits(gb, 8); + if (provider_oriented_code == smpte2094_40_provider_oriented_code && + application_identifier == smpte2094_40_application_identifier) { + return decode_registered_user_data_dynamic_hdr_plus(&s->dynamic_hdr_plus, gb, size); + } + } else { + uint32_t user_identifier; - user_identifier = get_bits_long(gb, 32); + if (size < 4) + return AVERROR(EINVAL); + size -= 4; - switch (user_identifier) { + user_identifier = get_bits_long(gb, 32); + switch (user_identifier) { case MKBETAG('G', 'A', '9', '4'): return decode_registered_user_data_closed_caption(&s->a53_caption, gb, size); default: - skip_bits_long(gb, size * 8); break; + } } + skip_bits_long(gb, size * 8); return 0; } @@ -453,4 +476,5 @@ void ff_hevc_reset_sei(HEVCSEI *s) av_buffer_unref(&s->unregistered.buf_ref[i]); s->unregistered.nb_buf_ref = 0; av_freep(&s->unregistered.buf_ref); + av_buffer_unref(&s->dynamic_hdr_plus.info); }