This includes Mastering Display, Content light level, and some ITU-T T35
metadata like closed captions and HDR10+.
Signed-off-by: James Almer
---
libavcodec/av1dec.c | 163
libavcodec/av1dec.h | 8 +++
2 files changed, 171 insertions(+)
diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
index d83c902f1f..dda9a22cf2 100644
--- a/libavcodec/av1dec.c
+++ b/libavcodec/av1dec.c
@@ -21,13 +21,16 @@
#include "config_components.h"
#include "libavutil/film_grain_params.h"
+#include "libavutil/mastering_display_metadata.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "av1dec.h"
+#include "atsc_a53.h"
#include "bytestream.h"
#include "codec_internal.h"
#include "decode.h"
+#include "dynamic_hdr10_plus.h"
#include "hwconfig.h"
#include "profiles.h"
#include "thread.h"
@@ -645,6 +648,7 @@ fail:
static av_cold int av1_decode_free(AVCodecContext *avctx)
{
AV1DecContext *s = avctx->priv_data;
+AV1RawMetadataITUTT35 itut_t35;
for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) {
av1_frame_unref(avctx, &s->ref[i]);
@@ -655,8 +659,14 @@ static av_cold int av1_decode_free(AVCodecContext *avctx)
av_buffer_unref(&s->seq_ref);
av_buffer_unref(&s->header_ref);
+av_buffer_unref(&s->cll_ref);
+av_buffer_unref(&s->mdcv_ref);
av_freep(&s->tile_group_info);
+while (s->itut_t35_fifo && av_fifo_read(s->itut_t35_fifo, &itut_t35, 1) >=
0)
+av_buffer_unref(&itut_t35.payload_ref);
+av_fifo_freep2(&s->itut_t35_fifo);
+
ff_cbs_fragment_free(&s->current_obu);
ff_cbs_close(&s->cbc);
@@ -771,6 +781,11 @@ static av_cold int av1_decode_init(AVCodecContext *avctx)
if (ret < 0)
return ret;
+s->itut_t35_fifo = av_fifo_alloc2(1, sizeof(AV1RawMetadataITUTT35),
+ AV_FIFO_FLAG_AUTO_GROW);
+if (!s->itut_t35_fifo)
+return AVERROR(ENOMEM);
+
av_opt_set_int(s->cbc->priv_data, "operating_point", s->operating_point,
0);
if (avctx->extradata && avctx->extradata_size) {
@@ -852,6 +867,106 @@ fail:
return ret;
}
+static int export_itut_t35(AVCodecContext *avctx, AVFrame *frame,
+ AV1RawMetadataITUTT35 *itut_t35)
+{
+GetByteContext gb;
+int ret, provider_code;
+
+bytestream2_init(&gb, itut_t35->payload, itut_t35->payload_size);
+
+provider_code = bytestream2_get_be16(&gb);
+switch (provider_code) {
+case 0x31: { // atsc_provider_code
+uint32_t user_identifier = bytestream2_get_be32(&gb);
+switch (user_identifier) {
+case MKBETAG('G', 'A', '9', '4'): { // closed captions
+AVBufferRef *buf = NULL;
+
+ret = ff_parse_a53_cc(&buf, gb.buffer,
bytestream2_get_bytes_left(&gb));
+if (ret < 0)
+return ret;
+if (!ret)
+break;
+
+if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_A53_CC,
buf))
+av_buffer_unref(&buf);
+
+avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
+break;
+}
+default: // ignore unsupported identifiers
+break;
+}
+}
+case 0x3C: { // smpte_provider_code
+AVDynamicHDRPlus *hdrplus;
+int provider_oriented_code = bytestream2_get_be16(&gb);
+int application_identifier = bytestream2_get_byte(&gb);
+
+if (provider_oriented_code != 1 || application_identifier != 4)
+break;
+
+hdrplus = av_dynamic_hdr_plus_create_side_data(frame);
+if (!hdrplus)
+return AVERROR(ENOMEM);
+
+ret = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(hdrplus, gb.buffer,
+
bytestream2_get_bytes_left(&gb));
+if (ret < 0)
+return ret;
+break;
+}
+default: // ignore unsupported provider codes
+break;
+}
+
+return 0;
+}
+
+static int export_metadata(AVCodecContext *avctx, AVFrame *frame)
+{
+AV1DecContext *s = avctx->priv_data;
+AV1RawMetadataITUTT35 itut_t35;
+int ret = 0;
+
+if (s->mdcv) {
+AVMasteringDisplayMetadata *mastering =
av_mastering_display_metadata_create_side_data(frame);
+if (!mastering)
+return AVERROR(ENOMEM);
+
+for (int i = 0; i < 3; i++) {
+mastering->display_primaries[i][0] =
av_make_q(s->mdcv->primary_chromaticity_x[i], 1 << 16);
+mastering->display_primaries[i][1] =
av_make_q(s->mdcv->primary_chromaticity_y[i], 1 << 16);
+}
+mastering->white_point[0] =
av_make_q(s->mdcv->white_point_chromaticity_x, 1 << 16);
+mastering->white_point[1] =
av_make_q(s->mdcv->white_point_chromaticity_y, 1 << 16);
+
+mastering->max_luminance = av_make_q(s->mdcv->luminance_max, 1 << 8);
+mastering->min_luminance = av_make_q(s->mdcv->luminance_min, 1 << 14);
+
+