History

avcodec: Pass HDR10+ metadata to packet side data in VP9 encoder

HDR10+ metadata is stored in the bit stream for HEVC. The story is different for VP9 and cannot store the metadata in the bit stream. HDR10+ should be passed to packet side data an stored in the container (mkv) for VP9. This CL is taking HDR10+ from AVFrame side data in libvpxenc and is passing it to the AVPacket side data.

Mohammad Izadi committed 5 years ago

Commit aca923b1 parent 947122f6 files · +105 −2Browse files

Unified · Split

6 files
  1. doc/APIchanges +2 −0
  2. libavcodec/avpacket.c +1 −0
  3. libavcodec/decode.c +1 −0
  4. libavcodec/libvpxenc.c +91 −0
  5. libavcodec/packet.h +8 −0
  6. libavcodec/version.h +2 −2
doc/APIchanges+2−0
@@ -13,6 +13,8 @@ libavutil: 2021-04-27 · 12 unmodified lines
1313
1414
1515 API changes, most recent first:
16+2021-06-17 - xxxxxxxxxx - lavc 59.2.100 - packet.h
17+ Add AV_PKT_DATA_DYNAMIC_HDR10_PLUS
1618
1719 2021-06-09 - xxxxxxxxxx - lavf 59.3.100 - avformat.h
1820 Add pts_wrap_bits to AVStream
libavcodec/avpacket.c+1−0
@@ -289,6 +289,7 @@ const char *av_packet_side_data_name(enum AVPacketSideDataType type) · 288 unmodified lines
289289 case AV_PKT_DATA_ICC_PROFILE: return "ICC Profile";
290290 case AV_PKT_DATA_DOVI_CONF: return "DOVI configuration record";
291291 case AV_PKT_DATA_S12M_TIMECODE: return "SMPTE ST 12-1:2014 timecode";
292+ case AV_PKT_DATA_DYNAMIC_HDR10_PLUS: return "HDR10+ Dynamic Metadata (SMPTE 2094-40)";
292293 }
293294 return NULL;
294295 }
libavcodec/decode.c+1−0
@@ -1497,6 +1497,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) · 1496 unmodified lines
14971497 { AV_PKT_DATA_A53_CC, AV_FRAME_DATA_A53_CC },
14981498 { AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE },
14991499 { AV_PKT_DATA_S12M_TIMECODE, AV_FRAME_DATA_S12M_TIMECODE },
1500+ { AV_PKT_DATA_DYNAMIC_HDR10_PLUS, AV_FRAME_DATA_DYNAMIC_HDR_PLUS },
15001501 };
15011502
15021503 if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) {
libavcodec/libvpxenc.c+91−0
@@ -64,6 +64,11 @@ struct FrameListData { · 63 unmodified lines
6464 struct FrameListData *next;
6565 };
6666
67+typedef struct FrameHDR10Plus {
68+ int64_t pts;
69+ AVBufferRef *hdr10_plus;
70+} FrameHDR10Plus;
71+
6772 typedef struct VPxEncoderContext {
6873 AVClass *class;
6974 struct vpx_codec_ctx encoder;
@@ -121,6 +126,8 @@ typedef struct VPxEncoderContext { · 51 unmodified lines
121126 int tune_content;
122127 int corpus_complexity;
123128 int tpl_model;
129+ int discard_hdr10_plus;
130+ AVFifoBuffer *hdr10_plus_fifo;
124131 /**
125132 * If the driver does not support ROI then warn the first time we
126133 * encounter a frame with ROI side data.
@@ -316,6 +323,51 @@ static av_cold void free_frame_list(struct FrameListData *list) · 189 unmodified lines
316323 }
317324 }
318325
326+static av_cold int add_hdr10_plus(AVFifoBuffer *fifo, struct FrameHDR10Plus *data)
327+{
328+ int err = av_fifo_grow(fifo, sizeof(*data));
329+ if (err < 0)
330+ return err;
331+ av_fifo_generic_write(fifo, data, sizeof(*data), NULL);
332+ return 0;
333+}
334+
335+static av_cold void free_hdr10_plus_fifo(AVFifoBuffer **fifo)
336+{
337+ FrameHDR10Plus frame_hdr10_plus;
338+ while (av_fifo_size(*fifo) >= sizeof(frame_hdr10_plus)) {
339+ av_fifo_generic_read(*fifo, &frame_hdr10_plus, sizeof(frame_hdr10_plus), NULL);
340+ av_buffer_unref(&frame_hdr10_plus.hdr10_plus);
341+ }
342+ av_fifo_freep(fifo);
343+}
344+
345+static int copy_hdr10_plus_to_pkt(AVFifoBuffer *fifo, AVPacket *pkt)
346+{
347+ FrameHDR10Plus frame_hdr10_plus;
348+ uint8_t *data;
349+ if (!pkt)
350+ return 0;
351+ if (av_fifo_size(fifo) < sizeof(frame_hdr10_plus))
352+ return 0;
353+ av_fifo_generic_peek(fifo, &frame_hdr10_plus, sizeof(frame_hdr10_plus), NULL);
354+ if (!frame_hdr10_plus.hdr10_plus || frame_hdr10_plus.pts != pkt->pts)
355+ return 0;
356+ av_fifo_generic_read(fifo, &frame_hdr10_plus, sizeof(frame_hdr10_plus), NULL);
357+ if (!frame_hdr10_plus.hdr10_plus)
358+ return 0;
359+
360+ data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, frame_hdr10_plus.hdr10_plus->size);
361+ if (!data) {
362+ av_buffer_unref(&frame_hdr10_plus.hdr10_plus);
363+ return AVERROR(ENOMEM);
364+ }
365+
366+ memcpy(data, frame_hdr10_plus.hdr10_plus->data, frame_hdr10_plus.hdr10_plus->size);
367+ av_buffer_unref(&frame_hdr10_plus.hdr10_plus);
368+ return 0;
369+}
370+
319371 static av_cold int codecctl_int(AVCodecContext *avctx,
320372 enum vp8e_enc_control_id id, int val)
321373 {
@@ -384,6 +436,8 @@ static av_cold int vpx_free(AVCodecContext *avctx) · 62 unmodified lines
384436 av_freep(&ctx->twopass_stats.buf);
385437 av_freep(&avctx->stats_out);
386438 free_frame_list(ctx->coded_frame_list);
439+ if (ctx->hdr10_plus_fifo)
440+ free_hdr10_plus_fifo(&ctx->hdr10_plus_fifo);
387441 return 0;
388442 }
389443
@@ -835,6 +889,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, · 445 unmodified lines
835889 #endif
836890 AVDictionaryEntry* en = NULL;
837891
892+ ctx->discard_hdr10_plus = 1;
838893 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
839894 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
840895
@@ -851,6 +906,14 @@ static av_cold int vpx_init(AVCodecContext *avctx, · 10 unmodified lines
851906 if (avctx->codec_id == AV_CODEC_ID_VP9) {
852907 if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))
853908 return AVERROR(EINVAL);
909+ // Keep HDR10+ if it has bit depth higher than 8 and
910+ // it has PQ trc (SMPTE2084).
911+ if (enccfg.g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) {
912+ ctx->discard_hdr10_plus = 0;
913+ ctx->hdr10_plus_fifo = av_fifo_alloc(sizeof(FrameHDR10Plus));
914+ if (!ctx->hdr10_plus_fifo)
915+ return AVERROR(ENOMEM);
916+ }
854917 }
855918 #endif
856919
@@ -1213,6 +1276,15 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, · 356 unmodified lines
12131276 AV_WB64(side_data, 1);
12141277 memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha);
12151278 }
1279+ if (cx_frame->frame_number != -1) {
1280+ VPxContext *ctx = avctx->priv_data;
1281+ if (!ctx->discard_hdr10_plus) {
1282+ int err = copy_hdr10_plus_to_pkt(ctx->hdr10_plus_fifo, pkt);
1283+ if (err < 0)
1284+ return err;
1285+ }
1286+ }
1287+
12161288 return pkt->size;
12171289 }
12181290
@@ -1620,6 +1692,25 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, · 401 unmodified lines
16201692 vp9_encode_set_roi(avctx, frame->width, frame->height, sd);
16211693 }
16221694 }
1695+
1696+ if (!ctx->discard_hdr10_plus) {
1697+ AVFrameSideData *hdr10_plus_metadata;
1698+ // Add HDR10+ metadata to queue.
1699+ hdr10_plus_metadata = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS);
1700+ if (hdr10_plus_metadata) {
1701+ int err;
1702+ struct FrameHDR10Plus data;
1703+ data.pts = frame->pts;
1704+ data.hdr10_plus = av_buffer_ref(hdr10_plus_metadata->buf);
1705+ if (!data.hdr10_plus)
1706+ return AVERROR(ENOMEM);
1707+ err = add_hdr10_plus(ctx->hdr10_plus_fifo, &data);
1708+ if (err < 0) {
1709+ av_buffer_unref(&data.hdr10_plus);
1710+ return err;
1711+ }
1712+ }
1713+ }
16231714 }
16241715
16251716 // this is for encoding with preset temporal layering patterns defined in
libavcodec/packet.h+8−0
@@ -290,6 +290,14 @@ enum AVPacketSideDataType { · 289 unmodified lines
290290 */
291291 AV_PKT_DATA_S12M_TIMECODE,
292292
293+ /**
294+ * HDR10+ dynamic metadata associated with a video frame. The metadata is in
295+ * the form of the AVDynamicHDRPlus struct and contains
296+ * information for color volume transform - application 4 of
297+ * SMPTE 2094-40:2016 standard.
298+ */
299+ AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
300+
293301 /**
294302 * The number of side data types.
295303 * This is not part of the public API/ABI in the sense that it may
libavcodec/version.h+2−2
@@ -28,8 +28,8 @@ · 27 unmodified lines
2828 #include "libavutil/version.h"
2929
3030 #define LIBAVCODEC_VERSION_MAJOR 59
31−#define LIBAVCODEC_VERSION_MINOR 1
32−#define LIBAVCODEC_VERSION_MICRO 102
31+#define LIBAVCODEC_VERSION_MINOR 2
32+#define LIBAVCODEC_VERSION_MICRO 100
3333
3434 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
3535 LIBAVCODEC_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t