IntelMediaSDK SampleDecode learning-1

ps:sdk v1.19
简单概念,
1. fourcc,代表四字符代码 (four character code), 它是一个32位的标示符,其实就是typedef unsigned int FOURCC;是一种独立标示视频数据流格式的四字符代码。通过四个字符经过一定的运算得到对应的码来选择对应的解码器。
执行流程,
1. Init过程,因为Sample是命令行输参,大部分初始化参数是未指定的,构造的时候初始化为0了。介绍一下初始化中比较重要的结构体,

typedef struct {
    mfxIMPL     Implementation; // sdk的实现方式
    mfxVersion  Version;        // 库版本
    mfxU16      ExternalThreads;// 线程模式,0表示内部线程,1-外部线程
    union {
        struct {
            mfxExtBuffer **ExtParam;
            mfxU16 NumExtParam; // 额外的配置数量
        };
        mfxU16  reserved2[5];
    };
    mfxU16      GPUCopy;        // 使能GPU拷贝
    mfxU16      reserved[21];
}  mfxInitParam;
typedef struct {
    mfxExtBuffer Header;

    mfxU16       NumThread; // 线程的数量
    mfxI32       SchedulingType; // 线程调度策略
    mfxI32       Priority; //所有线程的优先级
    mfxU16       reserved[55];
} mfxExtThreadsParam;
typedef struct {
    mfxU32  BufferId; // buffer内容的ID, ExtendedBufferID列举了完整的列表
    mfxU32  BufferSz; // buffer的size
} mfxExtBuffer;
typedef union {
    struct {
        mfxU16 Minor; // 次版本
        mfxU16 Major; // 主版本
    };
    mfxU32  Version;
} mfxVersion;

解码session的初始化,m_mfxSession.InitEx(initPar);
ps:使用sdk之前,必须初始化session,sdk维护了一个编解码器或者vpp的执行。
根据已填充的mfxInitParam。
Sample中session.init前已填充的有意义的值有,

typedef struct {
    mfxIMPL     Implementation = soft/hard/auto;
    mfxVersion  Version;        // 库版本
    mfxU16      ExternalThreads;// 线程模式,0表示内部线程,1-外部线程
    <del>union {
        struct {
            mfxExtBuffer **ExtParam;
            mfxU16 NumExtParam; // 额外的配置数量
        };
        mfxU16  reserved2[5];
    };</del>
    mfxU16      GPUCopy = 0; // 使用了0默认
    mfxU16      reserved[21];
}  mfxInitParam;

几乎没填什么初始值。
session init成功后,可以m_mfxSession.QueryVersion(&version);
m_mfxSession.QueryIMPL(&m_impl);获得加载库的版本和库的实现。接着,会将cmd参数的一些选项与获取的版本做对比,判断是否支持。
m_pmfxDEC = new MFXVideoDECODE(m_mfxSession)紧接着,根据创建的session获取了解码器(MFXVideoDECODE)的对象。并对待解码的视频表现参数赋值,m_mfxVideoParams.mfx.CodecId = pParams->videoType。若待解码的码流非MFX_CODEC_CAPTURE,初始化一个mfxBitStream。该结构如下,

typedef struct {
    union {
        struct {
            mfxEncryptedData *EncryptedData; // 保留,为0
            mfxExtBuffer **ExtParam; // 额外配置,不管
            mfxU16  NumExtParam; // 额外结构的数量,不管
        };
        mfxU32  reserved[6]; // 保留
    };
    mfxI64  DecodeTimeStamp; // 另辟blog学习
    mfxU64  TimeStamp;
    mfxU8  *Data; // 码流数据
    mfxU32  DataOffset; // 码流数据中的偏移
    mfxU32  DataLength; // 真实码流的字节数
    mfxU32  MaxLength;  // 分配码流buffer的字节数

    mfxU16  PicStruct; // 输出图像的类型
    mfxU16  FrameType; // 输出帧的类型
    mfxU16  DataFlag;  // buffer的额外标识,见BitstreamDataFlag
    mfxU16  reserved2;
}  mfxBitstream;
enum {
    MFX_BITSTREAM_COMPLETE_FRAME    = 0X0001, // buffer包含了完整的帧或场,意味着解码器可以不等待下一帧开始就进行该buffer的解码,有效的减少了延时
    MFX_BITSTREAM_EOS               = 0X0002  // buffer包含了流的结尾,意味着app不需要发送额外的数据给解码器
};

该结构就是一个存储压缩后的码流数据用的buffer。Sample中的初始化很简单,
delete []data;
pBitstream->Data = new mfxU8[nSize];
pBitstream->MaxLength = nSize;
接着是插件相关,因为初始时全清0,所以是MSDK_PLUGINGUID_NULL,然后根据对应的实现和初始化的参数(impl,MSDK_VDECODE,videotype),通过msdkGetPluginUID获取pluginGuid。
接着,是对解码器参数的设置InitMfxParams(pParams)。如果说之前的操作是申请资源,那这里就是开始初始化赋值了。
拿h264来说,该函数执行直接进入,m_pmfxDEC->DecodeHeader(&m_mfxBS, &m_mfxVideoParams),追踪到下一层发现底层有三个形参m_session以及上面的两个。执行成功后,m_bVppIsUsed = IsVppRequired(pParams);根据pParams的相关值看是否使用Vpp。该函数内的判断涉及了一个比较重要的结构体。

