From 23ca8f37bdfe5bd36dcf0a451b9760c17400927d Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Fri, 25 Sep 2020 15:27:04 +0200 Subject: [PATCH] Lavc: set range/colorspec to codec --- src/libavcodec_common.c | 65 ++++++++++++++++++------------- src/libavcodec_common.h | 8 +++- src/video_compress/libavcodec.cpp | 19 ++++++++- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/src/libavcodec_common.c b/src/libavcodec_common.c index 07cdd8b74..55cb4f93a 100644 --- a/src/libavcodec_common.c +++ b/src/libavcodec_common.c @@ -2369,36 +2369,36 @@ const struct uv_to_av_conversion *get_uv_to_av_conversions() { * conversions below the others. */ static const struct uv_to_av_conversion uv_to_av_conversions[] = { - { v210, AV_PIX_FMT_YUV420P10LE, v210_to_yuv420p10le }, - { v210, AV_PIX_FMT_YUV422P10LE, v210_to_yuv422p10le }, - { v210, AV_PIX_FMT_YUV444P10LE, v210_to_yuv444p10le }, - { v210, AV_PIX_FMT_YUV444P16LE, v210_to_yuv444p16le }, - { R10k, AV_PIX_FMT_YUV444P10LE, r10k_to_yuv444p10le }, - { R10k, AV_PIX_FMT_YUV444P12LE, r10k_to_yuv444p12le }, - { R10k, AV_PIX_FMT_YUV444P16LE, r10k_to_yuv444p16le }, - { R12L, AV_PIX_FMT_YUV444P16LE, r12l_to_yuv444p10le }, - { R12L, AV_PIX_FMT_YUV444P16LE, r12l_to_yuv444p12le }, - { R12L, AV_PIX_FMT_YUV444P16LE, r12l_to_yuv444p16le }, + { v210, AV_PIX_FMT_YUV420P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv420p10le }, + { v210, AV_PIX_FMT_YUV422P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv422p10le }, + { v210, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv444p10le }, + { v210, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv444p16le }, + { R10k, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p10le }, + { R10k, AV_PIX_FMT_YUV444P12LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p12le }, + { R10k, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p16le }, + { R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p10le }, + { R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p12le }, + { R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p16le }, #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 15, 100) // FFMPEG commit c2869b4640f - { v210, AV_PIX_FMT_P010LE, v210_to_p010le }, + { v210, AV_PIX_FMT_P010LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_p010le }, #endif - { UYVY, AV_PIX_FMT_YUV422P, uyvy_to_yuv422p }, - { UYVY, AV_PIX_FMT_YUVJ422P, uyvy_to_yuv422p }, - { UYVY, AV_PIX_FMT_YUV420P, uyvy_to_yuv420p }, - { UYVY, AV_PIX_FMT_YUVJ420P, uyvy_to_yuv420p }, - { UYVY, AV_PIX_FMT_NV12, uyvy_to_nv12 }, - { UYVY, AV_PIX_FMT_YUV444P, uyvy_to_yuv444p }, - { UYVY, AV_PIX_FMT_YUVJ444P, uyvy_to_yuv444p }, - { RGB, AV_PIX_FMT_BGR0, rgb_to_bgr0 }, - { RGB, AV_PIX_FMT_GBRP, rgb_to_gbrp }, - { RGBA, AV_PIX_FMT_GBRP, rgba_to_gbrp }, - { R10k, AV_PIX_FMT_BGR0, r10k_to_bgr0 }, - { R10k, AV_PIX_FMT_GBRP10LE, r10k_to_gbrp10le }, - { R10k, AV_PIX_FMT_YUV422P10LE, r10k_to_yuv422p10le }, + { UYVY, AV_PIX_FMT_YUV422P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv422p }, + { UYVY, AV_PIX_FMT_YUVJ422P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv422p }, + { UYVY, AV_PIX_FMT_YUV420P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv420p }, + { UYVY, AV_PIX_FMT_YUVJ420P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv420p }, + { UYVY, AV_PIX_FMT_NV12, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_nv12 }, + { UYVY, AV_PIX_FMT_YUV444P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv444p }, + { UYVY, AV_PIX_FMT_YUVJ444P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv444p }, + { RGB, AV_PIX_FMT_BGR0, AVCOL_SPC_RGB, AVCOL_RANGE_JPEG, rgb_to_bgr0 }, + { RGB, AV_PIX_FMT_GBRP, AVCOL_SPC_RGB, AVCOL_RANGE_JPEG, rgb_to_gbrp }, + { RGBA, AV_PIX_FMT_GBRP, AVCOL_SPC_RGB, AVCOL_RANGE_JPEG, rgba_to_gbrp }, + { R10k, AV_PIX_FMT_BGR0, AVCOL_SPC_RGB, AVCOL_RANGE_JPEG, r10k_to_bgr0 }, + { R10k, AV_PIX_FMT_GBRP10LE, AVCOL_SPC_RGB, AVCOL_RANGE_JPEG, r10k_to_gbrp10le }, + { R10k, AV_PIX_FMT_YUV422P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv422p10le }, #ifdef HAVE_12_AND_14_PLANAR_COLORSPACES - { R12L, AV_PIX_FMT_GBRP12LE, r12l_to_gbrp12le }, + { R12L, AV_PIX_FMT_GBRP12LE, AVCOL_SPC_RGB, AVCOL_RANGE_JPEG, r12l_to_gbrp12le }, #endif - { 0, 0, 0 } + { 0, 0, 0, 0, 0 } }; return uv_to_av_conversions; } @@ -2415,6 +2415,19 @@ pixfmt_callback_t get_uv_to_av_conversion(codec_t uv_codec, int av_codec) { return NULL; } +void get_av_pixfmt_details(codec_t uv_codec, int av_codec, enum AVColorSpace *colorspace, enum AVColorRange *color_range) +{ + for (const struct uv_to_av_conversion *conversions = get_uv_to_av_conversions(); + conversions->func != 0; conversions++) { + if (conversions->dst == av_codec && + conversions->src == uv_codec) { + *colorspace = conversions->colorspace; + *color_range = conversions->color_range; + return; + } + } +} + /** * @brief returns list of available conversion. Terminated by uv_to_av_conversion::uv_codec == VIDEO_CODEC_NONE */ diff --git a/src/libavcodec_common.h b/src/libavcodec_common.h index 6198d57f5..b6ec11f4f 100644 --- a/src/libavcodec_common.h +++ b/src/libavcodec_common.h @@ -189,10 +189,16 @@ typedef uv_to_av_convert *pixfmt_callback_t; struct uv_to_av_conversion { codec_t src; enum AVPixelFormat dst; - pixfmt_callback_t func; + enum AVColorSpace colorspace; ///< destination colorspace + enum AVColorRange color_range; ///< destination color range + pixfmt_callback_t func; ///< conversion function }; const struct uv_to_av_conversion *get_uv_to_av_conversions(void); pixfmt_callback_t get_uv_to_av_conversion(codec_t uv_codec, int av_codec); +/** + * Returns AV format details for given pair UV,AV codec (must be unique then) + */ +void get_av_pixfmt_details(codec_t uv_codec, int av_codec, enum AVColorSpace *colorspace, enum AVColorRange *color_range); typedef void av_to_uv_convert(char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, int * __restrict rgb_shift); typedef av_to_uv_convert *av_to_uv_convert_p; diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index 446fb9a31..0738c6297 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -937,7 +937,7 @@ static bool try_open_codec(struct state_video_compress_libav *s, AVPixelFormat &pix_fmt, struct video_desc desc, codec_t ug_codec, - AVCodec *codec) + const AVCodec *codec) { // avcodec_alloc_context3 allocates context and sets default value s->codec_ctx = avcodec_alloc_context3(codec); @@ -967,6 +967,13 @@ static bool try_open_codec(struct state_video_compress_libav *s, pix_fmt = AV_PIX_FMT_NV12; } #endif + + if (const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt)) { // defaults + s->codec_ctx->colorspace = (desc->flags & AV_PIX_FMT_FLAG_RGB) != 0U ? AVCOL_SPC_RGB : AVCOL_SPC_BT709; + s->codec_ctx->color_range = (desc->flags & AV_PIX_FMT_FLAG_RGB) != 0U ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + } + get_av_pixfmt_details(ug_codec, pix_fmt, &s->codec_ctx->colorspace, &s->codec_ctx->color_range); + /* open it */ pthread_mutex_lock(s->lavcd_global_lock); if (avcodec_open2(s->codec_ctx, codec, NULL) < 0) { @@ -976,8 +983,16 @@ static bool try_open_codec(struct state_video_compress_libav *s, pthread_mutex_unlock(s->lavcd_global_lock); return false; } - pthread_mutex_unlock(s->lavcd_global_lock); + + // setting again for JPEG encoder because avcodec_open2 overrides color_range from MPEG to JPEG for YUVJ* pix_fmts + if (pix_fmt == AV_PIX_FMT_YUVJ420P || pix_fmt == AV_PIX_FMT_YUVJ411P || pix_fmt == AV_PIX_FMT_YUVJ422P || pix_fmt == AV_PIX_FMT_YUVJ440P || pix_fmt == AV_PIX_FMT_YUVJ444P) { + if (const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt)) { // defaults + s->codec_ctx->colorspace = (desc->flags & AV_PIX_FMT_FLAG_RGB) != 0U ? AVCOL_SPC_RGB : AVCOL_SPC_BT709; + s->codec_ctx->color_range = (desc->flags & AV_PIX_FMT_FLAG_RGB) != 0U ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + } + get_av_pixfmt_details(ug_codec, pix_fmt, &s->codec_ctx->colorspace, &s->codec_ctx->color_range); + } return true; }