| @@ -64,6 +64,11 @@ struct FrameListData { · 63 unmodified lines |
| 64 | struct FrameListData *next; | 64 | struct FrameListData *next; |
| 65 | }; | 65 | }; |
| 66 | | 66 | |
| | 67 | typedef struct FrameHDR10Plus { |
| | 68 | int64_t pts; |
| | 69 | AVBufferRef *hdr10_plus; |
| | 70 | } FrameHDR10Plus; |
| | 71 | |
| 67 | typedef struct VPxEncoderContext { | 72 | typedef 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 we | 132 | * 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 | |
| | 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 | static av_cold int codecctl_int(AVCodecContext *avctx, | 371 | static 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 | #endif | 889 | #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 | #endif | 918 | #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 in | 1716 | // this is for encoding with preset temporal layering patterns defined in |