Hi,

2014-09-03 18:30 GMT+02:00 Rémi Denis-Courmont <[email protected]>:
> This allows the application to fallback to another hwaccel, or more
> likely, to software decoding.
> ---
>  libavcodec/utils.c | 46 ++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 36 insertions(+), 10 deletions(-)
>
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index c5fa50d..317e90f 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -902,11 +902,26 @@ static AVHWAccel *find_hwaccel(enum AVCodecID codec_id,
>  int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
>  {
>      const AVPixFmtDescriptor *desc;
> -    enum AVPixelFormat ret = avctx->get_format(avctx, fmt);
> +    enum AVPixelFormat *choices;
> +    enum AVPixelFormat ret;
> +    unsigned n = 0;
> +
> +    while (fmt[n] != AV_PIX_FMT_NONE)
> +        ++n;
> +
> +    choices = av_malloc(++n * sizeof(*choices));
> +    if (choices == NULL)
> +        return AV_PIX_FMT_NONE;
> +
> +    memcpy(choices, fmt, n * sizeof(*choices));
> +retry:
> +    ret = avctx->get_format(avctx, choices);
>
>      desc = av_pix_fmt_desc_get(ret);
> -    if (!desc)
> +    if (!desc) {
> +        av_freep(&choices);
>          return AV_PIX_FMT_NONE;
> +    }
>
>      if (avctx->hwaccel && avctx->hwaccel->uninit)
>          avctx->hwaccel->uninit(avctx);
> @@ -915,32 +930,43 @@ int ff_get_format(AVCodecContext *avctx, const enum 
> AVPixelFormat *fmt)
>
>      if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
>          AVHWAccel *hwaccel;
> -        int err;
> +        int err = 0;
>
>          hwaccel = find_hwaccel(avctx->codec_id, ret);
>          if (!hwaccel) {
>              av_log(avctx, AV_LOG_ERROR,
>                     "Could not find an AVHWAccel for the pixel format: %s",
>                     desc->name);
> -            return AV_PIX_FMT_NONE;
> +            err = AVERROR(ENOENT);
>          }
>
> -        if (hwaccel->priv_data_size) {
> +        if (err == 0 && hwaccel->priv_data_size) {
>              avctx->internal->hwaccel_priv_data = 
> av_mallocz(hwaccel->priv_data_size);
>              if (!avctx->internal->hwaccel_priv_data)
> -                return AV_PIX_FMT_NONE;
> +                err = AVERROR(ENOMEM);
>          }
>
> -        if (hwaccel->init) {
> +        if (err == 0 && hwaccel->init) {
>              err = hwaccel->init(avctx);
> -            if (err < 0) {
> +            if (err < 0)
>                  av_freep(&avctx->internal->hwaccel_priv_data);
> -                return AV_PIX_FMT_NONE;
> -            }
> +        }
> +
> +        if (err < 0) {
> +            /* Remove failed hwaccel from choices and reiterate */
> +            for (n = 0; fmt[n] != ret; n++)
> +                av_assert0(fmt[n] != AV_PIX_FMT_NONE);
> +
> +            do
> +                choices[n] = fmt[n + 1];
> +            while (choices[n] != AV_PIX_FMT_NONE);
> +
> +            goto retry;
>          }
>          avctx->hwaccel = hwaccel;
>      }

My eyes are small, I didn't sleep well but I don't think this part is
correct. s/fmt/choices/ or you risk to fail on second iteration by
getting a random index based off fmt[] instead of choices[]?

>
> +    av_freep(&choices);
>      return ret;
>  }
>
> --
> 1.8.1.5
>
> _______________________________________________
> libav-devel mailing list
> [email protected]
> https://lists.libav.org/mailman/listinfo/libav-devel


Regards,
-- 
Gwenole Beauchesne
Intel Corporation SAS / 2 rue de Paris, 92196 Meudon Cedex, France
Registration Number (RCS): Nanterre B 302 456 199
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to