21 #include <mfx/mfxvideo.h> 
   22 #include <mfx/mfxplugin.h> 
   37 #if QSV_VERSION_ATLEAST(1, 12) 
   38 #include "mfx/mfxvp8.h" 
   46 #if QSV_VERSION_ATLEAST(1, 8) 
   48         return MFX_CODEC_HEVC;
 
   52         return MFX_CODEC_MPEG2;
 
   55 #if QSV_VERSION_ATLEAST(1, 12) 
   69         return MFX_PROFILE_UNKNOWN;
 
   75         return 4 * profile + 1;
 
   79     return MFX_PROFILE_UNKNOWN;
 
   87     { MFX_ERR_NONE,                     0,               
"success"                              },
 
   89     { MFX_ERR_NULL_PTR,                 
AVERROR(EINVAL), 
"NULL pointer"                         },
 
   90     { MFX_ERR_UNSUPPORTED,              
AVERROR(ENOSYS), 
"unsupported"                          },
 
   91     { MFX_ERR_MEMORY_ALLOC,             
AVERROR(ENOMEM), 
"failed to allocate memory"            },
 
   92     { MFX_ERR_NOT_ENOUGH_BUFFER,        
AVERROR(ENOMEM), 
"insufficient input/output buffer"     },
 
   93     { MFX_ERR_INVALID_HANDLE,           
AVERROR(EINVAL), 
"invalid handle"                       },
 
   94     { MFX_ERR_LOCK_MEMORY,              
AVERROR(EIO),    
"failed to lock the memory block"      },
 
   95     { MFX_ERR_NOT_INITIALIZED,          
AVERROR_BUG,     
"not initialized"                      },
 
   96     { MFX_ERR_NOT_FOUND,                
AVERROR(ENOSYS), 
"specified object was not found"       },
 
  100     { MFX_ERR_MORE_SURFACE,             
AVERROR_UNKNOWN, 
"expect more surface at output"        },
 
  101     { MFX_ERR_MORE_BITSTREAM,           
AVERROR_UNKNOWN, 
"expect more bitstream at output"      },
 
  103     { MFX_ERR_DEVICE_LOST,              
AVERROR(EIO),    
"device lost"                          },
 
  104     { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, 
AVERROR(EINVAL), 
"incompatible video parameters"        },
 
  105     { MFX_ERR_INVALID_VIDEO_PARAM,      
AVERROR(EINVAL), 
"invalid video parameters"             },
 
  106     { MFX_ERR_UNDEFINED_BEHAVIOR,       
AVERROR_BUG,     
"undefined behavior"                   },
 
  107     { MFX_ERR_DEVICE_FAILED,            
AVERROR(EIO),    
"device failed"                        },
 
  108     { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, 
AVERROR(EINVAL), 
"incompatible audio parameters"        },
 
  109     { MFX_ERR_INVALID_AUDIO_PARAM,      
AVERROR(EINVAL), 
"invalid audio parameters"             },
 
  111     { MFX_WRN_IN_EXECUTION,             0,               
"operation in execution"               },
 
  112     { MFX_WRN_DEVICE_BUSY,              0,               
"device busy"                          },
 
  113     { MFX_WRN_VIDEO_PARAM_CHANGED,      0,               
"video parameters changed"             },
 
  114     { MFX_WRN_PARTIAL_ACCELERATION,     0,               
"partial acceleration"                 },
 
  115     { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0,               
"incompatible video parameters"        },
 
  116     { MFX_WRN_VALUE_NOT_CHANGED,        0,               
"value is saturated"                   },
 
  117     { MFX_WRN_OUT_OF_RANGE,             0,               
"value out of range"                   },
 
  118     { MFX_WRN_FILTER_SKIPPED,           0,               
"filter skipped"                       },
 
  119     { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0,               
"incompatible audio parameters"        },
 
  133         *desc = 
