Lavc: set range/colorspec to codec

This commit is contained in:
Martin Pulec
2020-09-25 15:27:04 +02:00
parent c5980d9557
commit 23ca8f37bd
3 changed files with 63 additions and 29 deletions

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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;
}