typedef struct {
    mfxU32 AllocId;
    mfxU32 reserved[2];
    mfxU16 reserved3;
    mfxI16 AsyncDepth; // 指定异步操作的数量在出执行结果之前(我的理解,流水线步骤的多少,一个需要均衡的值)
    union {
        mfxInfoMFX mfx; // dec,enc,transcode相关配置参数
        mfxInfoVPP vpp; // video processing相关配置参数
    };
    mfxU16  Protected; // 指定保护机制,该成员为保留参数,为0
    mfxU16  IOPattern; // 指定了SDK的内存访问形式,详细见IOPattern枚举 ps:enc必须指定input,dec必须指定output,vpp i/o都需要指定
    mfxExtBuffer** ExtParam;
    mfxU16  NumExtParam; // 额外配置的结构数量
    mfxU16  reserved2;
} mfxVideoParam;

该结构体包含了编解码转码视频处理参数的配置,总之就是针对整个codec的配置。
Vpp较少涉及,主要介绍mfxInfoMFX,

typedef struct {
    mfxU32  reserved[7];

    mfxU16  LowPower;
    mfxU16  BRCaramMultiplier;

    mfxFrameInfo    FrameInfo;
    mfxU32  CodecId;
    mfxU16  CodecProfile;
    mfxU16  CodecLevel;
    mfxU16  NumThread;

    union {
        ...
    };

}  mfxInfoMFX;

该结构指定了dec, enc, transcoding的配置,这些参数中任意的0值,都表示该参数配置没有被显示指定。IsVppRequired中涉及到该结构中的mfxFrameInfo结构,

typedef struct {
    mfxU32  reserced[4];
    mfxU16  reserved4;
    mfxU16  BitDepthLuma; // 描述亮度的位数,不是所有的x和sdk都支持该值,具体可Query查询是否支持
    mfxU16  BitDepthChroma; // 描述色度的位数,同上
    mfxU16  Shift;

    mfxFrameId FrameId;

    mfxU32  FourCC; // 色彩fourcc(nv12,rgb...)
    union {
        struct { /* Frame parameters */
            /* 宽高即视频帧的像素,必须是16的倍数,对于逐行帧序列,高位32的倍数 */
            mfxU16  Width;
            mfxU16  Height;
            /* 帧的显示区域,指定了videoparam中的显示宽高 */
            mfxU16  CropX;
            mfxU16  CropY;
            mfxU16  CropW;
            mfxU16  CropH;
        };
        struct { /* Buffer parameters (for plain formats like P8) */
            mfxU64 BufferSize; // frame buffer的字节数,仅适用于plain格式(p8),w, h, crop这种情况下是无效的
            mfxU32 reserved5;
        };
    };
    /* 帧率公式ExtN/ExtD,如果是编码,必须指定帧率,若为解码,帧率可能是未指定的(ExtN,ExtD都为0),此时帧率默认30fps */
    mfxU32  FrameRateExtN; // 分子
    mfxU32  FrameRateExtD; // 分母
    mfxU16  reserved3;
    /* 指定了sample的长宽比,如果都为0,采用默认,否则参考规范和公式,对于264比例无限制 */
    mfxU16  AspectRatioW;
    mfxU16  AspectRatioH;

    mfxU16  PicStruct;
    mfxU16  ChromaFormat; // 颜色采样的方式(420,422...),0为不指定
    mfxU16  reserved2;
}  mfxFrameInfo;

顾名思义,描述了视频帧的属性。初始情况下IsVppRequired也没有执行什么,直接return false了。
接下来直接执行bitstream里的帧率判断了。因为ExtN和ExtD都为0,所以分别设30,1,帧率默认30。比例为1:1。因为不设多视角,接着numViews = 1。Vpp是不使用的,m_mfxVideoParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY(输出到系统内存)。
至此初始化完毕。
2. 解码过程,RunDecoding(),先看其中涉及的重要的结构体。

typedef struct {
    mfxU32  reserved[4];
    mfxFrameInfo    Info; // 描述帧的属性
    mfxFrameData    Data; // 帧的真实数据
} mfxFrameSurface1;
typedef struct {
    union {
        mfxExtBuffer **ExtParam;
        mfxU64       reserved2;
    };
    mfxU16  NumExtParam;

    mfxU16      reserved[9];
    mfxU16      MemType;
    mfxU16      PitchHigh; // 帧中两个连续行的起始字节数之差

    mfxU64      TimeStamp;
    mfxU32      FrameOrder;
    mfxU16      Locked; // app的计数标识,若>0,app会锁住帧或场对(2),此时不能移动修改和删除
    union {
        mfxU16  Pitch;
        mfxU16  PitchLow;
    };
    /* color planes */
    ...
    mfxU8       *A;
    mfxMemId    MemId;

    /* Additional Flags */
    mfxU16  Corrupted;
    mfxU16  DataFlag;
}  mfxFrameData;

该结构体定义了未压缩的帧面信息和数据buffer。帧面在帧或者互补场成对像素中多达四个色彩通道。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值