]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/qsv.c
vc1: skip motion compensation when data for last picture is invalid
[ffmpeg] / libavcodec / qsv.c
index 45e9b7aa48de15953a984b8c3e091dd3f533cc22..e78633d62abe675b44b3783259f5d98516e2907b 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <mfx/mfxvideo.h>
 #include <mfx/mfxplugin.h>
+#include <mfx/mfxjpeg.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -56,6 +57,8 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
     case AV_CODEC_ID_VP8:
         return MFX_CODEC_VP8;
 #endif
+    case AV_CODEC_ID_MJPEG:
+        return MFX_CODEC_JPEG;
     default:
         break;
     }
@@ -94,15 +97,17 @@ static const struct {
     { MFX_ERR_LOCK_MEMORY,              AVERROR(EIO),    "failed to lock the memory block"      },
     { MFX_ERR_NOT_INITIALIZED,          AVERROR_BUG,     "not initialized"                      },
     { MFX_ERR_NOT_FOUND,                AVERROR(ENOSYS), "specified object was not found"       },
-    { MFX_ERR_MORE_DATA,                AVERROR(EAGAIN), "expect more data at input"            },
-    { MFX_ERR_MORE_SURFACE,             AVERROR(EAGAIN), "expect more surface at output"        },
+    /* the following 3 errors should always be handled explicitly, so those "mappings"
+     * are for completeness only */
+    { MFX_ERR_MORE_DATA,                AVERROR_UNKNOWN, "expect more data at input"            },
+    { MFX_ERR_MORE_SURFACE,             AVERROR_UNKNOWN, "expect more surface at output"        },
+    { MFX_ERR_MORE_BITSTREAM,           AVERROR_UNKNOWN, "expect more bitstream at output"      },
     { MFX_ERR_ABORTED,                  AVERROR_UNKNOWN, "operation aborted"                    },
     { MFX_ERR_DEVICE_LOST,              AVERROR(EIO),    "device lost"                          },
     { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters"        },
     { MFX_ERR_INVALID_VIDEO_PARAM,      AVERROR(EINVAL), "invalid video parameters"             },
     { MFX_ERR_UNDEFINED_BEHAVIOR,       AVERROR_BUG,     "undefined behavior"                   },
     { MFX_ERR_DEVICE_FAILED,            AVERROR(EIO),    "device failed"                        },
-    { MFX_ERR_MORE_BITSTREAM,           AVERROR(EAGAIN), "expect more bitstream at output"      },
     { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters"        },
     { MFX_ERR_INVALID_AUDIO_PARAM,      AVERROR(EINVAL), "invalid audio parameters"             },
 
@@ -384,7 +389,7 @@ static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
         mfxFrameInfo      *i  = &req->Info;
         mfxFrameInfo      *i1 = &frames_hwctx->surfaces[0].Info;
 
-        if (i->Width  != i1->Width  || i->Height != i1->Height ||
+        if (i->Width  > i1->Width  || i->Height > i1->Height ||
             i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
             av_log(ctx->logctx, AV_LOG_ERROR, "Mismatching surface properties in an "
                    "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
@@ -466,9 +471,7 @@ static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
     QSVMid *qsv_mid = mid;
     AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)qsv_mid->hw_frames_ref->data;
     AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx;
-    int size;
     int ret;
-    mfxStatus err;
 
     if (qsv_mid->locked_frame)
         return MFX_ERR_UNDEFINED_BEHAVIOR;
@@ -523,7 +526,6 @@ fail:
 static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
 {
     QSVMid *qsv_mid = mid;
-    int ret;
 
     av_frame_free(&qsv_mid->locked_frame);
     av_frame_free(&qsv_mid->hw_frame);
@@ -538,27 +540,16 @@ static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
     return MFX_ERR_NONE;
 }
 
-int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession,
-                                  QSVFramesContext *qsv_frames_ctx,
-                                  const char *load_plugins, int opaque)
+int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
+                               AVBufferRef *device_ref, const char *load_plugins)
 {
     static const mfxHandleType handle_types[] = {
         MFX_HANDLE_VA_DISPLAY,
         MFX_HANDLE_D3D9_DEVICE_MANAGER,
         MFX_HANDLE_D3D11_DEVICE,
     };
-    mfxFrameAllocator frame_allocator = {
-        .pthis  = qsv_frames_ctx,
-        .Alloc  = qsv_frame_alloc,
-        .Lock   = qsv_frame_lock,
-        .Unlock = qsv_frame_unlock,
-        .GetHDL = qsv_frame_get_hdl,
-        .Free   = qsv_frame_free,
-    };
-
-    AVHWFramesContext    *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data;
-    AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
-    AVQSVDeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
+    AVHWDeviceContext    *device_ctx = (AVHWDeviceContext*)device_ref->data;
+    AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
     mfxSession        parent_session = device_hwctx->session;
 
     mfxSession    session;
@@ -602,12 +593,47 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession,
                                       "Error setting a HW handle");
     }
 
+    err = MFXJoinSession(parent_session, session);
+    if (err != MFX_ERR_NONE)
+        return ff_qsv_print_error(avctx, err,
+                                  "Error joining session");
+
     ret = qsv_load_plugins(session, load_plugins, avctx);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
         return ret;
     }
 
+    *psession = session;
+    return 0;
+}
+
+int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession,
+                               QSVFramesContext *qsv_frames_ctx,
+                               const char *load_plugins, int opaque)
+{
+    mfxFrameAllocator frame_allocator = {
+        .pthis  = qsv_frames_ctx,
+        .Alloc  = qsv_frame_alloc,
+        .Lock   = qsv_frame_lock,
+        .Unlock = qsv_frame_unlock,
+        .GetHDL = qsv_frame_get_hdl,
+        .Free   = qsv_frame_free,
+    };
+
+    AVHWFramesContext    *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data;
+    AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
+
+    mfxSession    session;
+    mfxStatus err;
+
+    int ret;
+
+    ret = ff_qsv_init_session_device(avctx, &session,
+                                     frames_ctx->device_ref, load_plugins);
+    if (ret < 0)
+        return ret;
+
     if (!opaque) {
         qsv_frames_ctx->logctx = avctx;