summaryrefslogtreecommitdiff
authorJian 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)
commit002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60 (patch)
tree51a8170936cabaa7e3eabc7e3a9d2f259eed7cf7
parent77d2269a45227e6d6e7ed71150eb6df086e2660a (diff)
downloadffmpeg-002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60.zip
ffmpeg-002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60.tar.gz
ffmpeg-002f1a1b5e0cca1dd426fd40c2ba1f4be457ff60.tar.bz2
PD#141900: Add support hevc hdr info
Change-Id: Ie742b3f4ae8aa50d3797bdd96876d6f9b8e382b1
Diffstat
-rw-r--r--libavcodec/avcodec.h30
-rw-r--r--libavcodec/hevc.c52
-rw-r--r--libavcodec/hevc.h9
-rw-r--r--libavcodec/hevc_sei.c42
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);