"unknown error";
 
  138                        const char *error_string)
 
  148                          const char *warning_string)
 
  173         *fourcc = MFX_FOURCC_NV12;
 
  177         *fourcc = MFX_FOURCC_P010;
 
  187     for (i = 0; i < ctx->
nb_mids; i++) {
 
  198     if (!load_plugins || !*load_plugins)
 
  201     while (*load_plugins) {
 
  209         if (strlen(plugin) != 2 * 
sizeof(uid.Data)) {
 
  212             goto load_plugin_fail;
 
  215         for (i = 0; i < 
sizeof(uid.Data); i++) {
 
  216             err = sscanf(plugin + 2 * i, 
"%2hhx", uid.Data + i);
 
  220                 goto load_plugin_fail;
 
  225         ret = MFXVideoUSER_Load(session, &uid, 1);
 
  228             snprintf(errorbuf, 
sizeof(errorbuf),
 
  229                      "Could not load the requested plugin '%s'", plugin);
 
  231             goto load_plugin_fail;
 
  247                                  const char *load_plugins)
 
  249     mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
 
  255     ret = MFXInit(impl, &ver, session);
 
  258                                   "Error initializing an internal MFX session");
 
  266     MFXQueryIMPL(*session, &impl);
 
  268     switch (MFX_IMPL_BASETYPE(impl)) {
 
  269     case MFX_IMPL_SOFTWARE:
 
  272     case MFX_IMPL_HARDWARE:
 
  273     case MFX_IMPL_HARDWARE2:
 
  274     case MFX_IMPL_HARDWARE3:
 
  275     case MFX_IMPL_HARDWARE4:
 
  276         desc = 
"hardware accelerated";
 
  283            "Initialized an internal MFX session using %s implementation\n",
 
  300     int                  nb_surfaces = frames_hwctx->nb_surfaces;
 
  324     for (i = 0; i < nb_surfaces; i++) {
 
  326         mid->
handle        = frames_hwctx->surfaces[i].Data.MemId;
 
  339     int                  nb_surfaces = frames_hwctx->nb_surfaces;
 
  349     for (i = 0; i < nb_surfaces; i++)
 
  350         resp->mids[i] = &mids[i];
 
  351     resp->NumFrameActual = nb_surfaces;
 
  353     resp->mids[resp->NumFrameActual] = (mfxMemId)
av_buffer_ref(hw_frames_ref);
 
  354     if (!resp->mids[resp->NumFrameActual]) {
 
  359     resp->mids[resp->NumFrameActual + 1] = 
av_buffer_ref(mids_buf);
 
  360     if (!resp->mids[resp->NumFrameActual + 1]) {
 
  370                                  mfxFrameAllocResponse *resp)
 
  377     if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
 
  378                        MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))         ||
 
  379         !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
 
  380         return MFX_ERR_UNSUPPORTED;
 
  382     if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
 
  386         mfxFrameInfo      *i  = &req->Info;
 
  387         mfxFrameInfo      *i1 = &frames_hwctx->surfaces[0].Info;
 
  389         if (i->Width  != i1->Width  || i->Height != i1->Height ||
 
  390             i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
 
  392                    "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
 
  393                    i->Width,  i->Height,  i->FourCC,  i->ChromaFormat,
 
  394                    i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
 
  395             return MFX_ERR_UNSUPPORTED;
 
  401                    "Error filling an external frame allocation request\n");
 
  402             return MFX_ERR_MEMORY_ALLOC;
 
  404     } 
else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
 
  407         mfxFrameInfo      *i  = &req->Info;
 
  415             return MFX_ERR_MEMORY_ALLOC;
 
  418         frames_hwctx = frames_ctx->hwctx;
 
  422         frames_ctx->width             = i->Width;
 
  423         frames_ctx->height            = i->Height;
 
  424         frames_ctx->initial_pool_size = req->NumFrameSuggested;
 
  426         frames_hwctx->frame_type      = req->Type;
 
  431                    "Error initializing a frames context for an internal frame " 
  432                    "allocation request\n");
 
  434             return MFX_ERR_MEMORY_ALLOC;
 
  440             return MFX_ERR_MEMORY_ALLOC;
 
  448                    "Error filling an internal frame allocation request\n");
 
  449             return MFX_ERR_MEMORY_ALLOC;
 
  452         return MFX_ERR_UNSUPPORTED;
 
  474         return MFX_ERR_UNDEFINED_BEHAVIOR;
 
  479         return MFX_ERR_MEMORY_ALLOC;
 
  502     qsv_mid->
