Skip to content

Commit

Permalink
support non 4:2:0 input in FFmpeg >= 4.1
Browse files Browse the repository at this point in the history
Fall back to P010LE for 10 bit depth data and NV12 otherwise.

This may possibly lead to some loss of information
on modern hardware supporting 4:2:2 and 4:4:4 chroma subsampling
(e.g. HEVC with >= IceLake and 4:2:2 or 4:4:4 input).

Related to #26
  • Loading branch information
bmegli committed Feb 14, 2021
1 parent 98be90d commit 777a048
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion hve.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct hve
};

static int init_hwframes_context(struct hve* h, const struct hve_config *config);
static int hve_pixel_format_depth( enum AVPixelFormat pix_fmt, int *depth);
static struct hve *hve_close_and_return_null(struct hve *h, const char *msg);
static int HVE_ERROR_MSG(const char *msg);

Expand Down Expand Up @@ -165,10 +166,25 @@ static int init_hwframes_context(struct hve* h, const struct hve_config *config)

frames_ctx = (AVHWFramesContext*)(hw_frames_ref->data);
frames_ctx->format = AV_PIX_FMT_VAAPI;
frames_ctx->sw_format = h->sw_pix_fmt;
frames_ctx->width = config->width;
frames_ctx->height = config->height;
frames_ctx->initial_pool_size = 20;
frames_ctx->sw_format = AV_PIX_FMT_NV12;

// Starting from FFmpeg 4.1, avcodec will not fall back to NV12 automatically
// when using non 4:2:0 software pixel format not supported by codec.
// Here, instead of using h->sw_pix_fmt we always fall to P010LE for 10 bit
// input and NV12 otherwise which may possibly lead to some loss of information
// on modern hardware supporting 4:2:2 and 4:4:4 chroma subsampling
// (e.g. HEVC with >= IceLake)
// See:
// https://github.com/bmegli/hardware-video-encoder/issues/26
int depth;
if(hve_pixel_format_depth(h->sw_pix_fmt, &depth) != HVE_OK)
return HVE_ERROR_MSG("failed to get pixel format depth");

if(depth == 10)
frames_ctx->sw_format = AV_PIX_FMT_P010LE;

if((err = av_hwframe_ctx_init(hw_frames_ref)) < 0)
{
Expand All @@ -185,6 +201,22 @@ static int init_hwframes_context(struct hve* h, const struct hve_config *config)
return err == 0 ? HVE_OK : HVE_ERROR;
}

static int hve_pixel_format_depth(enum AVPixelFormat pix_fmt, int *depth)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
int i;

if (!desc || !desc->nb_components)
return HVE_ERROR;

*depth = -INT_MAX;

for (i = 0; i < desc->nb_components; i++)
*depth = FFMAX(desc->comp[i].depth, *depth);

return HVE_OK;
}

int hve_send_frame(struct hve *h,struct hve_frame *frame)
{
AVCodecContext* avctx=h->avctx;
Expand Down

0 comments on commit 777a048

Please sign in to comment.