author | Jian Wang <jian.wang@amlogic.com> | 2017-04-13 09:46:10 (GMT) |
---|---|---|
committer | Zhi Zhou <zhi.zhou@amlogic.com> | 2017-04-14 04:28:03 (GMT) |
commit | 002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60 (patch) | |
tree | 51a8170936cabaa7e3eabc7e3a9d2f259eed7cf7 | |
parent | 77d2269a45227e6d6e7ed71150eb6df086e2660a (diff) | |
download | ffmpeg-002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60.zip ffmpeg-002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60.tar.gz ffmpeg-002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60.tar.bz2 |
PD#141900: Add support hevc hdr info
Change-Id: Ie742b3f4ae8aa50d3797bdd96876d6f9b8e382b1
-rw-r--r-- | libavcodec/avcodec.h | 30 | ||||
-rw-r--r-- | libavcodec/hevc.c | 52 | ||||
-rw-r--r-- | libavcodec/hevc.h | 9 | ||||
-rw-r--r-- | libavcodec/hevc_sei.c | 42 |
4 files changed, 133 insertions, 0 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3a40c4b..d70854b 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1135,6 +1135,33 @@ enum AVFieldOrder { AV_FIELD_BT, //< Bottom coded first, top displayed first }; +typedef struct AVHDRMetadata { + /** + * CIE 1931 xy chromaticity coords of color primaries (r, g, b order). + */ + uint16_t display_primaries[3][2]; + + /** + * CIE 1931 xy chromaticity coords of white point. + */ + uint16_t white_point[2]; + + /** + * Min luminance of mastering display (cd/m^2). + */ + uint32_t min_luminance; + + /** + * Max luminance of mastering display (cd/m^2). + */ + uint32_t max_luminance; + + uint16_t max_cll; + + uint16_t max_pall; + +} AVHDRMetadata; + /** * main external API structure. * New fields can be added to the end with minor version bumps. @@ -2898,6 +2925,9 @@ typedef struct AVCodecContext { * - encoding: set by libavcodec */ int seek_preroll; + + int has_hdr_metadata; + AVHDRMetadata hdr_metadata; } AVCodecContext; AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 412ba19..ae18e57 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -2034,6 +2034,54 @@ static void restore_tqb_pixels(HEVCContext *s) } } + +static int set_hdr_data(HEVCContext *s) +{ + AVFrame *out = s->ref->frame; + + if (s->sei_mastering_display_info_present) { + // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b + const int mapping[3] = {2, 0, 1}; + const int chroma_den = 50000; + const int luma_den = 10000; + int i; + AVHDRMetadata* metadata = &s->avctx->hdr_metadata; + + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + metadata->display_primaries[i][0] = s->display_primaries[j][0]; + metadata->display_primaries[i][1] = s->display_primaries[j][1]; + } + metadata->white_point[0] = s->white_point[0]; + metadata->white_point[1] = s->white_point[1]; + + metadata->max_luminance = s->max_mastering_luminance; + metadata->min_luminance = s->min_mastering_luminance; + + metadata->max_cll = s->max_content_light_level; + metadata->max_pall = s->max_pic_average_light_level; + + av_log(s->avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); + av_log(s->avctx, AV_LOG_DEBUG, + "r(%x,%x) g(%x,%x) b(%x,%x) wp(%x,%x)\n", + metadata->display_primaries[0][0], + metadata->display_primaries[0][1], + metadata->display_primaries[1][0], + metadata->display_primaries[1][1], + metadata->display_primaries[2][0], + metadata->display_primaries[2][1], + metadata->white_point[0], metadata->white_point[1]); + av_log(s->avctx, AV_LOG_DEBUG, + "min_luminance=%x, max_luminance=%x\n", + metadata->min_luminance, metadata->max_luminance); + + s->avctx->has_hdr_metadata = 1; + } + + return 0; +} + + static int hevc_frame_start(HEVCContext *s) { HEVCLocalContext *lc = s->HEVClc; @@ -2068,6 +2116,10 @@ static int hevc_frame_start(HEVCContext *s) goto fail; } + ret = set_hdr_data(s); + if (ret < 0) + goto fail; + av_frame_unref(s->output_frame); ret = ff_hevc_output_frame(s, s->output_frame, 0); if (ret < 0) diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 4b45323..30b952d 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -872,6 +872,15 @@ typedef struct HEVCContext { int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) int nuh_layer_id; + /** mastering display */ + int sei_mastering_display_info_present; + uint16_t display_primaries[3][2]; + uint16_t white_point[2]; + uint32_t max_mastering_luminance; + uint32_t min_mastering_luminance; + uint16_t max_content_light_level; + uint16_t max_pic_average_light_level; + } HEVCContext; int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 1a96447..97feac6 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -77,6 +77,44 @@ static void decode_nal_sei_frame_packing_arrangement(HEVCLocalContext *lc) skip_bits1(gb); // upsampled_aspect_ratio_flag } +static int decode_nal_sei_mastering_display_info(HEVCContext *s) +{ + GetBitContext *gb = &s->HEVClc->gb; + int i; + av_log(s->avctx, AV_LOG_DEBUG, "decode_nal_sei_mastering_display_info\n"); + + // Mastering primaries + for (i = 0; i < 3; i++) { + s->display_primaries[i][0] = get_bits(gb, 16); + s->display_primaries[i][1] = get_bits(gb, 16); + } + // White point (x, y) + s->white_point[0] = get_bits(gb, 16); + s->white_point[1] = get_bits(gb, 16); + + // Max and min luminance of mastering display + s->max_mastering_luminance = get_bits_long(gb, 32); + s->min_mastering_luminance = get_bits_long(gb, 32); + + // As this SEI message comes before the first frame that references it, + // initialize the flag to 2 and decrement on IRAP access unit so it + // persists for the coded video sequence (e.g., between two IRAPs) + s->sei_mastering_display_info_present = 2; + return 0; +} + +static int decode_nal_sei_content_light_level(HEVCContext *s) +{ + GetBitContext *gb = &s->HEVClc->gb; + + av_log(s->avctx, AV_LOG_DEBUG, "decode_nal_sei_content_light_level\n"); + + s->max_content_light_level = get_bits(gb, 16); + s->max_pic_average_light_level = get_bits(gb, 16); + + return 0; +} + static int decode_nal_sei_message(HEVCContext *s) { GetBitContext *gb = &s->HEVClc->gb; @@ -100,6 +138,10 @@ static int decode_nal_sei_message(HEVCContext *s) decode_nal_sei_decoded_picture_hash(s, payload_size); else if (payload_type == 45) decode_nal_sei_frame_packing_arrangement(s->HEVClc); + else if (payload_type == 137) /* hdr info*/ + decode_nal_sei_mastering_display_info(s); + else if (payload_type == 144) /* ContentLightLevel*/ + decode_nal_sei_content_light_level(s); else { av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); skip_bits(gb, 8*payload_size); |