Merge commit 'aa9d15d89bb4ee8a31607d3db1b8c5334eb88d2d'
authorMichael Niedermayer <michael@niedermayer.cc>
Sat, 25 Jul 2015 21:10:14 +0000 (23:10 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Sat, 25 Jul 2015 21:10:14 +0000 (23:10 +0200)
* commit 'aa9d15d89bb4ee8a31607d3db1b8c5334eb88d2d':
  qsvdec: avoid an infinite loop with no consumed data and no output

Conflicts:
libavcodec/qsvdec.c

Merged-by: Michael Niedermayer <michael@niedermayer.cc>
1  2 
libavcodec/qsvdec.c

@@@ -308,52 -229,45 +308,59 @@@ int ff_qsv_decode(AVCodecContext *avctx
          ret = get_surface(avctx, q, &insurf);
          if (ret < 0)
              return ret;
 -
 -        ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
 -                                              insurf, &outsurf, &sync);
 -        if (ret == MFX_WRN_DEVICE_BUSY)
 +        do {
 +            ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
 +                                                  insurf, &outsurf, &sync);
 +            if (ret != MFX_WRN_DEVICE_BUSY)
 +                break;
              av_usleep(1);
 +        } while (1);
  
 -    } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
 +        if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
 +            /* TODO: handle here sequence header changing */
 +        }
  
 -    if (ret != MFX_ERR_NONE &&
 -        ret != MFX_ERR_MORE_DATA &&
 -        ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
 -        ret != MFX_ERR_MORE_SURFACE) {
 -        av_log(avctx, AV_LOG_ERROR, "Error during QSV decoding.\n");
 -        return ff_qsv_error(ret);
 +        if (sync) {
 +            QSVFrame *out_frame = find_frame(q, outsurf);
 +
 +            if (!out_frame) {
 +                av_log(avctx, AV_LOG_ERROR,
 +                       "The returned surface does not correspond to any frame\n");
 +                return AVERROR_BUG;
 +            }
 +
 +            out_frame->queued = 1;
 +            av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
 +            av_fifo_generic_write(q->async_fifo, &sync,      sizeof(sync),      NULL);
 +
 +            continue;
 +        }
 +        if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
 +            break;
      }
  
 -    if (sync) {
 -        QSVFrame *out_frame = find_frame(q, outsurf);
 -
 -        if (!out_frame) {
 -            av_log(avctx, AV_LOG_ERROR,
 -                   "The returned surface does not correspond to any frame\n");
 -            return AVERROR_BUG;
 -        }
+     /* make sure we do not enter an infinite loop if the SDK
+      * did not consume any data and did not return anything */
+     if (!sync && !bs.DataOffset) {
+         av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
+         bs.DataOffset = avpkt->size;
+     }
 +    if (buffered) {
 +        qsv_fifo_relocate(q->input_fifo, bs.DataOffset);
 +    } else if (bs.DataOffset!=avpkt->size) {
 +        /* some data of packet was not consumed. store it to local buffer */
 +        av_fifo_generic_write(q->input_fifo, avpkt->data+bs.DataOffset,
 +                              avpkt->size - bs.DataOffset, NULL);
 +    }
  
 -        out_frame->queued = 1;
 -        av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
 -        av_fifo_generic_write(q->async_fifo, &sync,      sizeof(sync),      NULL);
 +    if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
 +        return ff_qsv_error(ret);
      }
 +    n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
  
 -    if (!av_fifo_space(q->async_fifo) ||
 -        (!avpkt->size && av_fifo_size(q->async_fifo))) {
 +    if (n_out_frames > q->async_depth || (!avpkt->size && n_out_frames) ) {
          AVFrame *src_frame;
  
          av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);