硬件编解码(七)【Intel(R)_Media_SDK】官方文档翻译摘要

转载一个大神翻译的Intel Media SDK官方文档

原文地址:http://blog.csdn.net/jammg/article/details/52798434


【前言】


Intel media SDK调用系统底层库完成硬编解码,处理视频,库分用器如下



有很多硬解码库,不同的GPU可以使用不同的库,有些库也有可能为了跨硬件,就会像上图那样有个分层器,根据硬件类型选择不同的库进行硬解码,
相关库有:

DXVA Microsoft DirectX
CUDA 英伟达推出
CUVID 英伟达推出

还有一些开源的库



【文档翻译摘要】


Introduce


1.  Name rule 命名规则

    函数一般是大写MFX开头
    结构体一般是小写mfx开头

    函数命名规则:
    MFX ----- Video --- DECODE_ --- DecodeFrameAsync

    prefix - Domain --- Class ----- Name


2. lib调用规则
    应用通过调用lib分层库调用SDK,它会自动选择最合适该平台最合适的库然后调用;
    如果平台不支持任何硬件加速,那么就会选用默认的软件库,也就是软编码了。

    a.首选硬编码
    b.如果不支持那么使用


3.  Video Decoding

    a.DECODE 只能解码纯码流,也就是说像MP4这种封装了多种流的文件无法解析。

    b.纯码流在第一字节前必须提供一个时间戳。

    c.纯码流前面必须带有码流的信息,不然DECODE不工作;当码流发生帧不连续时,如果没有
      提供新的码流信息,那么DECODE默认使用之前的配置

4.  Video Encoding

    a. 编码通常是一组图像序列(Group of picture sequence[GOP],可以包含IPB帧)进行
    b. GOP可以确定序列的长度和I帧之间的距离
    c. 一个GOP独立编码,不依赖其他GOP,也就是说解码也可以独立进行
    d. 编码输出的码流会带有时间戳

    ENCODE processes input frames in two ways:
    Display order: ENCODE receives input frames in the display order.
                   A few GOP structure parameters specify the GOP sequence 
                   during ENCODE initialization. Scene change results from 
                   the video processing stage of a pipeline can alter the GOP sequence.

    Encoded order: ENCODE receives input frames in their encoding order. 
                   The application must specify the exact input frame type for encoding. 
                   ENCODE references GOP parameters


Programming Guide


1. 文件与库

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Include these files:  
  2. #include “mfxvideo.h” /* The SDK include file */  
  3. #include “mfxvideo++.h” /* Optional for C++ development */  
  4. Link this library:  
  5. libmfx.lib /* The SDK static dispatcher library */  
  6. or  
  7. libmfx.a /* The SDK static dispatcher library */  


    Linux下:
    1. 链接 dispatcher_shared.a
    2. 定义宏 MFX_DISPATCHER_EXPOSED_PREFIX

2. Status Codes 代码描述

    a. SDK都是封装在一个class,包括ENCODE,DECODE and VPP(video processing functions)
       里面都包含有Init(分配内存),Reset(重新初始化内存)和Close这些函数,这些函数在使用库
       之前进行一些初始化
    b. SDK返回码是mfxStatus类型,MFX_ERR_NONE为成功执行,小于MFX_ERR_NONE是ERROR,大于
       MFX_ERR_NONE是WARNING
    c. SDK返回WARNING说明是完全执行了函数,但结果不一定可靠,还需要检查输出的合法性
    d. SDK出错后,必须调用Reset或Close进行清除;Init和Close总是成对出现

3. SDK Session SDK会话

    a. 使用SDK前必需先创建一个SDK会话,SDK会话维护了一个使用DECODE\ENCODE\VPP的上下文
    b. 函数MFXInit开始初始化SDK会话,MFXClose关闭会话,为防止内存泄漏,必需成对出现
    c. MFX_IMPL_SOFTWARE / MFX_IMPL_HARDWARE 分别是使用软硬编码,如果存在多个GPU设备
       ,那么MFX_IMPL_HARDWARE1...MFX_IMPL_HARDWARE4支持进行选择
    d. 可以使用MFX_IMPL_AUTO/MFX_IMPL_AUTO_ANY进行自动初始化,函数MFXQueryIMPL返回
       实际的实现方式

