Re: [FFmpeg-devel] [PATCH] avcodec/av1dec: parse and export Metadata OBUs

2023-03-10 Thread James Almer

On 3/6/2023 1:58 PM, James Almer wrote:

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(+)


Will apply.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH] avcodec/av1dec: parse and export Metadata OBUs

2023-03-06 Thread James Almer
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);
+
+