[FFmpeg-devel] [PATCH 5/7] vaapi_decode: Make the frames context format selection more general
Philip Langdale
philipl at overt.org
Tue Feb 20 02:55:32 EET 2018
On Mon, 19 Feb 2018 23:28:47 +0000
Mark Thompson <sw at jkqxz.net> wrote:
> Examine the supported fourcc list manually and make the best choice,
> then use the external attribute on the frames context to force that
> fourcc. ---
> libavcodec/vaapi_decode.c | 152
> +++++++++++++++++++++++++++++++++++++++-------
> libavcodec/vaapi_decode.h | 2 + 2 files changed, 132 insertions(+),
> 22 deletions(-)
>
> diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
> index 572b3a40ac..28c6eeb801 100644
> --- a/libavcodec/vaapi_decode.c
> +++ b/libavcodec/vaapi_decode.c
> @@ -232,6 +232,132 @@ int ff_vaapi_decode_cancel(AVCodecContext
> *avctx, return 0;
> }
>
> +static const struct {
> + uint32_t fourcc;
> + enum AVPixelFormat pix_fmt;
> +} vaapi_format_map[] = {
> +#define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
> + // 4:0:0
> + MAP(Y800, GRAY8),
> + // 4:2:0
> + MAP(NV12, NV12),
> + MAP(YV12, YUV420P),
> + MAP(IYUV, YUV420P),
> +#ifdef VA_FOURCC_I420
> + MAP(I420, YUV420P),
> +#endif
> + MAP(IMC3, YUV420P),
> + // 4:1:1
> + MAP(411P, YUV411P),
> + // 4:2:2
> + MAP(422H, YUV422P),
> +#ifdef VA_FOURCC_YV16
> + MAP(YV16, YUV422P),
> +#endif
> + // 4:4:0
> + MAP(422V, YUV440P),
> + // 4:4:4
> + MAP(444P, YUV444P),
> + // 4:2:0 10-bit
> +#ifdef VA_FOURCC_P010
> + MAP(P010, P010),
> +#endif
> +#ifdef VA_FOURCC_I010
> + MAP(I010, YUV420P10),
> +#endif
> +#undef MAP
> +};
> +
> +static int vaapi_decode_find_best_format(AVCodecContext *avctx,
> + AVHWDeviceContext *device,
> + VAConfigID config_id,
> + AVHWFramesContext *frames)
> +{
> + AVVAAPIDeviceContext *hwctx = device->hwctx;
> + VAStatus vas;
> + VASurfaceAttrib *attr;
> + enum AVPixelFormat source_format, best_format, format;
> + uint32_t best_fourcc, fourcc;
> + int i, j, nb_attr;
> +
> + source_format = avctx->sw_pix_fmt;
> + av_assert0(source_format != AV_PIX_FMT_NONE);
> +
> + vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
> + NULL, &nb_attr);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to query surface
> attributes: "
> + "%d (%s).\n", vas, vaErrorStr(vas));
> + return AVERROR(ENOSYS);
> + }
> +
> + attr = av_malloc_array(nb_attr, sizeof(*attr));
> + if (!attr)
> + return AVERROR(ENOMEM);
> +
> + vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
> + attr, &nb_attr);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to query surface
> attributes: "
> + "%d (%s).\n", vas, vaErrorStr(vas));
> + av_freep(&attr);
> + return AVERROR(ENOSYS);
> + }
> +
> + best_format = AV_PIX_FMT_NONE;
> +
> + for (i = 0; i < nb_attr; i++) {
> + if (attr[i].type != VASurfaceAttribPixelFormat)
> + continue;
> +
> + fourcc = attr[i].value.value.i;
> + for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) {
> + if (fourcc == vaapi_format_map[j].fourcc)
> + break;
> + }
> + if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) {
> + av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format
> %#x.\n",
> + fourcc);
> + continue;
> + }
> + format = vaapi_format_map[j].pix_fmt;
> + av_log(avctx, AV_LOG_DEBUG, "Considering format %#x ->
> %s.\n",
> + fourcc, av_get_pix_fmt_name(format));
> +
> + best_format = av_find_best_pix_fmt_of_2(format, best_format,
> + source_format, 0,
> NULL);
> + if (format == best_format)
> + best_fourcc = fourcc;
> + }
> +
> + av_freep(&attr);
> +
> + if (best_format == AV_PIX_FMT_NONE) {
> + av_log(avctx, AV_LOG_ERROR, "No usable formats for
> decoding!\n");
> + return AVERROR(EINVAL);
> + }
> +
> + av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for
> %s.\n",
> + av_get_pix_fmt_name(best_format), best_fourcc,
> + av_get_pix_fmt_name(source_format));
> +
> + frames->sw_format = best_format;
> + if (avctx->internal->hwaccel_priv_data) {
> + VAAPIDecodeContext *ctx =
> avctx->internal->hwaccel_priv_data;
> + AVVAAPIFramesContext *avfc = frames->hwctx;
> +
> + ctx->pixel_format_attribute = (VASurfaceAttrib) {
> + .type = VASurfaceAttribPixelFormat,
> + .value.value.i = best_fourcc,
> + };
> +
> + avfc->attributes = &ctx->pixel_format_attribute;
> + avfc->nb_attributes = 1;
> + }
> +
> + return 0;
> +}
> +
> static const struct {
> enum AVCodecID codec_id;
> int codec_profile;
> @@ -289,7 +415,6 @@ static int
> vaapi_decode_make_config(AVCodecContext *avctx, const
> AVCodecDescriptor *codec_desc; VAProfile *profile_list = NULL,
> matched_va_profile; int profile_count, exact_match,
> matched_ff_profile;
> - const AVPixFmtDescriptor *sw_desc, *desc;
>
> AVHWDeviceContext *device =
> (AVHWDeviceContext*)device_ref->data; AVVAAPIDeviceContext *hwctx =
> device->hwctx; @@ -417,27 +542,10 @@ static int
> vaapi_decode_make_config(AVCodecContext *avctx, frames->width =
> avctx->coded_width; frames->height = avctx->coded_height;
>
> - // Find the first format in the list which matches the
> expected
> - // bit depth and subsampling. If none are found (this can
> happen
> - // when 10-bit streams are decoded to 8-bit surfaces, for
> example)
> - // then just take the first format on the list.
> - frames->sw_format = constraints->valid_sw_formats[0];
> - sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
> - for (i = 0; constraints->valid_sw_formats[i] !=
> AV_PIX_FMT_NONE; i++) {
> - desc =
> av_pix_fmt_desc_get(constraints->valid_sw_formats[i]);
> - if (desc->nb_components != sw_desc->nb_components ||
> - desc->log2_chroma_w != sw_desc->log2_chroma_w ||
> - desc->log2_chroma_h != sw_desc->log2_chroma_h)
> - continue;
> - for (j = 0; j < desc->nb_components; j++) {
> - if (desc->comp[j].depth != sw_desc->comp[j].depth)
> - break;
> - }
> - if (j < desc->nb_components)
> - continue;
> - frames->sw_format = constraints->valid_sw_formats[i];
> - break;
> - }
> + err = vaapi_decode_find_best_format(avctx, device,
> + *va_config, frames);
> + if (err < 0)
> + goto fail;
>
> frames->initial_pool_size = 1;
> // Add per-codec number of surfaces used for storing
> reference frames. diff --git a/libavcodec/vaapi_decode.h
> b/libavcodec/vaapi_decode.h index 1fcecac468..6b415dd1d3 100644
> --- a/libavcodec/vaapi_decode.h
> +++ b/libavcodec/vaapi_decode.h
> @@ -72,6 +72,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
>
> enum AVPixelFormat surface_format;
> int surface_count;
> +
> + VASurfaceAttrib pixel_format_attribute;
> } VAAPIDecodeContext;
>
>
LGTM
--phil
More information about the ffmpeg-devel
mailing list