4. Multiple Sessions

    a. 如果应用需要ENCODE / DECODE / VPP多个实例,那么可以进行多重会话的初始化,各个会话
       是独立的;每个SDK会话能够独立工作在软件实施会话 或者 硬件实施会话
    b. 应用可以创建 多重会话 或者 一个"joined"会话,前者数据的不能分享的,除非做了明显的同步
       工作去保证数据是合法并且完整的
    c. MFXJoinSession创建一个“joined”会话,MFXCloneSession复制一个存在的会话
    d. Joined SDK sessions如同一个SDK session,它们共享资源、优化操作等,When joined, one 
       of the sessions (the first join) serves as a parent session, scheduling execution 
       resources, with all others child sessions relying on the parent session for resource 
       management.
    e. MFXSetPriority设置session优先级(针对CPU),对硬件加速无影响
    f. MFXDisjoinSession分离一个child session,parent session只有在所有child session
       disjoined/closed 才能close.

5. Frame and field
    In SDK terminology, a frame (or frame surface, interchangeably) contains either a 
    progressive frame or a complementary field pair. If the frame is a complementary 
    field pair, the odd lines(奇数行) of the surface buffer store the top fields and the even 
    lines(偶数行) of the surface buffer store the bottom fields.

6. Frame Surface Locking(编码一个GOP sequence时)

    a. 编码出一帧时,还需要保存着为下一帧做为编解码的依赖,通常需要复制操作,直到一个GOP sequence编码完成;
       而Frame-Locking机制避免了复制

       1. 应用分配一个帧池(pool of frame)以足够放下SDK函数一个i/o frame,每一个frame surface包含一个
          Locker 计数(mfxFrameData的一个成员),初始化时Locker值为0
       2. 应用使用frame surface去呼叫SDK函数从pool of frame,如果函数需要存储frame surface,那么函数
          增加Locker计数,Locker为非0时,代表“In use”,就只能read,不能alter,move,delete,free frame surface
       3. 当Locker为0时,应用可以任意操作frame surface

    b. 应用不应该操作Locker 计数,SDK已经内部实现
    c. 如果真需要操作Locker计数,那么应该使用atomic操作避免条件竞争(不被推荐)


7. Decoding Procedures(解码步骤)


    以下是主要点的说明:
    a. MFXVideoDECODE_DecodeHeader -> 在bitstream进行解码参数的初始化
    b. MFXVideoDECODE_QueryIOSurf  -> The application uses the MFXVideoDECODE_QueryIOSurf function to 
       obtain the number of working frame surfaces required to reorder output frames.
    c. MFXVideoDECODE_DecodeFrameAsync -> 解码bitstream(bits) 和 一个unlocked frame surface(work)作为输入
       参数,如果输出不可用,那么函数返回码:请求额外bitstream 或者 working frame surface ,如下:

       MFX_ERR_MORE_DATA: The function needs additional bitstream input. The existing buffer contains less than a frame worth of bitstream data.
       MFX_ERR_MORE_SURFACE: The function needs one more frame surface to produce any output.
       MFX_ERR_REALLOC_SURFACE: Dynamic resolution change case - the function needs bigger working frame surface (work).

    d. MFXVideoDECODE_DecodeFrameAsync返回MFX_ERR_NONE,解码帧仍未可用,因为此函数是异步的,
       MFXVideoCORE_SyncOperation -> 应用必须在获取帧数据前进行同步解码操作

    e. MFXVideoDECODE_DecodeFrameAsync -> 传入NULL bitstream指针头获取SDK解码器的frame cached(也就是一些剩余的数据)