surf.Info = hw_frames_hwctx->surfaces[0].Info;
 
  520     return MFX_ERR_MEMORY_ALLOC;
 
  544         MFX_HANDLE_VA_DISPLAY,
 
  545         MFX_HANDLE_D3D9_DEVICE_MANAGER,
 
  546         MFX_HANDLE_D3D11_DEVICE,
 
  550     mfxSession        parent_session = device_hwctx->session;
 
  555     mfxHDL        handle = 
NULL;
 
  561     err = MFXQueryIMPL(parent_session, &impl);
 
  562     if (err == MFX_ERR_NONE)
 
  563         err = MFXQueryVersion(parent_session, &ver);
 
  564     if (err != MFX_ERR_NONE)
 
  566                                   "Error querying the session attributes");
 
  569         err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle);
 
  570         if (err == MFX_ERR_NONE) {
 
  578                "from the session\n");
 
  581     err = MFXInit(impl, &ver, &session);
 
  582     if (err != MFX_ERR_NONE)
 
  584                                   "Error initializing a child MFX session");
 
  587         err = MFXVideoCORE_SetHandle(session, 
handle_type, handle);
 
  588         if (err != MFX_ERR_NONE)
 
  590                                       "Error setting a HW handle");
 
  605                                const char *load_plugins, 
int opaque)
 
  607     mfxFrameAllocator frame_allocator = {
 
  608         .pthis  = qsv_frames_ctx,
 
  630         qsv_frames_ctx->
logctx = avctx;
 
  638         qsv_frames_ctx->
nb_mids = frames_hwctx->nb_surfaces;
 
  640         err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
 
  641         if (err != MFX_ERR_NONE)
 
  643                                       "Error setting a frame allocator");
 
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e. 
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
ptrdiff_t const GLvoid * data
static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
#define AV_LOG_WARNING
Something somehow does not look correct. 
mfxHandleType handle_type
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame. 
This struct is allocated as AVHWFramesContext.hwctx. 
static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx)
int width
The allocated dimensions of the frames in this pool. 
AVBufferRef * hw_frames_ctx
int ff_qsv_print_error(void *log_ctx, mfxStatus err, const char *error_string)
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values. 
8 bits with AV_PIX_FMT_RGB32 palette 
static void mids_buf_free(void *opaque, uint8_t *data)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context. 
#define AV_LOG_VERBOSE
Detailed information. 
int ff_qsv_map_error(mfxStatus mfx_err, const char **desc)
Convert a libmfx error code into an ffmpeg error code. 
int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, QSVFramesContext *qsv_frames_ctx, const char *load_plugins, int opaque)
This struct is allocated as AVHWDeviceContext.hwctx. 
AVCodecID
Identify the syntax and semantics of the bitstream. 
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered. 
int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame)
The mapping must be direct. 
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g. 
static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array. 
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use. 
static void * av_mallocz_array(size_t nmemb, size_t size)
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
int ff_qsv_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc)
int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile)
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
#define QSV_VERSION_MINOR
#define FF_PROFILE_UNKNOWN
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
preferred ID for MPEG-1/2 video decoding 
#define FF_ARRAY_ELEMS(a)
static const mfxHandleType handle_types[]
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
static const struct @106 qsv_errors[]
Libavcodec external API header. 
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc(). 
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line. 
main external API structure. 
uint8_t * data
The data buffer. 
void * hwctx
The format-specific data, allocated and freed automatically along with this context. 
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2. 
#define AV_PIX_FMT_YUV420P10
static const char * format
AVBufferRef * hw_frames_ref
This struct describes a set or pool of "hardware" frames (i.e. 
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure. 
static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref, AVBufferRef *mids_buf)
static AVBufferRef * qsv_create_mids(AVBufferRef *hw_frames_ref)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes. 
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext. 
A reference to a data buffer. 
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) 
common internal and external API header 
static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
static enum AVPixelFormat qsv_map_fourcc(uint32_t fourcc)
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame. 
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context. 
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer. 
int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, const char *load_plugins)
#define QSV_VERSION_MAJOR
#define AVERROR_UNKNOWN
Unknown error, typically from an external library. 
An API-specific header for AV_HWDEVICE_TYPE_QSV. 
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames. 
AVPixelFormat
Pixel format. 
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins)