| @@ -64,6 +64,11 @@ struct FrameListData { · 63 unmodified lines |
| 64 | 64 | struct FrameListData *next; |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | +typedef struct FrameHDR10Plus { |
| 68 | + int64_t pts; |
| 69 | + AVBufferRef *hdr10_plus; |
| 70 | +} FrameHDR10Plus; |
| 71 | + |
| 67 | 72 | typedef struct VPxEncoderContext { |
| 68 | 73 | AVClass *class; |
| 69 | 74 | struct vpx_codec_ctx encoder; |
| @@ -121,6 +126,8 @@ typedef struct VPxEncoderContext { · 51 unmodified lines |
| 121 | 126 | int tune_content; |
| 122 | 127 | int corpus_complexity; |
| 123 | 128 | int tpl_model; |
| 129 | + int discard_hdr10_plus; |
| 130 | + AVFifoBuffer *hdr10_plus_fifo; |
| 124 | 131 | /** |
| 125 | 132 | * If the driver does not support ROI then warn the first time we |
| 126 | 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 | |
| 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 | + |
| 319 | 371 | static av_cold int codecctl_int(AVCodecContext *avctx, |
| 320 | 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 | 436 | av_freep(&ctx->twopass_stats.buf); |
| 385 | 437 | av_freep(&avctx->stats_out); |
| 386 | 438 | free_frame_list(ctx->coded_frame_list); |
| 439 | + if (ctx->hdr10_plus_fifo) |
| 440 | + free_hdr10_plus_fifo(&ctx->hdr10_plus_fifo); |
| 387 | 441 | return 0; |
| 388 | 442 | } |
| 389 | 443 | |
| @@ -835,6 +889,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, · 445 unmodified lines |
| 835 | 889 | #endif |
| 836 | 890 | AVDictionaryEntry* en = NULL; |
| 837 | 891 | |
| 892 | + ctx->discard_hdr10_plus = 1; |
| 838 | 893 | av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); |
| 839 | 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 | 906 | if (avctx->codec_id == AV_CODEC_ID_VP9) { |
| 852 | 907 | if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt)) |
| 853 | 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 | 918 | #endif |
| 856 | 919 | |
| @@ -1213,6 +1276,15 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, · 356 unmodified lines |
| 1213 | 1276 | AV_WB64(side_data, 1); |
| 1214 | 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 | 1288 | return pkt->size; |
| 1217 | 1289 | } |
| 1218 | 1290 | |
| @@ -1620,6 +1692,25 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, · 401 unmodified lines |
| 1620 | 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 | 1716 | // this is for encoding with preset temporal layering patterns defined in |