8.  Bitstream Repositioning(比特流重定位)

    a. MFXVideoDECODE_Reset -> 进行重定位,此时SDK 解码器直到接收到sequence header前都不进行解码操作

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. MFXVideoDECODE_DecodeHeader(session, bitstream, &init_param);  
  2. MFXVideoDECODE_QueryIOSurf(session, &init_param, &request);  
  3. allocate_pool_of_frame_surfaces(request.NumFrameSuggested);  
  4. MFXVideoDECODE_Init(session, &init_param);  
  5. sts=MFX_ERR_MORE_DATA;  
  6. for (;;) {  
  7.     if (sts==MFX_ERR_MORE_DATA && !end_of_stream())  
  8.         append_more_bitstream(bitstream);  
  9.     find_unlocked_surface_from_the_pool(&work);  
  10.     bits=(end_of_stream())?NULL:bitstream;  
  11.     sts=MFXVideoDECODE_DecodeFrameAsync(session,bits,work,&disp,&syncp);  
  12.     if (sts==MFX_ERR_MORE_SURFACE) continue;  
  13.     if (end_of_bitstream() && sts==MFX_ERR_MORE_DATA) break;  
  14.     if (sts==MFX_ERR_REALLOC_SURFACE) {  
  15.         MFXVideoDECODE_GetVideoParam(session, ¶m);  
  16.         realloc_surface(work, param.mfx.FrameInfo);  
  17.         continue;  
  18.     }  
  19.     … // other error handling  
  20.     if (sts==MFX_ERR_NONE) {  
  21.         MFXVideoCORE_SyncOperation(session, syncp, INFINITE);  
  22.         do_something_with_decoded_frame(disp);  
  23.     }  
  24. }  
  25. MFXVideoDECODE_Close();  
  26. free_pool_of_frame_surfaces();  




9.  Multiple Sequence Headers

    a. bitstream 可以包含多个sequence headers,SDK会返回一个状态码如果新的header被解析

    b. 如果新的header能够解码已有的码流,那么MFXVideoDECODE_DeocdeFrameAsync返回
       MFX_WRN_VIDEO_PARAM_CHANGED

    c. MFXVideoDECODE_GetVideoParam 可以获取新的视频参数

    d. 如果新的header不能再不reallocte frame buffer的前提下解析已有的bitstream,那么
       MFXVideoDECODE_DecodeFrameAsync 返回 MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,此时,需要以下步骤:
       1. 使用NULL bitstream指针调用MFXVideoDECODE_DecodeFrameAsync获取剩余数据,直到函数返回
          MFX_ERR_MORE_DATA

       2. 然后调用MFXVideoDECODE_Close,最后在新的bitstream position重启解码程序

10. Encoding Procedures

     The application uses the MFXVideoENCODE_QueryIOSurf function to obtain the number of 
       working frame surfaces required for reordering input frames.
     The application calls the MFXVideoENCODE_EncodedFrameAsync function for the encoding 
       operation. The input frame must be in an unlocked frame surface from the frame surface pool. 
       If the encoding output is not available, the function returns the status code MFX_ERR_MORE_DATA 
       to request additional input frames.
     Upon successful encoding, the MFXVideoENCODE_EncodeFrameAsync function returns MFX_ERR_NONE. However,
      the encoded bitstream is not yet available because the MFXVideoENCODE_EncodeFrameAsync function is 
      asynchronous. The application must use the MFXVideoCORE_SyncOperation function to synchronize the 
      encoding operation before retrieving the encoded bitstream.
     At the end of the stream, the application continuously calls the MFXVideoENCODE_EncodeFrameAsync 
      function with NULL surface pointer to drain any remaining bitstreams cached within the SDK encoder, 
      until the function returns MFX_ERR_MORE_DATA.
    
    a.  MFXVideoENCODE_QueryIOSurf -> 获取working frame的数量(被reorder input frame需要)
    b.  MFXVideoENCODE_EncodeFrameAsync -> input frame 必须是从pool frame 中提取的unlocked frame surface, 
        MFX_ERR_MORE_DATA代表需要额外的frame

    c.  b.步骤返回MFX_ERR_NONE后,需要调用MFXVideoCORE_SyncOperation 去同步编码操作和获取可用的已编码的bitstream
    d.  MFXVideoENCODE_EncodeFrameAsync -> 传递NULL surface pointer去获取剩余数据,直到返回MFX_ERR_MORE_DATA


11. Configuration change

    a. MFXVideoENCODE_Reset 进行重置,可以使用现有参数继续编码 或者 在新的bitstream工作,需要从一个IDR帧开始解码
    
    b. 在调用MFXVideoENCODE_Reset前,最好先调用 MFXVideoENCODE_Query返回与mfxVideoParm相关联的mfxExtEncoderResetOption
       通过这个结构体,应用可以判断当前是否合适重置操作

    c. 重置操作过程:

        1. MFXVideoENCODE_EncodeFrameAsync -> 使用NULL input frame调用直到返回MFX_ERR_MORE_DATA
           注意:mfxExtCodingOption必须初始化为OFF
        2. MFXVideoENCODE_Reset -> 成功则可继续解码现有的流,如果返回MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,
           那么需要关闭SDK encoder 和 对新的配置重新进行编码步骤的初始化

 
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. MFXVideoENCODE_QueryIOSurf(session, &init_param, &request);  
  2.  allocate_pool_of_frame_surfaces(request.NumFrameSuggested);  
  3.  MFXVideoENCODE_Init(session, &init_param);  
  4.  sts=MFX_ERR_MORE_DATA;  
  5.  for (;;) {  
  6.      if (sts==MFX_ERR_MORE_DATA && !end_of_stream()) {  
  7.          find_unlocked_surface_from_the_pool(&surface);  
  8.          fill_content_for_encoding(surface);  
  9.      }  
  10.      surface2=end_of_stream()?NULL:surface;  
  11.      sts=MFXVideoENCODE_EncodeFrameAsync(session,NULL,surface2,bits,&syncp);  
  12.      if (end_of_stream() && sts==MFX_ERR_MORE_DATA) break;  
  13.      … // other error handling  
  14.      if (sts==MFX_ERR_NONE) {  
  15.          MFXVideoCORE_SyncOperation(session, syncp, INFINITE);  
  16.          do_something_with_encoded_bits(bits);  
  17.      }  
  18.  }  
  19.  MFXVideoENCODE_Close();  
  20.  free_pool_of_frame_surfaces();  

12. Video Processing Procedures

    一下记录主要的步骤:

    a. MFXVideoVPP_QueryIOSurf 返回frame surfaces数量,必须包含两个frame surface pool,一个是input
       一个是output

    b. MFXVideoVPP_RunFrameVPPAsync -> 异步处理 
       MFXVideoCORE_SyncOperation -> 同步处理,获取结果

    A. 主要的处理过程:

        1. 如果处理的input frames填满output generated
           VPP返回MFX_ERR_NONE应用必须在同步之后才能处理数据,因为MFXVideoVPP_RunFrameVPPAsync是异步的,
           最后使用null input获取剩余数据
        2. 如果处理的input frames不够填满 output generated
           vpp返回MFX_ERR_MORE_DATA,直到output ready ,此时VPP返回MFX_ERR_NONE,最后使用null input获取剩余数据
        3. 如果处理的input frames能够填满output generated
           MFX_ERR_MORE_SURFACE -> 当不是output generated 整数倍
           MFX_ERR_NONE -> 刚好是output generated 整数倍
           最后使用null input获取剩余数据

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. MFXVideoVPP_QueryIOSurf(session, &init_param, response);  
  2. allocate_pool_of_surfaces(in_pool, response[0].NumFrameSuggested);  
  3. allocate_pool_of_surfaces(out_pool, response[1].NumFrameSuggested);  
  4. MFXVideoVPP_Init(session, &init_param);  
  5. in=find_unlocked_surface_and_fill_content(in_pool);  
  6. out=find_unlocked_surface_from_the_pool(out_pool);  
  7. for (;;) {  
  8.     sts=MFXVideoVPP_RunFrameVPPAsync(session,in,out,aux,&syncp);  
  9.     if (sts==MFX_ERR_MORE_SURFACE || sts==MFX_ERR_NONE) {  
  10.         MFXVideoCore_SyncOperation(session,syncp,INFINITE);  
  11.         process_output_frame(out);  
  12.         out=find_unlocked_surface_from_the_pool(out_pool);  
  13.     }  
  14.     if (sts==MFX_ERR_MORE_DATA && in==NULL) break;  
  15.     if (sts==MFX_ERR_NONE || sts==MFX_ERR_MORE_DATA) {  
  16.     in=find_unlocked_surface(in_pool);  
  17.     fill_content_for_video_processing(in);  
  18.         if (end_of_input_sequence()) in=NULL;  
  19.     }  
  20. }  
  21. MFXVideoVPP_Close(session);  
  22. free_pool_of_surfaces(in_pool);  
  23. free_pool_of_surfaces(out_pool);  




13. Configuration(管道操作配置,即是处理input format 转到 output format(another format))

    a. 转换的格式参数在 mfxVideoParam 结构体指定
        例如:
        1. 能够进行color format 的转换
        2. 能够 interleave -> progressive,SDK可以进行 de-interlacing

    b. 除了mfxVideoParam结构体设置之外,还有mfxExtVPPDoNotUse等结构体进行format微调
    c. mfxExtVPPDoUse能够通过关联mfxVideoParam,调用MFXVideoVPP_GetVideoParam获取相关参数

        
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* enable image stabilization filter with default settings */  
  2. mfxExtVPPDoUse du;  
  3. mfxU32 al=MFX_EXTBUFF_VPP_IMAGE_STABILIZATION;  
  4. du.Header.BufferId=MFX_EXTBUFF_VPP_DOUSE;  
  5. du.Header.BufferSz=sizeof(mfxExtVPPDoUse);  
  6. du.NumAlg=1;  
  7. du.AlgList=&al;  
  8. /* configure the mfxVideoParam structure */  
  9. mfxVideoParam conf;  
  10. mfxExtBuffer *eb=&du;  
  11. memset(&conf,0,sizeof(conf));  
  12. conf.IOPattern=MFX_IOPATTERN_IN_SYSTEM_MEMORY|  
  13. MFX_IOPATTERN_OUT_SYSTEM_MEMORY;  
  14. conf.NumExtParam=1;  
  15. conf.ExtParam=&eb;  
  16. conf.vpp.In.FourCC=MFX_FOURCC_YV12;  
  17. conf.vpp.Out.FourCC=MFX_FOURCC_NV12;  
  18. conf.vpp.In.Width=conf.vpp.Out.Width=1920;  
  19. conf.vpp.In.Height=conf.vpp.Out.Height=1088;  
  20. /* video processing initialization */  
  21. MFXVideoVPP_Init(session, &conf);  



14. Region of Interest

    a. mfxVideoParam 结构体设置感兴趣的区域,然后进行管道处理


15. Transcoding Procedures(转码步骤)

    应用可以使用encode decode video SDK 进行一系列的转换,两个或以上SDK 函数合作

16. Asyncchronous Pipeline(异步管道)

    a. 应用通过上游函数的返回值调用下游函数从而创建出来的管道,它们是以动态运行时实现的

        例如:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. mfxSyncPoint sp;  
  2. MFXVideoDECODE_DecodeFrameAsync(session,bs,work,vin, &sp_d);  
  3. if (going_through_vpp) {  
  4.     MFXVideoVPP_RunFrameVPPAsync(session,vin,vout, &sp_d);  
  5.     MFXVideoENCODE_EncodeFrameAsync(session,NULL,vout,bits2,&sp_e);  
  6. else {  
  7.     MFXVideoENCODE_EncodeFrameAsync(session,NULL,vin,bits2,&sp_e);  
  8. }  
  9. MFXVideoCORE_SyncOperation(session,sp_e,INFINITE);  



    b. SDK简化了异步管道进行同步的要求,仅需要在最后一步进行同步,在中间进行同步会减慢处理速度
    c. SDK跟踪动态管道的创建,确定input到output之间的依赖性,从而确定管道函数执行的顺序
       如:在上面的例子, MFXVideoENCODE_EncodedFrameAsync 不会开始执行直到
       MFXVideoDECODE_DecodeFrameAsync 和 MFXVideoVPP_RunFrameVPPAsync执行完成
    e. 在管道执行过程,直到完成前不能对处理的数据进行更改;同时,也应该考虑到异步操作完成并
       不代表数据已是可用
    f. 不要更改input / output parameters 直到previous asynchronous完成前
    g. An exception occurs when the input and output parameters are structures, 
       in which case overwriting fields in the structures is allowed. (Note that the dependency 
       check works on the pointers to the structures only.)

    h. 以下有两个值得注意的例外:
        1.  在调用MFXVideoDecode_DecoderFrameAsync 前,必须进行同步操作
        2. 从异步获取的数据当不用于SDK-Compenent时,必须显示的对surface 进行同步操作


17. Surface Pool Allocate

    a. 当链接SDK function A和B时,必须考虑到the number of frame surfaces in the surface pool,
       最简单地,就是Na + Nb(Na/Nb分别是SDK fucntion A和B需要的数量)
    b. 重复性调用
       For performance considerations, the application must submit multiple operations and delays
       synchronization as much as possible, which gives the SDK flexibility to organize internal 
       pipelining. For example, the operation sequence, ENCODE(f1)  ENCODE(f2)  SYNC(f1)  SYNC(f2) 
       is recommended, compared with ENCODE(f1)  SYNC(f1)  ENCODE(f2)  SYNC(f2).

    c. 针对b的情况,surface pool需要考虑由于multiple asynchronous operations所导致需要的number of surface pool
       AsyncDepth parameter of mfxVideoParam 告知SDK多少异步操作函数被调用,相应的QueryIOSurf获取NumFrameSuggested
       例如一下 calculate Surface Pool size:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. async_depth=4;  
  2. init_param_v.AsyncDepth=async_depth;  
  3. MFXVideoVPP_QueryIOSurf(session, &init_param_v, response_v);  
  4. init_param_e.AsyncDepth=async_depth;  
  5. MFXVideoENCODE_QueryIOSurf(session, &init_param_e, &response_e);  
  6. num_surfaces = response_v[1].NumFrameSuggested  
  7.                 +response_e.NumFrameSuggested  
  8.                 -async_depth; /* double counted in ENCODE & VPP */  

18. Pipeline Error Reporting (管道错误报告)

    a. 如果有SDK调用序列如:A->B->C
       如果C函数出错,且返回MFX_ERR_ABORTED,那么说明错误出现在上游函数,继续调用B以此类推
       直到得到返回error code

19. Working with hardware acceleration

    a. 为了充分利用硬件加速,系统应该包含基础设施,如window包含DX ,Linux包含VA API
    b. 硬件加速由video memory(图像存储器) 和 acceleration device(加速设备)支持
    c. Video memory(图片)
    
    d. 应用根据mfxVideoParam的成员IOPattern初始化I/O access pattern(io访问模式),后面调用的函数
       跟随上游的设置
       例如:
       如果SDK function使用video memory surfaces 处理输入和输出,那么应用必须将IOPattern初始化为
       MFX_IOPATTERN_IN_VIDEO_MEMORY/MFX_IOPATTERN_OUT_VIDEO_MEMORY,在Init...Close sequence之间不能改变
    
    e. 初始化hardware accelerated SDK 组件需要加速硬件的句柄,SDK component可以使用它去查询HW capability,
       应用可以通过MFXVideoCORE_SetHandle去分享一个句柄

20. Working with Microsoft *DirectX* application

    a. SDK function在windows会使用 "Direct3D 9 DXVA2" and "Direct3D 11 Video API"进行硬件加速
       以上两个是微软实现的硬件加速接口(我们是可以直接调用这些接口进行硬解的!)
       在Linux会使用 "VA API"

    b. 应用应该先使用 IDirect3DDeviceManager9创建硬件加速句柄,然后调用MFXVideoCORE_SetHandle进行share
       如果不提供句柄,那么应用就不能访问内部的设备

       例子:Setting multithreading mode
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. ID3D11Device *pD11Device;  
  2. ID3D11DeviceContext *pD11Context;  
  3. ID3D10Multithread *pD10Multithread;  
  4. pD11Device->GetImmediateContext(&pD11Context);  
  5. pD11Context->QueryInterface(IID_ID3D10Multithread, &pD10Multithread);  
  6. pD10Multithread->SetMultithreadProtected(true);  
    
    c. Direct3D 9/11 支持的转换



21. Memory Allocation and external Allocater

    a. 所有SDK 都委托应用管理内存,所以分配回收都由应用进行,SDK通过回调函数(指向外部内存分配接口mfxFrameAllocator)
       管理内存
       mfxBufferAllocator不再使用

    b. 如果应用要管理内存就应设置mfxFrameAllocator callback,否则SDK内部(internal)默认allocator被使用
    c. 如果应用使用了video memory surface(图像存储器面),那么必须确定hardware acceleration device 和 
       external frame Allocator(mfxFrameAllocator)

    d. external frame allocator能够分配两种帧类型:
        1. system memory
        2. video memory,作为 "decoder render targets" or "processor render targets"

    e. external frame allocator仅仅相应frame alloction请求(system / video memory),对于其他请求
       external frame allocator 返回MFX_ERR_UNSUPPORTED,另外,efa通过flags,part 和 memory type域来
       判断哪个SDK发起的请求而做出相应响应
       
    f. allocator 示例
    

22. Surface Type Neutral Transcoding

    a. SDK执行需要在CPU和GPU之间进行,也就是说就算是硬件加速也是需要使用CPU的
    b. 为了更好表现,SDK提供了一个"opaque surface",它在system memory 和 video memory之间进行映射,
       而应用主需要管理好一个surface type.(目前提到了三种surface type)
       trascoding pipeline:
       DECODE->opaque surface->VPP->Opaque surface->ENCODE

    c. 使用opaque surface 步骤,假设一个转码管道 SDK A -> SDK B
        1. 使用MFX_IOPATTERN_IN_OPAQUE_MEMORY/MFX_IOPATTERN_OUT_OPAQUE_MEMORY确定surface pool size,
           如果返回的memory type和size不一样,那么使用其中一个
        2. 分配的surface pool 是一个mfxFrameSurface1数组,初始化Y,U,V,A,MemID 为0
        3. 在初始化阶段,应用通过mfxExtOpaqueSurfaceAlloc传递给SDK component.
        4. 在编解码,视频处理阶段,应用就可以管理surface pool 和 传递frame surface 到SDK A和B,使用
           方法和Decoding Procedures, Encoding Procedures,  Video Processing Procedures一样
    
    d. 如果应用要将opaque surface应用于不同的session,那么在SDK组件初始化前必须join

    示例:pseudo-code of opaque surface Procedures

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. mfxExtOpqueSurfaceAlloc osa, *posa=&osa;  
  2. memset(&osa,0,sizeof(osa));  
  3. // query frame surface allocation needs  
  4. MFXVideoDECODE_QueryIOSurf(session, &decode_param, &request_decode);  
  5. MFXVideoENCODE_QueryIOSurf(session, &encode_param, &request_encode);  
  6. // calculate the surface pool surface type and numbers  
  7. if (MFX_MEMTYPE_BASE(request_decode.Type) ==  
  8.     MFX_MEMTYPE_BASE(request_encode.Type)) {  
  9.     osa.Out.NumSurface = request_decode.NumFrameSuggested +  
  10.     request_encode.NumFrameSuggested - decode_param.AsyncDepth;  
  11.     osa.Out.Type=request_decode.Type;  
  12. else {  
  13.     // it is also ok to use decode's NumFrameSuggested and Type.  
  14.     osa.Out.NumSurface=request_encode.NumFrameSuggested;  
  15.     osa.Out.Type=request_encode.Type;  
  16. }  
  17. // allocate surface pool and zero MemId/Y/U/V/A pointers  
  18. osa.Out.Surfaces=alloc_mfxFrameSurface1(osa.Out.NumSurface);  
  19. // attach the surface pool during decode & encode initialization  
  20. osa.Header.BufferId=MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;  
  21. osa.Header.BufferSz=sizeof(osa);  
  22. decode_param.NumExtParam=1;  
  23. decode_param.ExtParam=&posa;  
  24. MFXVideoDECODE_Init(session, &decode_param);  
  25. memcpy(&osa.In, &osa.Out, sizeof(osa.Out));  
  26. encode_param.NumExtParam=1;  
  27. encode_param.ExtParam=&posa;  
  28. MFXVideoENCODE_Init(session, &encode_param);  




23. Hardware Device Error handling

    a. SDK编解码,视频处理可能返回以下错误:

        MFX_ERR_DEVICE_FAILED
            Hardware device returned unexpected errors. SDK was unable to restore operation.
        MFX_ERR_DEVICE_LOST
            Hardware device was lost due to system lock or shutdown.
        MFX_WRN_PARTIAL_ACCELERATION
            The hardware does not fully support the specified configuration. The encoding, decoding, or video processing operation may be partially accelerated.
        MFX_WRN_DEVICE_BUSY
            Hardware device is currently busy.

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值