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
13 13
14 14
15API changes, most recent first:15API changes, most recent first:
162021-06-17 - xxxxxxxxxx - lavc 59.2.100 - packet.h
17 Add AV_PKT_DATA_DYNAMIC_HDR10_PLUS
16 18
172021-06-09 - xxxxxxxxxx - lavf 59.3.100 - avformat.h192021-06-09 - xxxxxxxxxx - lavf 59.3.100 - avformat.h
18 Add pts_wrap_bits to AVStream20 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
289 case AV_PKT_DATA_ICC_PROFILE: return "ICC Profile";289 case AV_PKT_DATA_ICC_PROFILE: return "ICC Profile";
290 case AV_PKT_DATA_DOVI_CONF: return "DOVI configuration record";290 case AV_PKT_DATA_DOVI_CONF: return "DOVI configuration record";
291 case AV_PKT_DATA_S12M_TIMECODE: return "SMPTE ST 12-1:2014 timecode";291 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)";
292 }293 }
293 return NULL;294 return NULL;
294}295}
libavcodec/decode.c+1−0
@@ -1497,6 +1497,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) · 1496 unmodified lines
1497 { AV_PKT_DATA_A53_CC, AV_FRAME_DATA_A53_CC },1497 { AV_PKT_DATA_A53_CC, AV_FRAME_DATA_A53_CC },
1498 { AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE },1498 { AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE },
1499 { AV_PKT_DATA_S12M_TIMECODE, AV_FRAME_DATA_S12M_TIMECODE },1499 { AV_PKT_DATA_S12M_TIMECODE, AV_FRAME_DATA_S12M_TIMECODE },
1500 { AV_PKT_DATA_DYNAMIC_HDR10_PLUS, AV_FRAME_DATA_DYNAMIC_HDR_PLUS },
1500 };1501 };
1501 1502
1502 if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) {1503 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
64 struct FrameListData *next;64 struct FrameListData *next;
65};65};
66 66
67typedef struct FrameHDR10Plus {
68 int64_t pts;
69 AVBufferRef *hdr10_plus;
70} FrameHDR10Plus;
71
67typedef struct VPxEncoderContext {72typedef struct VPxEncoderContext {
68 AVClass *class;73 AVClass *class;
69 struct vpx_codec_ctx encoder;74 struct vpx_codec_ctx encoder;
@@ -121,6 +126,8 @@ typedef struct VPxEncoderContext { · 51 unmodified lines
121 int tune_content;126 int tune_content;
122 int corpus_complexity;127 int corpus_complexity;
123 int tpl_model;128 int tpl_model;
129 int discard_hdr10_plus;
130 AVFifoBuffer *hdr10_plus_fifo;
124 /**131 /**
125 * If the driver does not support ROI then warn the first time we132 * If the driver does not support ROI then warn the first time we
126 * encounter a frame with ROI side data.133 * encounter a frame with ROI side data.
@@ -316,6 +323,51 @@ static av_cold void free_frame_list(struct FrameListData *list) · 189 unmodified lines
316 }323 }
317}324}
318 325
326static 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
335static 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
345static 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
319static av_cold int codecctl_int(AVCodecContext *avctx,371static av_cold int codecctl_int(AVCodecContext *avctx,
320 enum vp8e_enc_control_id id, int val)372 enum vp8e_enc_control_id id, int val)
321{373{
@@ -384,6 +436,8 @@ static av_cold int vpx_free(AVCodecContext *avctx) · 62 unmodified lines
384 av_freep(&ctx->twopass_stats.buf);436 av_freep(&ctx->twopass_stats.buf);
385 av_freep(&avctx->stats_out);437 av_freep(&avctx->stats_out);
386 free_frame_list(ctx->coded_frame_list);438 free_frame_list(ctx->coded_frame_list);
439 if (ctx->hdr10_plus_fifo)
440 free_hdr10_plus_fifo(&ctx->hdr10_plus_fifo);
387 return 0;441 return 0;
388}442}
389 443
@@ -835,6 +889,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, · 445 unmodified lines
835#endif889#endif
836 AVDictionaryEntry* en = NULL;890 AVDictionaryEntry* en = NULL;
837 891
892 ctx->discard_hdr10_plus = 1;
838 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());893 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
839 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());894 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
840 895
@@ -851,6 +906,14 @@ static av_cold int vpx_init(AVCodecContext *avctx, · 10 unmodified lines
851 if (avctx->codec_id == AV_CODEC_ID_VP9) {906 if (avctx->codec_id == AV_CODEC_ID_VP9) {
852 if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))907 if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))
853 return AVERROR(EINVAL);908 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 }
854 }917 }
855#endif918#endif
856 919
@@ -1213,6 +1276,15 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, · 356 unmodified lines
1213 AV_WB64(side_data, 1);1276 AV_WB64(side_data, 1);
1214 memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha);1277 memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha);
1215 }1278 }
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
1216 return pkt->size;1288 return pkt->size;
1217}1289}
1218 1290
@@ -1620,6 +1692,25 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, · 401 unmodified lines
1620 vp9_encode_set_roi(avctx, frame->width, frame->height, sd);1692 vp9_encode_set_roi(avctx, frame->width, frame->height, sd);
1621 }1693 }
1622 }1694 }
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 }
1623 }1714 }
1624 1715
1625 // this is for encoding with preset temporal layering patterns defined in1716 // 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
290 */290 */
291 AV_PKT_DATA_S12M_TIMECODE,291 AV_PKT_DATA_S12M_TIMECODE,
292 292
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
293 /**301 /**
294 * The number of side data types.302 * The number of side data types.
295 * This is not part of the public API/ABI in the sense that it may303 * 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
28#include "libavutil/version.h"28#include "libavutil/version.h"
29 29
30#define LIBAVCODEC_VERSION_MAJOR 5930#define LIBAVCODEC_VERSION_MAJOR 59
31#define LIBAVCODEC_VERSION_MINOR 131#define LIBAVCODEC_VERSION_MINOR 2
32#define LIBAVCODEC_VERSION_MICRO 10232#define LIBAVCODEC_VERSION_MICRO 100
33 33
34#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \34#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
35 LIBAVCODEC_VERSION_MINOR, \35 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