From cacb62f9cbf37bb05b00a025b21904b6966b6a49 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Sep 2018 15:21:09 -0300 Subject: [PATCH 01/10] Revert "decode: copy the output parameters from the last bsf in the chain back to the AVCodecContext" This reverts commit 662558f985f50834eebe82d6b6854c66f33ab320. The avcodec_parameters_to_context() call was freeing and reallocating AVCodecContext->extradata, essentially taking ownership of it, which according to the doxy is user owned. This is an API break and has produces crashes in some library users like Firefox. Revert until a better solution is found to internally propagate the filtered extradata back into the decoder context. Signed-off-by: James Almer --- libavcodec/decode.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index d10a2c8b58..2dab7f2a71 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -221,10 +221,6 @@ int ff_decode_bsfs_init(AVCodecContext *avctx) goto fail; } - ret = avcodec_parameters_to_context(avctx, s->bsfs[s->nb_bsfs - 1]->par_out); - if (ret < 0) - return ret; - return 0; fail: ff_decode_bsfs_uninit(avctx); From 8d80046a0ff72652438ed3ea361d59a58a9a082f Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 25 Oct 2018 23:12:05 -0300 Subject: [PATCH 02/10] libaom: remove references to yuva444p pixfmt Support for it was apparently never in the codebase, and the enum value was recently removed from the public headers [1] [1] https://aomedia.googlesource.com/aom/+/f1570f0c2f70832dd170285f8de60bd2379c8efa Signed-off-by: James Almer --- libavcodec/libaom.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/libaom.c b/libavcodec/libaom.c index 512095b339..bfc25ebe38 100644 --- a/libavcodec/libaom.c +++ b/libavcodec/libaom.c @@ -44,8 +44,6 @@ enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth) return AV_PIX_FMT_YUV422P; case AOM_IMG_FMT_I444: return AV_PIX_FMT_YUV444P; - case AOM_IMG_FMT_444A: - return AV_PIX_FMT_YUVA444P; HIGH_DEPTH(420) HIGH_DEPTH(422) HIGH_DEPTH(444) @@ -65,8 +63,6 @@ aom_img_fmt_t ff_aom_pixfmt_to_imgfmt(enum AVPixelFormat pix) return AOM_IMG_FMT_I422; case AV_PIX_FMT_YUV444P: return AOM_IMG_FMT_I444; - case AV_PIX_FMT_YUVA444P: - return AOM_IMG_FMT_444A; case AV_PIX_FMT_YUV420P10: return AOM_IMG_FMT_I42016; case AV_PIX_FMT_YUV422P10: From a3a501df240fa179fe12c2cf5dbbb4f1d9f650ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 25 Oct 2018 15:41:26 +0300 Subject: [PATCH 03/10] libavutil: Undeprecate the AVFrame reordered_opaque field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was marked as deprecated (but only in the doxygen, not with an actual deprecation attribute) in 81c623fae05 in 2011, but was undeprecated in ad1ee5fa7. Signed-off-by: Martin Storsjö --- libavutil/frame.h | 1 - libavutil/version.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libavutil/frame.h b/libavutil/frame.h index ff3fe46dd6..c7240ebe9b 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -295,7 +295,6 @@ typedef struct AVFrame { * that time, * the decoder reorders values as needed and sets AVFrame.reordered_opaque * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque - * @deprecated in favor of pkt_pts */ int64_t reordered_opaque; diff --git a/libavutil/version.h b/libavutil/version.h index 4a9fffef43..e5fbd4ca81 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -55,7 +55,7 @@ #define LIBAVUTIL_VERSION_MAJOR 56 #define LIBAVUTIL_VERSION_MINOR 7 -#define LIBAVUTIL_VERSION_MICRO 0 +#define LIBAVUTIL_VERSION_MICRO 1 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From 80f85a95da293e9894c071b440c5a2e002e26ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 11 Oct 2018 16:03:10 +0300 Subject: [PATCH 04/10] libx264: Pass the reordered_opaque field through the encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libx264 does have a field for opaque data to pass along with frames through the encoder, but it is a pointer, while the libavcodec reordered_opaque field is an int64_t. Therefore, allocate an array within the libx264 wrapper, where reordered_opaque values in flight are stored, and pass a pointer to this array to libx264. Update the public libavcodec documentation for the AVCodecContext field to explain this usage, and add a codec capability that allows detecting whether an encoder handles this field. Signed-off-by: Martin Storsjö --- libavcodec/avcodec.h | 12 +++++++++++- libavcodec/libx264.c | 33 +++++++++++++++++++++++++++++++-- libavcodec/version.h | 2 +- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index fb8e34e7d5..727e1c411d 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -899,6 +899,13 @@ typedef struct RcOverride{ */ #define AV_CODEC_CAP_HYBRID (1 << 18) +/** + * This codec takes the reordered_opaque field from input AVFrames + * and returns it in the corresponding field in AVCodecContext after + * encoding. + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 19) + /** * Pan Scan area. * This specifies the area which should be displayed. @@ -2297,7 +2304,10 @@ typedef struct AVCodecContext { /** * opaque 64-bit number (generally a PTS) that will be reordered and * output in AVFrame.reordered_opaque - * - encoding: unused + * - encoding: Set by libavcodec to the reordered_opaque of the input + * frame corresponding to the last returned packet. Only + * supported by encoders with the + * AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability. * - decoding: Set by user. */ int64_t reordered_opaque; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 3dc53aaf38..f30a4ccad1 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -85,6 +85,9 @@ typedef struct X264Context { int noise_reduction; char *x264_params; + + int nb_reordered_opaque, next_reordered_opaque; + int64_t *reordered_opaque; } X264Context; static void X264_log(void *p, int level, const char *fmt, va_list args) @@ -240,6 +243,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, x264_nal_t *nal; int nnal, i, ret; x264_picture_t pic_out; + int64_t *out_opaque; x264_picture_init( &x4->pic ); x4->pic.img.i_csp = x4->params.i_csp; @@ -259,6 +263,11 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, x4->pic.i_pts = frame->pts; + x4->reordered_opaque[x4->next_reordered_opaque] = frame->reordered_opaque; + x4->pic.opaque = &x4->reordered_opaque[x4->next_reordered_opaque]; + x4->next_reordered_opaque++; + x4->next_reordered_opaque %= x4->nb_reordered_opaque; + switch (frame->pict_type) { case AV_PICTURE_TYPE_I: x4->pic.i_type = x4->forced_idr ? X264_TYPE_IDR @@ -288,6 +297,15 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, pkt->pts = pic_out.i_pts; pkt->dts = pic_out.i_dts; + out_opaque = pic_out.opaque; + if (out_opaque >= x4->reordered_opaque && + out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { + ctx->reordered_opaque = *out_opaque; + } else { + // Unexpected opaque pointer on picture output + ctx->reordered_opaque = 0; + } + #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS switch (pic_out.i_type) { @@ -331,6 +349,7 @@ static av_cold int X264_close(AVCodecContext *avctx) av_freep(&avctx->extradata); av_freep(&x4->sei); + av_freep(&x4->reordered_opaque); if (x4->enc) { x264_encoder_close(x4->enc); @@ -663,6 +682,14 @@ FF_ENABLE_DEPRECATION_WARNINGS cpb_props->max_bitrate = x4->params.rc.i_vbv_max_bitrate * 1000; cpb_props->avg_bitrate = x4->params.rc.i_bitrate * 1000; + // Overestimate the reordered opaque buffer size, in case a runtime + // reconfigure would increase the delay (which it shouldn't). + x4->nb_reordered_opaque = x264_encoder_maximum_delayed_frames(x4->enc) + 17; + x4->reordered_opaque = av_malloc_array(x4->nb_reordered_opaque, + sizeof(*x4->reordered_opaque)); + if (!x4->reordered_opaque) + return AVERROR(ENOMEM); + return 0; } @@ -850,7 +877,8 @@ AVCodec ff_libx264_encoder = { .init = X264_init, .encode2 = X264_frame, .close = X264_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_class = &class, .defaults = x264_defaults, .init_static_data = X264_init_static, @@ -877,7 +905,8 @@ AVCodec ff_libx262_encoder = { .init = X264_init, .encode2 = X264_frame, .close = X264_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_class = &X262_class, .defaults = x264_defaults, .pix_fmts = pix_fmts_8bit, diff --git a/libavcodec/version.h b/libavcodec/version.h index 32486a83c1..29ff4d3ad0 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 10 +#define LIBAVCODEC_VERSION_MINOR 11 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From ee3f62a90caad03d10bc6734103f95b6ae42cd2d Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 6 Nov 2018 01:39:03 -0300 Subject: [PATCH 05/10] pixfmt: Add GRAY10 Based on 7471352f by Luca Barbato. Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavutil/pixdesc.c | 22 ++++++++++++++++++++++ libavutil/pixfmt.h | 4 ++++ libavutil/version.h | 4 ++-- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 9ba03648c5..c1bbae170d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2018-xx-xx - xxxxxxx - lavu 56.8.0 - pixfmt.h + Add AV_PIX_FMT_GRAY10(LE/BE). + 2018-xx-xx - xxxxxxx - lavc 58.10.0 - avcodec.h Add av_bsf_flush(). diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 957f99fdaa..a09fe52c9e 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -483,6 +483,27 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, + [AV_PIX_FMT_GRAY10BE] = { + .name = "gray10be", + .nb_components = 1, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + }, + .flags = AV_PIX_FMT_FLAG_BE, + .alias = "y10be", + }, + [AV_PIX_FMT_GRAY10LE] = { + .name = "gray10le", + .nb_components = 1, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + }, + .alias = "y10le", + }, [AV_PIX_FMT_GRAY12BE] = { .name = "gray12be", .nb_components = 1, @@ -1958,6 +1979,7 @@ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt) case AV_PIX_FMT_ ## fmt ## LE: return AV_PIX_FMT_ ## fmt ## BE switch (pix_fmt) { + PIX_FMT_SWAP_ENDIANNESS(GRAY10); PIX_FMT_SWAP_ENDIANNESS(GRAY12); PIX_FMT_SWAP_ENDIANNESS(GRAY16); PIX_FMT_SWAP_ENDIANNESS(YA16); diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index bcbb378378..23331c3332 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -249,6 +249,9 @@ enum AVPixelFormat { */ AV_PIX_FMT_D3D11, + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; @@ -263,6 +266,7 @@ enum AVPixelFormat { #define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) #define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) #define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) #define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) #define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) diff --git a/libavutil/version.h b/libavutil/version.h index e5fbd4ca81..1e5ba98ca2 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,8 +54,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 7 -#define LIBAVUTIL_VERSION_MICRO 1 +#define LIBAVUTIL_VERSION_MINOR 8 +#define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From f149a4a5fc5af30f56c7d2022bf2a9030369ddf9 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 6 Nov 2018 02:08:05 -0300 Subject: [PATCH 06/10] swscale: Add GRAY10 Based on ab839054 by Luca Barbato. Signed-off-by: James Almer --- libswscale/input.c | 2 ++ libswscale/swscale_internal.h | 2 ++ libswscale/swscale_unscaled.c | 1 + libswscale/utils.c | 2 ++ libswscale/version.h | 2 +- tests/ref/fate/filter-pixdesc-gray10be | 1 + tests/ref/fate/filter-pixdesc-gray10le | 1 + tests/ref/fate/filter-pixfmts-copy | 2 ++ tests/ref/fate/filter-pixfmts-null | 2 ++ tests/ref/fate/filter-pixfmts-scale | 2 ++ tests/ref/fate/filter-pixfmts-vflip | 2 ++ 11 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/filter-pixdesc-gray10be create mode 100644 tests/ref/fate/filter-pixdesc-gray10le diff --git a/libswscale/input.c b/libswscale/input.c index 761776c1ce..3bc475dc69 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -1136,6 +1136,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_YUV420P16LE: case AV_PIX_FMT_YUV422P16LE: case AV_PIX_FMT_YUV444P16LE: + case AV_PIX_FMT_GRAY10LE: case AV_PIX_FMT_GRAY12LE: case AV_PIX_FMT_GRAY16LE: c->lumToYV12 = bswap16Y_c; @@ -1165,6 +1166,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_YUV420P16BE: case AV_PIX_FMT_YUV422P16BE: case AV_PIX_FMT_YUV444P16BE: + case AV_PIX_FMT_GRAY10BE: case AV_PIX_FMT_GRAY12BE: case AV_PIX_FMT_GRAY16BE: c->lumToYV12 = bswap16Y_c; diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index adfe1708e1..7232921b9e 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -600,6 +600,8 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) #define isGray(x) \ ((x) == AV_PIX_FMT_GRAY8 || \ (x) == AV_PIX_FMT_YA8 || \ + (x) == AV_PIX_FMT_GRAY10BE || \ + (x) == AV_PIX_FMT_GRAY10LE || \ (x) == AV_PIX_FMT_GRAY12BE || \ (x) == AV_PIX_FMT_GRAY12LE || \ (x) == AV_PIX_FMT_GRAY16BE || \ diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index f130ac58cb..06ad3a6cae 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1097,6 +1097,7 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY10) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YA16) || diff --git a/libswscale/utils.c b/libswscale/utils.c index d94be5a50b..f391bdad1f 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -108,6 +108,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_RGBA] = { 1, 1 }, [AV_PIX_FMT_ABGR] = { 1, 1 }, [AV_PIX_FMT_BGRA] = { 1, 1 }, + [AV_PIX_FMT_GRAY10BE] = { 1, 1 }, + [AV_PIX_FMT_GRAY10LE] = { 1, 1 }, [AV_PIX_FMT_GRAY12BE] = { 1, 1 }, [AV_PIX_FMT_GRAY12LE] = { 1, 1 }, [AV_PIX_FMT_GRAY16BE] = { 1, 1 }, diff --git a/libswscale/version.h b/libswscale/version.h index 5badd3d321..e21758eb46 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #define LIBSWSCALE_VERSION_MAJOR 5 #define LIBSWSCALE_VERSION_MINOR 0 -#define LIBSWSCALE_VERSION_MICRO 0 +#define LIBSWSCALE_VERSION_MICRO 1 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ diff --git a/tests/ref/fate/filter-pixdesc-gray10be b/tests/ref/fate/filter-pixdesc-gray10be new file mode 100644 index 0000000000..74bf8c69a7 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-gray10be @@ -0,0 +1 @@ +pixdesc-gray10be 64bfd85801ed894c86337d2c7a7efaff diff --git a/tests/ref/fate/filter-pixdesc-gray10le b/tests/ref/fate/filter-pixdesc-gray10le new file mode 100644 index 0000000000..d32cf96f95 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-gray10le @@ -0,0 +1 @@ +pixdesc-gray10le c1aa37491db157f32d589e66f020adee diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index c23187c595..baaf86cc08 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -25,6 +25,8 @@ gbrp12le 654861b1837d312569395f598da1a2a1 gbrp9be cbe1bf8ead497a92362a749bd4b0a57e gbrp9le f88c68df5d699a4a7f1b0152df9f25fe gray 8c941e9bbf6da5336384c57f15a4a454 +gray10be 69c8af356c3861792f9695fdff966629 +gray10le a97b97107bf03f27136abbaca074aa88 gray12be aecffce8ea67ab93527dc74c1a523454 gray12le eac4b15c8686f04ea73751294f40b8e0 gray16be 43bda75c197b0d59a9b87ee941553644 diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index c23187c595..baaf86cc08 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -25,6 +25,8 @@ gbrp12le 654861b1837d312569395f598da1a2a1 gbrp9be cbe1bf8ead497a92362a749bd4b0a57e gbrp9le f88c68df5d699a4a7f1b0152df9f25fe gray 8c941e9bbf6da5336384c57f15a4a454 +gray10be 69c8af356c3861792f9695fdff966629 +gray10le a97b97107bf03f27136abbaca074aa88 gray12be aecffce8ea67ab93527dc74c1a523454 gray12le eac4b15c8686f04ea73751294f40b8e0 gray16be 43bda75c197b0d59a9b87ee941553644 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index 0c73ec827a..1744e0c377 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -25,6 +25,8 @@ gbrp12le 735061c07442657580577d1cede3a636 gbrp9be 01c837e1def99abec205b80d21b68bf0 gbrp9le dd982d59c3d71c3b201f2d9363d8952c gray 4c571fb634a75f177b64cee168fbf3a1 +gray10be 6131685ecaf830d08d2e0dee7f9c9d41 +gray10le 6d398a3189f6b029a098393576af989c gray12be d237d56e08482038ebc5f3943d6ec8d5 gray12le dcd15a0ed89bd019cc367b552fc9b1c0 gray16be 9b57ff7d2090b47e4427bee79dba0d9e diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 184793000a..b1c5f8946c 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -25,6 +25,8 @@ gbrp12le b7b27715bc9054a93ba81f110cf42ee5 gbrp9be 2ae8f0d3b079d6550a2b1d4a7c4a6e4b gbrp9le c62df0f386c957cc9cacb3c8014542eb gray 684ba667effbbf5983f46a9bea4afaae +gray10be 394b31c05242c3a381f444a84bb327a1 +gray10le 21e14d72eb5b5d1adb2375e0a7417252 gray12be e33397832d19ec628f3e887e0a16ccc7 gray12le c8a8d7267e2595a0c4ce5d582bea23a1 gray16be 112077b2f1c85cbd44907ed271901b28 From 9bf9358b615dbf3d0f81ca2dbfbec6103dc77f25 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Nov 2018 01:11:22 -0300 Subject: [PATCH 07/10] avcodec: libdav1d AV1 decoder wrapper. Originally written by Ronald S. Bultje, with fixes, optimizations and improvements by James Almer. Signed-off-by: James Almer --- Changelog | 1 + configure | 4 + doc/general.texi | 12 +- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libdav1d.c | 269 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 7 files changed, 285 insertions(+), 5 deletions(-) create mode 100644 libavcodec/libdav1d.c diff --git a/Changelog b/Changelog index 27a4d4eee3..773f640e0c 100644 --- a/Changelog +++ b/Changelog @@ -25,6 +25,7 @@ version : - Dropped support for building for Windows XP. The minimum supported Windows version is Windows Vista. - support mbedTLS-based TLS +- AV1 Support through libdav1d version 12: diff --git a/configure b/configure index 2aa7eb627f..c5bafc3822 100755 --- a/configure +++ b/configure @@ -190,6 +190,7 @@ External library support: --enable-libaom AV1 video encoding/decoding --enable-libbs2b Bauer stereophonic-to-binaural DSP --enable-libcdio audio CD input + --enable-libdav1d AV1 video decoding --enable-libdc1394 IEEE 1394/Firewire camera input --enable-libdcadec DCA audio decoding --enable-libfaac AAC audio encoding @@ -1357,6 +1358,7 @@ EXTERNAL_LIBRARY_LIST=" gnutls libaom libbs2b + libdav1d libdc1394 libdcadec libfontconfig @@ -2372,6 +2374,7 @@ avisynth_demuxer_deps_any="avisynth avxsynth" avisynth_demuxer_select="riffdec" libaom_av1_decoder_deps="libaom" libaom_av1_encoder_deps="libaom" +libdav1d_decoder_deps="libdav1d" libdcadec_decoder_deps="libdcadec" libfaac_encoder_deps="libfaac" libfaac_encoder_select="audio_frame_queue" @@ -4673,6 +4676,7 @@ enabled libaom && { } enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new +enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.0.1" dav1d/dav1d.h dav1d_version enabled libdcadec && require libdcadec libdcadec/dca_context.h dcadec_context_create -ldcadec enabled libfaac && require libfaac "stdint.h faac.h" faacEncGetVersion -lfaac enabled libfdk_aac && require_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen diff --git a/doc/general.texi b/doc/general.texi index e066b42187..6a21a8b794 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -18,12 +18,16 @@ explicitly requested by passing the appropriate flags to @section Alliance for Open Media libaom -Libav can make use of the libaom library for AV1 decoding. +Libav can make use of the libaom and libdav1d libraries for AV1 decoding. Go to @url{http://aomedia.org/} and follow the instructions for -installing the library. Then pass @code{--enable-libaom} to configure to +installing libaom. Then pass @code{--enable-libaom} to configure to enable it. +Go to @url{https://code.videolan.org/videolan/dav1d/} and follow the +instructions for installing libdav1d. Then pass @code{--enable-libdav1d} +to configure to enable it. + @section OpenCORE and VisualOn libraries Spun off Google Android sources, OpenCore, VisualOn and Fraunhofer @@ -625,8 +629,8 @@ following image formats are supported: @item Autodesk Animator Flic video @tab @tab X @item Autodesk RLE @tab @tab X @tab fourcc: AASC -@item AV1 @tab @tab E - @tab Supported through external library libaom +@item AV1 @tab E @tab E + @tab Supported through external libraries libaom and libdav1d @item AVS (Audio Video Standard) video @tab @tab X @tab Video encoding used by the Creature Shock game. @item Beam Software VB @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ea0c9dceae..ae35628840 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -689,6 +689,7 @@ OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # external codec libraries OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o +OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o OBJS-$(CONFIG_LIBDCADEC_DECODER) += libdcadec.o dca.o OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4aee65762e..f38ea19f4c 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -422,6 +422,7 @@ void avcodec_register_all(void) /* external libraries */ REGISTER_ENCDEC (LIBAOM_AV1, libaom_av1); + REGISTER_DECODER(LIBDAV1D, libdav1d) REGISTER_DECODER(LIBDCADEC, libdcadec) REGISTER_ENCODER(LIBFAAC, libfaac); REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac); diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c new file mode 100644 index 0000000000..ad4611fb9c --- /dev/null +++ b/libavcodec/libdav1d.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2018 Ronald S. Bultje + * Copyright (c) 2018 James Almer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/fifo.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "decode.h" +#include "internal.h" + +typedef struct Libdav1dContext { + AVClass *class; + Dav1dContext *c; + + AVFifoBuffer *cache; + Dav1dData data; + int tile_threads; +} Libdav1dContext; + +static av_cold int libdav1d_init(AVCodecContext *c) +{ + Libdav1dContext *dav1d = c->priv_data; + Dav1dSettings s; + int res; + + av_log(c, AV_LOG_INFO, "libdav1d %s\n", dav1d_version()); + + dav1d_default_settings(&s); + s.n_tile_threads = dav1d->tile_threads; + s.n_frame_threads = FFMIN(c->thread_count ? c->thread_count : av_cpu_count(), 256); + + dav1d->cache = av_fifo_alloc(8 * sizeof(AVPacket)); + if (!dav1d->cache) + return AVERROR(ENOMEM); + + res = dav1d_open(&dav1d->c, &s); + if (res < 0) + return AVERROR(ENOMEM); + + return 0; +} + +static void libdav1d_flush(AVCodecContext *c) +{ + Libdav1dContext *dav1d = c->priv_data; + + av_fifo_reset(dav1d->cache); + dav1d_data_unref(&dav1d->data); + dav1d_flush(dav1d->c); +} + +static int libdav1d_fifo_write(void *src, void *dst, int dst_size) { + AVPacket *pkt_dst = dst, *pkt_src = src; + + av_assert2(dst_size >= sizeof(AVPacket)); + + pkt_src->buf = NULL; + av_packet_free_side_data(pkt_src); + *pkt_dst = *pkt_src; + + return sizeof(AVPacket); +} + +static void libdav1d_data_free(const uint8_t *data, void *opaque) { + AVBufferRef *buf = opaque; + + av_buffer_unref(&buf); +} + +static void libdav1d_frame_free(void *opaque, uint8_t *data) { + Dav1dPicture p = { 0 }; + + p.ref = opaque; + p.data[0] = (void *) 0x1; // this has to be non-NULL + dav1d_picture_unref(&p); +} + +static const enum AVPixelFormat pix_fmt[][2] = { + [DAV1D_PIXEL_LAYOUT_I400] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10 }, + [DAV1D_PIXEL_LAYOUT_I420] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10 }, + [DAV1D_PIXEL_LAYOUT_I422] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10 }, + [DAV1D_PIXEL_LAYOUT_I444] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10 }, +}; + +// TODO: Update once 12bit support is added. +static const int profile[] = { + [DAV1D_PIXEL_LAYOUT_I400] = FF_PROFILE_AV1_MAIN, + [DAV1D_PIXEL_LAYOUT_I420] = FF_PROFILE_AV1_MAIN, + [DAV1D_PIXEL_LAYOUT_I422] = FF_PROFILE_AV1_PROFESSIONAL, + [DAV1D_PIXEL_LAYOUT_I444] = FF_PROFILE_AV1_HIGH, +}; + +static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) +{ + Libdav1dContext *dav1d = c->priv_data; + Dav1dData *data = &dav1d->data; + AVPacket pkt = { 0 }; + Dav1dPicture p = { 0 }; + int res; + + if (!data->sz) { + res = ff_decode_get_packet(c, &pkt); + if (res < 0 && res != AVERROR_EOF) + return res; + + if (pkt.size) { + if (!av_fifo_space(dav1d->cache)) { + res = av_fifo_realloc2(dav1d->cache, av_fifo_size(dav1d->cache) + 8 * sizeof(pkt)); + if (res < 0) { + av_packet_unref(&pkt); + return res; + } + } + + res = dav1d_data_wrap(data, pkt.data, pkt.size, libdav1d_data_free, pkt.buf); + if (res < 0) { + av_packet_unref(&pkt); + return res; + } + + av_fifo_generic_write(dav1d->cache, &pkt, sizeof(pkt), libdav1d_fifo_write); + } else { + data = NULL; + } + } + + res = dav1d_decode(dav1d->c, data, &p); + if (res < 0) { + if (res == -EINVAL) + res = AVERROR_INVALIDDATA; + else if (res == -EAGAIN && c->internal->draining) + res = AVERROR_EOF; + + return res; + } + + av_assert0(p.data[0] != NULL); + + av_fifo_generic_read(dav1d->cache, &pkt, sizeof(pkt), NULL); + + frame->buf[0] = av_buffer_create(NULL, 0, libdav1d_frame_free, + p.ref, AV_BUFFER_FLAG_READONLY); + if (!frame->buf[0]) { + dav1d_picture_unref(&p); + return AVERROR(ENOMEM); + } + + frame->data[0] = p.data[0]; + frame->data[1] = p.data[1]; + frame->data[2] = p.data[2]; + frame->linesize[0] = p.stride[0]; + frame->linesize[1] = p.stride[1]; + frame->linesize[2] = p.stride[1]; + + c->profile = profile[p.p.layout]; + frame->format = c->pix_fmt = pix_fmt[p.p.layout][p.p.bpc == 10]; + frame->width = p.p.w; + frame->height = p.p.h; + if (c->width != p.p.w || c->height != p.p.h) { + res = ff_set_dimensions(c, p.p.w, p.p.h); + if (res < 0) + return res; + } + + switch (p.p.chr) { + case DAV1D_CHR_VERTICAL: + frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_LEFT; + break; + case DAV1D_CHR_COLOCATED: + frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_TOPLEFT; + break; + } + frame->colorspace = c->colorspace = (enum AVColorSpace) p.p.mtrx; + frame->color_primaries = c->color_primaries = (enum AVColorPrimaries) p.p.pri; + frame->color_trc = c->color_trc = (enum AVColorTransferCharacteristic) p.p.trc; + frame->color_range = c->color_range = p.p.fullrange ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + + // match timestamps and packet size + frame->pts = pkt.pts; +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_pts = pkt.pts; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->pkt_dts = pkt.dts; + frame->key_frame = p.p.type == DAV1D_FRAME_TYPE_KEY; + + switch (p.p.type) { + case DAV1D_FRAME_TYPE_KEY: + case DAV1D_FRAME_TYPE_INTRA: + frame->pict_type = AV_PICTURE_TYPE_I; + break; + case DAV1D_FRAME_TYPE_INTER: + frame->pict_type = AV_PICTURE_TYPE_P; + break; + case DAV1D_FRAME_TYPE_SWITCH: + frame->pict_type = AV_PICTURE_TYPE_SP; + break; + default: + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static av_cold int libdav1d_close(AVCodecContext *c) +{ + Libdav1dContext *dav1d = c->priv_data; + + av_fifo_free(dav1d->cache); + dav1d_data_unref(&dav1d->data); + dav1d_close(&dav1d->c); + + return 0; +} + +#define OFFSET(x) offsetof(Libdav1dContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption libdav1d_options[] = { + { "tilethreads", "Tile threads", OFFSET(tile_threads), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 64, VD, NULL }, + { NULL } +}; + +static const AVClass libdav1d_class = { + .class_name = "libdav1d decoder", + .item_name = av_default_item_name, + .option = libdav1d_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libdav1d_decoder = { + .name = "libdav1d", + .long_name = NULL_IF_CONFIG_SMALL("dav1d AV1 decoder by VideoLAN"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .priv_data_size = sizeof(Libdav1dContext), + .init = libdav1d_init, + .close = libdav1d_close, + .flush = libdav1d_flush, + .receive_frame = libdav1d_receive_frame, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SETS_PKT_DTS, + .priv_class = &libdav1d_class, + .wrapper_name = "libdav1d", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 29ff4d3ad0..61afbec438 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 11 +#define LIBAVCODEC_VERSION_MINOR 12 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From e716323fa8526c7243ce73edd077761dc40e5f86 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Mon, 5 Nov 2018 10:28:59 +0800 Subject: [PATCH 08/10] qsvenc: Add VDENC support for H264 and HEVC Add VDENC(lowpower mode) support for QSV h264 and HEVC It's an experimental function(like lowpower in vaapi) with some limitations: - CBR/VBR require HuC which should be explicitly loaded via i915 module parameter(i915.enable_guc=2 for linux kerner version >= 4.16) - HEVC VDENC was supported >= ICE LAKE use option "-low_power 1" to enable VDENC. Signed-off-by: Linjie Fu --- libavcodec/qsvenc.c | 3 +++ libavcodec/qsvenc.h | 2 ++ libavcodec/qsvenc_h264.c | 3 +++ libavcodec/qsvenc_hevc.c | 3 +++ 4 files changed, 11 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 17a0559f36..16d6e79e2b 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -472,6 +472,9 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) } } +#if QSV_HAVE_VDENC + q->param.mfx.LowPower = q->low_power ? MFX_CODINGOPTION_ON:MFX_CODINGOPTION_OFF; +#endif q->param.mfx.CodecProfile = q->profile; q->param.mfx.TargetUsage = avctx->compression_level; q->param.mfx.GopPicSize = FFMAX(0, avctx->gop_size); diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 2d83c7b1af..b74b977e88 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -44,6 +44,7 @@ #define QSV_HAVE_LA QSV_VERSION_ATLEAST(1, 7) #define QSV_HAVE_LA_DS QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_LA_HRD QSV_VERSION_ATLEAST(1, 11) +#define QSV_HAVE_VDENC QSV_VERSION_ATLEAST(1, 15) #if defined(_WIN32) #define QSV_HAVE_AVBR QSV_VERSION_ATLEAST(1, 3) @@ -159,6 +160,7 @@ typedef struct QSVEncContext { int int_ref_cycle_size; int int_ref_qp_delta; int recovery_point_sei; + int low_power; #if QSV_HAVE_MF int mfmode; diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 164f57332f..795e27c002 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -101,6 +101,9 @@ static const AVOption options[] = { { "off" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_MF_DISABLED }, INT_MIN, INT_MAX, VE, "mfmode" }, { "auto" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_MF_AUTO }, INT_MIN, INT_MAX, VE, "mfmode" }, #endif +#if QSV_HAVE_VDENC + { "low_power", "enable low power mode (experimental, many limitations by mfx version, HW platform, BRC modes, etc.", OFFSET(qsv.low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, +#endif { NULL }, }; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 471d174873..cba671bb90 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -238,6 +238,9 @@ static const AVOption options[] = { { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, { "mainsp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAINSP }, INT_MIN, INT_MAX, VE, "profile" }, +#if QSV_HAVE_VDENC + { "low_power", "enable low power mode (experimental, many limitations by mfx version, HW platform, BRC modes, etc.", OFFSET(qsv.low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, +#endif { NULL }, }; From 56f50183f38087e53c07cb670e5793f200d84d18 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 14 Nov 2018 22:04:35 -0300 Subject: [PATCH 09/10] libdav1d: fix build after a recent API break Signed-off-by: James Almer --- libavcodec/libdav1d.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index ad4611fb9c..3501c15e22 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -142,12 +142,18 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) } av_fifo_generic_write(dav1d->cache, &pkt, sizeof(pkt), libdav1d_fifo_write); - } else { - data = NULL; } } - res = dav1d_decode(dav1d->c, data, &p); + res = dav1d_send_data(dav1d->c, data); + if (res < 0) { + if (res == -EINVAL) + res = AVERROR_INVALIDDATA; + if (res != -EAGAIN) + return res; + } + + res = dav1d_get_picture(dav1d->c, &p); if (res < 0) { if (res == -EINVAL) res = AVERROR_INVALIDDATA; From 70ab2778be9c83dab84340af7e3ba83fa0f98576 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 11 Dec 2018 12:59:09 -0300 Subject: [PATCH 10/10] libdav1d: update API usage to the first stable release The color fields were moved to another struct, and a way to propagate timestamps and other input metadata was introduced, so the packet fifo can be removed. Add support for 12bit streams, an option to disable film grain, and read the profile from the sequence header referenced by the ouput picture instead of guessing based on output pix_fmt. Signed-off-by: James Almer --- configure | 2 +- libavcodec/libdav1d.c | 90 ++++++++++++++----------------------------- libavcodec/version.h | 2 +- 3 files changed, 31 insertions(+), 63 deletions(-) diff --git a/configure b/configure index c5bafc3822..26455054ba 100755 --- a/configure +++ b/configure @@ -4676,7 +4676,7 @@ enabled libaom && { } enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new -enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.0.1" dav1d/dav1d.h dav1d_version +enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.1.0" dav1d/dav1d.h dav1d_version enabled libdcadec && require libdcadec libdcadec/dca_context.h dcadec_context_create -ldcadec enabled libfaac && require libfaac "stdint.h faac.h" faacEncGetVersion -lfaac enabled libfdk_aac && require_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 3501c15e22..99390d527c 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -22,7 +22,6 @@ #include #include "libavutil/avassert.h" -#include "libavutil/fifo.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -35,9 +34,9 @@ typedef struct Libdav1dContext { AVClass *class; Dav1dContext *c; - AVFifoBuffer *cache; Dav1dData data; int tile_threads; + int apply_grain; } Libdav1dContext; static av_cold int libdav1d_init(AVCodecContext *c) @@ -50,11 +49,8 @@ static av_cold int libdav1d_init(AVCodecContext *c) dav1d_default_settings(&s); s.n_tile_threads = dav1d->tile_threads; - s.n_frame_threads = FFMIN(c->thread_count ? c->thread_count : av_cpu_count(), 256); - - dav1d->cache = av_fifo_alloc(8 * sizeof(AVPacket)); - if (!dav1d->cache) - return AVERROR(ENOMEM); + s.apply_grain = dav1d->apply_grain; + s.n_frame_threads = FFMIN(c->thread_count ? c->thread_count : av_cpu_count(), DAV1D_MAX_FRAME_THREADS); res = dav1d_open(&dav1d->c, &s); if (res < 0) @@ -67,23 +63,10 @@ static void libdav1d_flush(AVCodecContext *c) { Libdav1dContext *dav1d = c->priv_data; - av_fifo_reset(dav1d->cache); dav1d_data_unref(&dav1d->data); dav1d_flush(dav1d->c); } -static int libdav1d_fifo_write(void *src, void *dst, int dst_size) { - AVPacket *pkt_dst = dst, *pkt_src = src; - - av_assert2(dst_size >= sizeof(AVPacket)); - - pkt_src->buf = NULL; - av_packet_free_side_data(pkt_src); - *pkt_dst = *pkt_src; - - return sizeof(AVPacket); -} - static void libdav1d_data_free(const uint8_t *data, void *opaque) { AVBufferRef *buf = opaque; @@ -98,50 +81,38 @@ static void libdav1d_frame_free(void *opaque, uint8_t *data) { dav1d_picture_unref(&p); } -static const enum AVPixelFormat pix_fmt[][2] = { - [DAV1D_PIXEL_LAYOUT_I400] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10 }, - [DAV1D_PIXEL_LAYOUT_I420] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10 }, - [DAV1D_PIXEL_LAYOUT_I422] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10 }, - [DAV1D_PIXEL_LAYOUT_I444] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10 }, -}; - -// TODO: Update once 12bit support is added. -static const int profile[] = { - [DAV1D_PIXEL_LAYOUT_I400] = FF_PROFILE_AV1_MAIN, - [DAV1D_PIXEL_LAYOUT_I420] = FF_PROFILE_AV1_MAIN, - [DAV1D_PIXEL_LAYOUT_I422] = FF_PROFILE_AV1_PROFESSIONAL, - [DAV1D_PIXEL_LAYOUT_I444] = FF_PROFILE_AV1_HIGH, +static const enum AVPixelFormat pix_fmt[][3] = { + [DAV1D_PIXEL_LAYOUT_I400] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12 }, + [DAV1D_PIXEL_LAYOUT_I420] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12 }, + [DAV1D_PIXEL_LAYOUT_I422] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12 }, + [DAV1D_PIXEL_LAYOUT_I444] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12 }, }; static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) { Libdav1dContext *dav1d = c->priv_data; Dav1dData *data = &dav1d->data; - AVPacket pkt = { 0 }; Dav1dPicture p = { 0 }; int res; if (!data->sz) { + AVPacket pkt = { 0 }; + res = ff_decode_get_packet(c, &pkt); if (res < 0 && res != AVERROR_EOF) return res; if (pkt.size) { - if (!av_fifo_space(dav1d->cache)) { - res = av_fifo_realloc2(dav1d->cache, av_fifo_size(dav1d->cache) + 8 * sizeof(pkt)); - if (res < 0) { - av_packet_unref(&pkt); - return res; - } - } - res = dav1d_data_wrap(data, pkt.data, pkt.size, libdav1d_data_free, pkt.buf); if (res < 0) { av_packet_unref(&pkt); return res; } - av_fifo_generic_write(dav1d->cache, &pkt, sizeof(pkt), libdav1d_fifo_write); + data->m.timestamp = pkt.pts; + + pkt.buf = NULL; + av_packet_unref(&pkt); } } @@ -165,8 +136,6 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) av_assert0(p.data[0] != NULL); - av_fifo_generic_read(dav1d->cache, &pkt, sizeof(pkt), NULL); - frame->buf[0] = av_buffer_create(NULL, 0, libdav1d_frame_free, p.ref, AV_BUFFER_FLAG_READONLY); if (!frame->buf[0]) { @@ -181,8 +150,8 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) frame->linesize[1] = p.stride[1]; frame->linesize[2] = p.stride[1]; - c->profile = profile[p.p.layout]; - frame->format = c->pix_fmt = pix_fmt[p.p.layout][p.p.bpc == 10]; + c->profile = p.seq_hdr->profile; + frame->format = c->pix_fmt = pix_fmt[p.p.layout][p.seq_hdr->hbd]; frame->width = p.p.w; frame->height = p.p.h; if (c->width != p.p.w || c->height != p.p.h) { @@ -191,7 +160,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) return res; } - switch (p.p.chr) { + switch (p.seq_hdr->chr) { case DAV1D_CHR_VERTICAL: frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_LEFT; break; @@ -199,22 +168,22 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_TOPLEFT; break; } - frame->colorspace = c->colorspace = (enum AVColorSpace) p.p.mtrx; - frame->color_primaries = c->color_primaries = (enum AVColorPrimaries) p.p.pri; - frame->color_trc = c->color_trc = (enum AVColorTransferCharacteristic) p.p.trc; - frame->color_range = c->color_range = p.p.fullrange ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + frame->colorspace = c->colorspace = (enum AVColorSpace) p.seq_hdr->mtrx; + frame->color_primaries = c->color_primaries = (enum AVColorPrimaries) p.seq_hdr->pri; + frame->color_trc = c->color_trc = (enum AVColorTransferCharacteristic) p.seq_hdr->trc; + frame->color_range = c->color_range = p.seq_hdr->color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; // match timestamps and packet size - frame->pts = pkt.pts; + frame->pts = p.m.timestamp; #if FF_API_PKT_PTS FF_DISABLE_DEPRECATION_WARNINGS - frame->pkt_pts = pkt.pts; + frame->pkt_pts = p.m.timestamp; FF_ENABLE_DEPRECATION_WARNINGS #endif - frame->pkt_dts = pkt.dts; - frame->key_frame = p.p.type == DAV1D_FRAME_TYPE_KEY; + frame->pkt_dts = p.m.timestamp; + frame->key_frame = p.frame_hdr->frame_type == DAV1D_FRAME_TYPE_KEY; - switch (p.p.type) { + switch (p.frame_hdr->frame_type) { case DAV1D_FRAME_TYPE_KEY: case DAV1D_FRAME_TYPE_INTRA: frame->pict_type = AV_PICTURE_TYPE_I; @@ -236,7 +205,6 @@ static av_cold int libdav1d_close(AVCodecContext *c) { Libdav1dContext *dav1d = c->priv_data; - av_fifo_free(dav1d->cache); dav1d_data_unref(&dav1d->data); dav1d_close(&dav1d->c); @@ -246,7 +214,8 @@ static av_cold int libdav1d_close(AVCodecContext *c) #define OFFSET(x) offsetof(Libdav1dContext, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption libdav1d_options[] = { - { "tilethreads", "Tile threads", OFFSET(tile_threads), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 64, VD, NULL }, + { "tilethreads", "Tile threads", OFFSET(tile_threads), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, DAV1D_MAX_TILE_THREADS, VD }, + { "filmgrain", "Apply Film Grain", OFFSET(apply_grain), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VD }, { NULL } }; @@ -268,8 +237,7 @@ AVCodec ff_libdav1d_decoder = { .flush = libdav1d_flush, .receive_frame = libdav1d_receive_frame, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | - FF_CODEC_CAP_SETS_PKT_DTS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS, .priv_class = &libdav1d_class, .wrapper_name = "libdav1d", }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 61afbec438..831a2491a4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 12 -#define LIBAVCODEC_VERSION_MICRO 0 +#define LIBAVCODEC_VERSION_MICRO 1 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \