[FFmpeg-devel] [PATCH 3/3] avcodec/videotoolbox: restart decompression session on bad data errors

wm4 nfxjfg at googlemail.com
Fri Feb 17 08:00:11 EET 2017


On Thu, 16 Feb 2017 10:29:38 -0800
Aman Gupta <ffmpeg at tmm1.net> wrote:

> From: Aman Gupta <aman at tmm1.net>
> 
> On some platforms (observed on macOS Sierra with 12" macbook), the VT
> decoder will start returning errors when encountering an SPS change in
> the h264 bitstream. With this patch, the kVTVideoDecoderBadDataErr
> response from the decoder is caught and the decompression session is
> recreated with a new avcC. The "bad data" is then fed into the new
> decompression session so that it can be decoded correctly.
> 
> I discovered the underlying issue here by running ffmpeg with lldb,
> which causes macOS to display debug information from the VT hardware
> decoder on stderr. The following errors were shown, which indicated the
> need to restart the decoder session with a new SPS/avcC:
> 
>   ffmpeg[15127:4094995] GVA error: SPS mismatch ...
>   ffmpeg[15127:4094995] GVA error: AVF_PushMetaData, first field kAVF_QT0_SPSPPSBoundaryMarker
>   ffmpeg[15127:4094995] GVA error: pushMetaData, submitNewJobs
>   ffmpeg[15127:4094995] GVA warning: OutputQueueReadyCallback status = 1, buffer == 0x0
> 
> Tested with the following sample, which contains an SPS change midstream:
> http://tmm1.s3.amazonaws.com/videotoolbox/spschange.ts
> ---
>  libavcodec/videotoolbox.c | 28 ++++++++++++++++++++++++----
>  1 file changed, 24 insertions(+), 4 deletions(-)
> 
> diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
> index 9be7bee..159d98d 100644
> --- a/libavcodec/videotoolbox.c
> +++ b/libavcodec/videotoolbox.c
> @@ -38,6 +38,9 @@
>  
>  #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING  12
>  
> +static void videotoolbox_stop(AVCodecContext *avctx);
> +static int videotoolbox_start(AVCodecContext *avctx);
> +
>  static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
>  {
>      CVPixelBufferRef cv_buffer = (CVImageBufferRef)data;
> @@ -350,13 +353,25 @@ static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame)
>      int status;
>      AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
>      VTContext *vtctx = avctx->internal->hwaccel_priv_data;
> +    int retry;
>  
>      av_buffer_unref(&frame->buf[0]);
>  
>      if (!videotoolbox->session || !vtctx->bitstream)
>          return AVERROR_INVALIDDATA;
>  
> -    status = videotoolbox_session_decode_frame(avctx);
> +    for (retry = 0; retry < 2; retry++) {

Why retry?

> +        status = videotoolbox_session_decode_frame(avctx);
> +
> +        if (status == kVTVideoDecoderBadDataErr) {
> +            av_log(avctx, AV_LOG_DEBUG, "vt decoder got bad data error, restarting..\n");
> +            videotoolbox_stop(avctx);
> +            videotoolbox_start(avctx);

Wouldn't Bad Things happen if the session failed to create for some
reason?

> +            continue;
> +        } else {
> +            break;
> +        }
> +    }
>  
>      if (status) {
>          av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
> @@ -506,7 +521,7 @@ static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecT
>      return cm_fmt_desc;
>  }
>  
> -static int videotoolbox_default_init(AVCodecContext *avctx)
> +static int videotoolbox_start(AVCodecContext *avctx)
>  {
>      AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
>      OSStatus status;
> @@ -587,7 +602,12 @@ static int videotoolbox_default_init(AVCodecContext *avctx)
>      }
>  }
>  
> -static void videotoolbox_default_free(AVCodecContext *avctx)
> +static int videotoolbox_default_init(AVCodecContext *avctx)
> +{
> +    return videotoolbox_start(avctx);
> +}
> +
> +static void videotoolbox_stop(AVCodecContext *avctx)
>  {
>      AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
>      if (!videotoolbox)
> @@ -696,7 +716,7 @@ int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *
>  void av_videotoolbox_default_free(AVCodecContext *avctx)
>  {
>  
> -    videotoolbox_default_free(avctx);
> +    videotoolbox_stop(avctx);
>      av_freep(&avctx->hwaccel_context);
>  }
>  #endif /* CONFIG_VIDEOTOOLBOX */



More information about the ffmpeg-devel mailing list