使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流
<p> 本文门槛较高,因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵<br> 如果你跟随这篇文章实现了播放器,那你会得到一个高效率,无cpu占用(cpu仅用作网络数据接收和从数据入显存,因此几乎看不出占用),且代码和引用精简(无其他托管和非托管的dll依赖,更无需安装任何插件,你的程序完全绿色运行);并且如果硬解不可用,切换到软件是自动过程</p><p> </p>
<p> 首先需要准备好visual studio/msys2/ffmpeg源码/dx9sdk。因为我们要自己编译ffmpeg,并且是改动代码后编译,ffmpeg我们编译时会裁剪。</p>
<p> ffmpeg源码大家使用4.2.1,和我保持同步,这样比较好对应,下载地址为ffmpeg-4.2.1.tar.gz</p>
<p> msys2安装好后不需要装mingw和其他东西,只需要安装make(见下方图片;我们编译工具链会用msvc而非mingw-gcc)</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123125637758-117967469.png" alt="" loading="lazy"></p>
<p> visual studio版本新一些更好,需要安装c++和c#的模块(见下方图片;应该也不需要特意去打开什么功能)</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123130039588-753219373.png" alt="" loading="lazy"></p>
<p> dx9的sdk理论上是不用安装的(如果你是高手,可以用c#的ilgenerator直接写calli;亦或者写unsafe代码直接进行内存call,文章最后我会为大家揭秘如何用c#调用c++甚至com组件)。我用了directx的managecode,由官方为我们做了dx的调用(见下方图片)</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123152133495-1554327199.png" alt="" loading="lazy"></p>
<p> </p>
<p> 第二步是修改ffmpeg源码并编译,我们要修改的源码只有一个文件的十余行,而且是增量修改。</p>
<p> 修改的文件位于libavutil/hwcontext_dxva2.c文件,我先将修改部分贴出来然后再给大家解释</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_404f6b13-b82c-4d50-9fda-4b8e136299a5" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_404f6b13-b82c-4d50-9fda-4b8e136299a5" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_404f6b13-b82c-4d50-9fda-4b8e136299a5" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> dxva2_device_create9_extend(AVHWDeviceContext *<span style="color: rgba(0, 0, 0, 1)">ctx, UINT adapter, HWND hWnd)
{
DXVA2DevicePriv </span>*priv = ctx-><span style="color: rgba(0, 0, 0, 1)">user_opaque;
D3DPRESENT_PARAMETERS d3dpp </span>= {<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">};
D3DDISPLAYMODE d3ddm;
HRESULT hr;
pDirect3DCreate9 </span>*createD3D = (pDirect3DCreate9 *)dlsym(priv->d3dlib, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Direct3DCreate9</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">createD3D) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to locate Direct3DCreate9\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
priv</span>->d3d9 =<span style="color: rgba(0, 0, 0, 1)"> createD3D(D3D_SDK_VERSION);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!priv-><span style="color: rgba(0, 0, 0, 1)">d3d9) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to create IDirect3D object\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
IDirect3D9_GetAdapterDisplayMode(priv</span>->d3d9, adapter, &<span style="color: rgba(0, 0, 0, 1)">d3ddm);
d3dpp.BackBufferFormat </span>=<span style="color: rgba(0, 0, 0, 1)"> d3ddm.Format;
d3dpp.Windowed </span>= TRUE; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 是否窗口显示 </span>
d3dpp.hDeviceWindow = hWnd; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示窗口句柄</span>
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 交换链设置,后台缓冲使用后直接丢弃</span>
d3dpp.Flags = D3DPRESENTFLAG_VIDEO; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 附加特性,显示视频</span>
<span style="color: rgba(0, 0, 0, 1)">
DWORD behaviorFlags </span>= D3DCREATE_MULTITHREADED |<span style="color: rgba(0, 0, 0, 1)"> D3DCREATE_FPU_PRESERVE;
D3DDEVTYPE devType </span>=<span style="color: rgba(0, 0, 0, 1)"> D3DDEVTYPE_HAL;
D3DCAPS9 caps;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (IDirect3D9_GetDeviceCaps(priv->d3d9, D3DADAPTER_DEFAULT, devType, &caps) >= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (caps.DevCaps &<span style="color: rgba(0, 0, 0, 1)"> D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
behaviorFlags </span>|=<span style="color: rgba(0, 0, 0, 1)"> D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
behaviorFlags </span>|=<span style="color: rgba(0, 0, 0, 1)"> D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">hWnd)
hWnd </span>=<span style="color: rgba(0, 0, 0, 1)"> GetDesktopWindow();
hr </span>= IDirect3D9_CreateDevice(priv-><span style="color: rgba(0, 0, 0, 1)">d3d9, adapter, D3DDEVTYPE_HAL, hWnd,
behaviorFlags,
</span>&d3dpp, &priv-><span style="color: rgba(0, 0, 0, 1)">d3d9device);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to create Direct3D device\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> dxva2_device_create(AVHWDeviceContext *ctx, <span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">char</span> *<span style="color: rgba(0, 0, 0, 1)">device,
AVDictionary </span>*opts, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> flags)
{
AVDXVA2DeviceContext </span>*hwctx = ctx-><span style="color: rgba(0, 0, 0, 1)">hwctx;
DXVA2DevicePriv </span>*<span style="color: rgba(0, 0, 0, 1)">priv;
pCreateDeviceManager9 </span>*createDeviceManager =<span style="color: rgba(0, 0, 0, 1)"> NULL;
unsigned resetToken </span>= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
UINT adapter </span>=<span style="color: rgba(0, 0, 0, 1)"> D3DADAPTER_DEFAULT;
HRESULT hr;
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> err;
AVDictionaryEntry </span>*t =<span style="color: rgba(0, 0, 0, 1)"> NULL;
HWND hWnd </span>=<span style="color: rgba(0, 0, 0, 1)"> NULL;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (device)
adapter </span>=<span style="color: rgba(0, 0, 0, 1)"> atoi(device);
priv </span>= av_mallocz(<span style="color: rgba(0, 0, 255, 1)">sizeof</span>(*<span style="color: rgba(0, 0, 0, 1)">priv));
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">priv)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR(ENOMEM);
ctx</span>->user_opaque =<span style="color: rgba(0, 0, 0, 1)"> priv;
ctx</span>-><span style="color: rgba(0, 0, 255, 1)">free</span> =<span style="color: rgba(0, 0, 0, 1)"> dxva2_device_free;
priv</span>->device_handle =<span style="color: rgba(0, 0, 0, 1)"> INVALID_HANDLE_VALUE;
priv</span>->d3dlib = dlopen(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">d3d9.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!priv-><span style="color: rgba(0, 0, 0, 1)">d3dlib) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to load D3D9 library\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
priv</span>->dxva2lib = dlopen(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dxva2.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!priv-><span style="color: rgba(0, 0, 0, 1)">dxva2lib) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to load DXVA2 library\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
createDeviceManager </span>= (pCreateDeviceManager9 *)dlsym(priv-><span style="color: rgba(0, 0, 0, 1)">dxva2lib,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DXVA2CreateDirect3DDeviceManager9</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">createDeviceManager) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to locate DXVA2CreateDirect3DDeviceManager9\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
t </span>= av_dict_get(opts, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hWnd</span><span style="color: rgba(128, 0, 0, 1)">"</span>, NULL, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(t) {
hWnd </span>= (HWND)atoi(t-><span style="color: rgba(0, 0, 0, 1)">value);
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(hWnd) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span>((err = dxva2_device_create9_extend(ctx, adapter, hWnd)) < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (dxva2_device_create9ex(ctx, adapter) < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Retry with "classic" d3d9</span>
err =<span style="color: rgba(0, 0, 0, 1)"> dxva2_device_create9(ctx, adapter);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> err;
}
}
hr </span>= createDeviceManager(&resetToken, &hwctx-><span style="color: rgba(0, 0, 0, 1)">devmgr);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to create Direct3D device manager\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
hr </span>= IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv-><span style="color: rgba(0, 0, 0, 1)">d3d9device, resetToken);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to bind Direct3D device to device manager\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
hr </span>= IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv-><span style="color: rgba(0, 0, 0, 1)">device_handle);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Failed to open device handle\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AVERROR_UNKNOWN;
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<span class="cnblogs_code_collapse">hwcontext_dxva2.c修改部分</span></div>
<p> 代码中dxva2_device_create9_extend函数是我新加入的,并且在dxva2_device_create函数(这个函数是ffmpeg原始流程中的,我的改动不影响原本任何功能)中适时调用;简单来说,原来的ffmpeg也能基于dxva2硬件解码,但是它没法将解码得到的surface用于前台播放,因为它创建device时并未指定窗口和其他相关参数,大家可以参考我代码实现,我将窗口句柄传入后创建过程完全改变(其他人如果使用我们编译的代码,他没有传入窗口句柄,就执行原来的创建,因此百分百兼容)。</p>
<p> 原始文件(版本不一致,仅供参考)</p>
<p> (ps:在这里我讲一下网络上另外一种写法(两年前我也用的他们的,因为没时间详细看ffmpeg源码),他们是在外面创建的device和surface然后想办法传到ffmpeg内部进行替换,这样做有好处,就是不用自己修改和编译ffmpeg,坏处是得自己维护device和surface。至于二进制兼容方面考虑,两种做法都不是太好)</p>
<p> 代码修改完成后我们使用msys2编译</p>
<p> 首先是需要把编译器设置为msvc,这个步骤通过使用vs的命令行工具即可,如下图</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123132818896-285810337.png" alt="" loading="lazy"></p>
<p> 然后是设置msys2继承环境变量(这样make时才能找到cl/link)</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123133057808-1106550836.png" alt="" loading="lazy"></p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123133208323-690120576.png" alt="" loading="lazy"></p>
<p> 打开msys,查看变量是否正确</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123133353672-1953857221.png" alt="" loading="lazy"></p>
<p> 编译ffmpeg</p>
<div class="cnblogs_code">
<pre>./configure --enable-shared --enable-small --disable-all --disable-autodetect --enable-avcodec --enable-decoder=h264 --enable-dxva2 --enable-hwaccel=h264_dxva2 --toolchain=msvc --prefix=<span style="color: rgba(0, 0, 0, 1)">host
make && make install</span></pre>
</div>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123133619825-1116403300.png" alt="" loading="lazy"></p>
<p> 编译完成后头文件和dll在host文件夹内(编译产出的dll也是clear的,不依赖msvc**.dll)</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123133750107-285595466.png" alt="" loading="lazy"></p>
<p> 在C#中使用我们产出的方式需要使用p/invoke和unsafe代码。</p>
<p> 我先贴出我针对ffmpeg写的一个工具类,然后给大家稍微讲解一下</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_b29cd179-2909-4742-bf9b-0bebf7e6df3b" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_b29cd179-2909-4742-bf9b-0bebf7e6df3b" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_b29cd179-2909-4742-bf9b-0bebf7e6df3b" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Runtime.InteropServices;
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> MultiPlayer
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> AVCodecID
{
AV_CODEC_ID_NONE,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> video codecs </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_MPEG1VIDEO,
AV_CODEC_ID_MPEG2VIDEO, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< preferred ID for MPEG-1/2 video decoding
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_H261,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_H263,
AV_CODEC_ID_RV10,
AV_CODEC_ID_RV20,
AV_CODEC_ID_MJPEG,
AV_CODEC_ID_MJPEGB,
AV_CODEC_ID_LJPEG,
AV_CODEC_ID_SP5X,
AV_CODEC_ID_JPEGLS,
AV_CODEC_ID_MPEG4,
AV_CODEC_ID_RAWVIDEO,
AV_CODEC_ID_MSMPEG4V1,
AV_CODEC_ID_MSMPEG4V2,
AV_CODEC_ID_MSMPEG4V3,
AV_CODEC_ID_WMV1,
AV_CODEC_ID_WMV2,
AV_CODEC_ID_H263P,
AV_CODEC_ID_H263I,
AV_CODEC_ID_FLV1,
AV_CODEC_ID_SVQ1,
AV_CODEC_ID_SVQ3,
AV_CODEC_ID_DVVIDEO,
AV_CODEC_ID_HUFFYUV,
AV_CODEC_ID_CYUV,
AV_CODEC_ID_H264,
AV_CODEC_ID_INDEO3,
AV_CODEC_ID_VP3,
AV_CODEC_ID_THEORA,
AV_CODEC_ID_ASV1,
AV_CODEC_ID_ASV2,
AV_CODEC_ID_FFV1,
AV_CODEC_ID_4XM,
AV_CODEC_ID_VCR1,
AV_CODEC_ID_CLJR,
AV_CODEC_ID_MDEC,
AV_CODEC_ID_ROQ,
AV_CODEC_ID_INTERPLAY_VIDEO,
AV_CODEC_ID_XAN_WC3,
AV_CODEC_ID_XAN_WC4,
AV_CODEC_ID_RPZA,
AV_CODEC_ID_CINEPAK,
AV_CODEC_ID_WS_VQA,
AV_CODEC_ID_MSRLE,
AV_CODEC_ID_MSVIDEO1,
AV_CODEC_ID_IDCIN,
AV_CODEC_ID_8BPS,
AV_CODEC_ID_SMC,
AV_CODEC_ID_FLIC,
AV_CODEC_ID_TRUEMOTION1,
AV_CODEC_ID_VMDVIDEO,
AV_CODEC_ID_MSZH,
AV_CODEC_ID_ZLIB,
AV_CODEC_ID_QTRLE,
AV_CODEC_ID_TSCC,
AV_CODEC_ID_ULTI,
AV_CODEC_ID_QDRAW,
AV_CODEC_ID_VIXL,
AV_CODEC_ID_QPEG,
AV_CODEC_ID_PNG,
AV_CODEC_ID_PPM,
AV_CODEC_ID_PBM,
AV_CODEC_ID_PGM,
AV_CODEC_ID_PGMYUV,
AV_CODEC_ID_PAM,
AV_CODEC_ID_FFVHUFF,
AV_CODEC_ID_RV30,
AV_CODEC_ID_RV40,
AV_CODEC_ID_VC1,
AV_CODEC_ID_WMV3,
AV_CODEC_ID_LOCO,
AV_CODEC_ID_WNV1,
AV_CODEC_ID_AASC,
AV_CODEC_ID_INDEO2,
AV_CODEC_ID_FRAPS,
AV_CODEC_ID_TRUEMOTION2,
AV_CODEC_ID_BMP,
AV_CODEC_ID_CSCD,
AV_CODEC_ID_MMVIDEO,
AV_CODEC_ID_ZMBV,
AV_CODEC_ID_AVS,
AV_CODEC_ID_SMACKVIDEO,
AV_CODEC_ID_NUV,
AV_CODEC_ID_KMVC,
AV_CODEC_ID_FLASHSV,
AV_CODEC_ID_CAVS,
AV_CODEC_ID_JPEG2000,
AV_CODEC_ID_VMNC,
AV_CODEC_ID_VP5,
AV_CODEC_ID_VP6,
AV_CODEC_ID_VP6F,
AV_CODEC_ID_TARGA,
AV_CODEC_ID_DSICINVIDEO,
AV_CODEC_ID_TIERTEXSEQVIDEO,
AV_CODEC_ID_TIFF,
AV_CODEC_ID_GIF,
AV_CODEC_ID_DXA,
AV_CODEC_ID_DNXHD,
AV_CODEC_ID_THP,
AV_CODEC_ID_SGI,
AV_CODEC_ID_C93,
AV_CODEC_ID_BETHSOFTVID,
AV_CODEC_ID_PTX,
AV_CODEC_ID_TXD,
AV_CODEC_ID_VP6A,
AV_CODEC_ID_AMV,
AV_CODEC_ID_VB,
AV_CODEC_ID_PCX,
AV_CODEC_ID_SUNRAST,
AV_CODEC_ID_INDEO4,
AV_CODEC_ID_INDEO5,
AV_CODEC_ID_MIMIC,
AV_CODEC_ID_RL2,
AV_CODEC_ID_ESCAPE124,
AV_CODEC_ID_DIRAC,
AV_CODEC_ID_BFI,
AV_CODEC_ID_CMV,
AV_CODEC_ID_MOTIONPIXELS,
AV_CODEC_ID_TGV,
AV_CODEC_ID_TGQ,
AV_CODEC_ID_TQI,
AV_CODEC_ID_AURA,
AV_CODEC_ID_AURA2,
AV_CODEC_ID_V210X,
AV_CODEC_ID_TMV,
AV_CODEC_ID_V210,
AV_CODEC_ID_DPX,
AV_CODEC_ID_MAD,
AV_CODEC_ID_FRWU,
AV_CODEC_ID_FLASHSV2,
AV_CODEC_ID_CDGRAPHICS,
AV_CODEC_ID_R210,
AV_CODEC_ID_ANM,
AV_CODEC_ID_BINKVIDEO,
AV_CODEC_ID_IFF_ILBM,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_KGV1,
AV_CODEC_ID_YOP,
AV_CODEC_ID_VP8,
AV_CODEC_ID_PICTOR,
AV_CODEC_ID_ANSI,
AV_CODEC_ID_A64_MULTI,
AV_CODEC_ID_A64_MULTI5,
AV_CODEC_ID_R10K,
AV_CODEC_ID_MXPEG,
AV_CODEC_ID_LAGARITH,
AV_CODEC_ID_PRORES,
AV_CODEC_ID_JV,
AV_CODEC_ID_DFA,
AV_CODEC_ID_WMV3IMAGE,
AV_CODEC_ID_VC1IMAGE,
AV_CODEC_ID_UTVIDEO,
AV_CODEC_ID_BMV_VIDEO,
AV_CODEC_ID_VBLE,
AV_CODEC_ID_DXTORY,
AV_CODEC_ID_V410,
AV_CODEC_ID_XWD,
AV_CODEC_ID_CDXL,
AV_CODEC_ID_XBM,
AV_CODEC_ID_ZEROCODEC,
AV_CODEC_ID_MSS1,
AV_CODEC_ID_MSA1,
AV_CODEC_ID_TSCC2,
AV_CODEC_ID_MTS2,
AV_CODEC_ID_CLLC,
AV_CODEC_ID_MSS2,
AV_CODEC_ID_VP9,
AV_CODEC_ID_AIC,
AV_CODEC_ID_ESCAPE130,
AV_CODEC_ID_G2M,
AV_CODEC_ID_WEBP,
AV_CODEC_ID_HNM4_VIDEO,
AV_CODEC_ID_HEVC,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_FIC,
AV_CODEC_ID_ALIAS_PIX,
AV_CODEC_ID_BRENDER_PIX,
AV_CODEC_ID_PAF_VIDEO,
AV_CODEC_ID_EXR,
AV_CODEC_ID_VP7,
AV_CODEC_ID_SANM,
AV_CODEC_ID_SGIRLE,
AV_CODEC_ID_MVC1,
AV_CODEC_ID_MVC2,
AV_CODEC_ID_HQX,
AV_CODEC_ID_TDSC,
AV_CODEC_ID_HQ_HQA,
AV_CODEC_ID_HAP,
AV_CODEC_ID_DDS,
AV_CODEC_ID_DXV,
AV_CODEC_ID_SCREENPRESSO,
AV_CODEC_ID_RSCC,
AV_CODEC_ID_AVS2,
AV_CODEC_ID_Y41P </span>= <span style="color: rgba(128, 0, 128, 1)">0x8000</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_AVRP,
AV_CODEC_ID_012V,
AV_CODEC_ID_AVUI,
AV_CODEC_ID_AYUV,
AV_CODEC_ID_TARGA_Y216,
AV_CODEC_ID_V308,
AV_CODEC_ID_V408,
AV_CODEC_ID_YUV4,
AV_CODEC_ID_AVRN,
AV_CODEC_ID_CPIA,
AV_CODEC_ID_XFACE,
AV_CODEC_ID_SNOW,
AV_CODEC_ID_SMVJPEG,
AV_CODEC_ID_APNG,
AV_CODEC_ID_DAALA,
AV_CODEC_ID_CFHD,
AV_CODEC_ID_TRUEMOTION2RT,
AV_CODEC_ID_M101,
AV_CODEC_ID_MAGICYUV,
AV_CODEC_ID_SHEERVIDEO,
AV_CODEC_ID_YLC,
AV_CODEC_ID_PSD,
AV_CODEC_ID_PIXLET,
AV_CODEC_ID_SPEEDHQ,
AV_CODEC_ID_FMVC,
AV_CODEC_ID_SCPR,
AV_CODEC_ID_CLEARVIDEO,
AV_CODEC_ID_XPM,
AV_CODEC_ID_AV1,
AV_CODEC_ID_BITPACKED,
AV_CODEC_ID_MSCC,
AV_CODEC_ID_SRGC,
AV_CODEC_ID_SVG,
AV_CODEC_ID_GDV,
AV_CODEC_ID_FITS,
AV_CODEC_ID_IMM4,
AV_CODEC_ID_PROSUMER,
AV_CODEC_ID_MWSC,
AV_CODEC_ID_WCMV,
AV_CODEC_ID_RASC,
AV_CODEC_ID_HYMT,
AV_CODEC_ID_ARBC,
AV_CODEC_ID_AGM,
AV_CODEC_ID_LSCR,
AV_CODEC_ID_VP4,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> various PCM "codecs" </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_FIRST_AUDIO </span>= <span style="color: rgba(128, 0, 128, 1)">0x10000</span>, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< A dummy id pointing at the start of audio codecs
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_PCM_S16LE = 0x10000,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_PCM_S16BE,
AV_CODEC_ID_PCM_U16LE,
AV_CODEC_ID_PCM_U16BE,
AV_CODEC_ID_PCM_S8,
AV_CODEC_ID_PCM_U8,
AV_CODEC_ID_PCM_MULAW,
AV_CODEC_ID_PCM_ALAW,
AV_CODEC_ID_PCM_S32LE,
AV_CODEC_ID_PCM_S32BE,
AV_CODEC_ID_PCM_U32LE,
AV_CODEC_ID_PCM_U32BE,
AV_CODEC_ID_PCM_S24LE,
AV_CODEC_ID_PCM_S24BE,
AV_CODEC_ID_PCM_U24LE,
AV_CODEC_ID_PCM_U24BE,
AV_CODEC_ID_PCM_S24DAUD,
AV_CODEC_ID_PCM_ZORK,
AV_CODEC_ID_PCM_S16LE_PLANAR,
AV_CODEC_ID_PCM_DVD,
AV_CODEC_ID_PCM_F32BE,
AV_CODEC_ID_PCM_F32LE,
AV_CODEC_ID_PCM_F64BE,
AV_CODEC_ID_PCM_F64LE,
AV_CODEC_ID_PCM_BLURAY,
AV_CODEC_ID_PCM_LXF,
AV_CODEC_ID_S302M,
AV_CODEC_ID_PCM_S8_PLANAR,
AV_CODEC_ID_PCM_S24LE_PLANAR,
AV_CODEC_ID_PCM_S32LE_PLANAR,
AV_CODEC_ID_PCM_S16BE_PLANAR,
AV_CODEC_ID_PCM_S64LE </span>= <span style="color: rgba(128, 0, 128, 1)">0x10800</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_PCM_S64BE,
AV_CODEC_ID_PCM_F16LE,
AV_CODEC_ID_PCM_F24LE,
AV_CODEC_ID_PCM_VIDC,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> various ADPCM codecs </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_ADPCM_IMA_QT </span>= <span style="color: rgba(128, 0, 128, 1)">0x11000</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_ADPCM_IMA_WAV,
AV_CODEC_ID_ADPCM_IMA_DK3,
AV_CODEC_ID_ADPCM_IMA_DK4,
AV_CODEC_ID_ADPCM_IMA_WS,
AV_CODEC_ID_ADPCM_IMA_SMJPEG,
AV_CODEC_ID_ADPCM_MS,
AV_CODEC_ID_ADPCM_4XM,
AV_CODEC_ID_ADPCM_XA,
AV_CODEC_ID_ADPCM_ADX,
AV_CODEC_ID_ADPCM_EA,
AV_CODEC_ID_ADPCM_G726,
AV_CODEC_ID_ADPCM_CT,
AV_CODEC_ID_ADPCM_SWF,
AV_CODEC_ID_ADPCM_YAMAHA,
AV_CODEC_ID_ADPCM_SBPRO_4,
AV_CODEC_ID_ADPCM_SBPRO_3,
AV_CODEC_ID_ADPCM_SBPRO_2,
AV_CODEC_ID_ADPCM_THP,
AV_CODEC_ID_ADPCM_IMA_AMV,
AV_CODEC_ID_ADPCM_EA_R1,
AV_CODEC_ID_ADPCM_EA_R3,
AV_CODEC_ID_ADPCM_EA_R2,
AV_CODEC_ID_ADPCM_IMA_EA_SEAD,
AV_CODEC_ID_ADPCM_IMA_EA_EACS,
AV_CODEC_ID_ADPCM_EA_XAS,
AV_CODEC_ID_ADPCM_EA_MAXIS_XA,
AV_CODEC_ID_ADPCM_IMA_ISS,
AV_CODEC_ID_ADPCM_G722,
AV_CODEC_ID_ADPCM_IMA_APC,
AV_CODEC_ID_ADPCM_VIMA,
AV_CODEC_ID_ADPCM_AFC </span>= <span style="color: rgba(128, 0, 128, 1)">0x11800</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_ADPCM_IMA_OKI,
AV_CODEC_ID_ADPCM_DTK,
AV_CODEC_ID_ADPCM_IMA_RAD,
AV_CODEC_ID_ADPCM_G726LE,
AV_CODEC_ID_ADPCM_THP_LE,
AV_CODEC_ID_ADPCM_PSX,
AV_CODEC_ID_ADPCM_AICA,
AV_CODEC_ID_ADPCM_IMA_DAT4,
AV_CODEC_ID_ADPCM_MTAF,
AV_CODEC_ID_ADPCM_AGM,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> AMR </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_AMR_NB </span>= <span style="color: rgba(128, 0, 128, 1)">0x12000</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_AMR_WB,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> RealAudio codecs</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_RA_144 </span>= <span style="color: rgba(128, 0, 128, 1)">0x13000</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_RA_288,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> various DPCM codecs </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_ROQ_DPCM </span>= <span style="color: rgba(128, 0, 128, 1)">0x14000</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_INTERPLAY_DPCM,
AV_CODEC_ID_XAN_DPCM,
AV_CODEC_ID_SOL_DPCM,
AV_CODEC_ID_SDX2_DPCM </span>= <span style="color: rgba(128, 0, 128, 1)">0x14800</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_GREMLIN_DPCM,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> audio codecs </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_MP2 </span>= <span style="color: rgba(128, 0, 128, 1)">0x15000</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_MP3, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< preferred ID for decoding MPEG audio layer 1, 2 or 3
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_AAC,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_AC3,
AV_CODEC_ID_DTS,
AV_CODEC_ID_VORBIS,
AV_CODEC_ID_DVAUDIO,
AV_CODEC_ID_WMAV1,
AV_CODEC_ID_WMAV2,
AV_CODEC_ID_MACE3,
AV_CODEC_ID_MACE6,
AV_CODEC_ID_VMDAUDIO,
AV_CODEC_ID_FLAC,
AV_CODEC_ID_MP3ADU,
AV_CODEC_ID_MP3ON4,
AV_CODEC_ID_SHORTEN,
AV_CODEC_ID_ALAC,
AV_CODEC_ID_WESTWOOD_SND1,
AV_CODEC_ID_GSM, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< as in Berlin toast format
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_QDM2,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_COOK,
AV_CODEC_ID_TRUESPEECH,
AV_CODEC_ID_TTA,
AV_CODEC_ID_SMACKAUDIO,
AV_CODEC_ID_QCELP,
AV_CODEC_ID_WAVPACK,
AV_CODEC_ID_DSICINAUDIO,
AV_CODEC_ID_IMC,
AV_CODEC_ID_MUSEPACK7,
AV_CODEC_ID_MLP,
AV_CODEC_ID_GSM_MS, </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> as found in WAV </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_ATRAC3,
AV_CODEC_ID_APE,
AV_CODEC_ID_NELLYMOSER,
AV_CODEC_ID_MUSEPACK8,
AV_CODEC_ID_SPEEX,
AV_CODEC_ID_WMAVOICE,
AV_CODEC_ID_WMAPRO,
AV_CODEC_ID_WMALOSSLESS,
AV_CODEC_ID_ATRAC3P,
AV_CODEC_ID_EAC3,
AV_CODEC_ID_SIPR,
AV_CODEC_ID_MP1,
AV_CODEC_ID_TWINVQ,
AV_CODEC_ID_TRUEHD,
AV_CODEC_ID_MP4ALS,
AV_CODEC_ID_ATRAC1,
AV_CODEC_ID_BINKAUDIO_RDFT,
AV_CODEC_ID_BINKAUDIO_DCT,
AV_CODEC_ID_AAC_LATM,
AV_CODEC_ID_QDMC,
AV_CODEC_ID_CELT,
AV_CODEC_ID_G723_1,
AV_CODEC_ID_G729,
AV_CODEC_ID_8SVX_EXP,
AV_CODEC_ID_8SVX_FIB,
AV_CODEC_ID_BMV_AUDIO,
AV_CODEC_ID_RALF,
AV_CODEC_ID_IAC,
AV_CODEC_ID_ILBC,
AV_CODEC_ID_OPUS,
AV_CODEC_ID_COMFORT_NOISE,
AV_CODEC_ID_TAK,
AV_CODEC_ID_METASOUND,
AV_CODEC_ID_PAF_AUDIO,
AV_CODEC_ID_ON2AVC,
AV_CODEC_ID_DSS_SP,
AV_CODEC_ID_CODEC2,
AV_CODEC_ID_FFWAVESYNTH </span>= <span style="color: rgba(128, 0, 128, 1)">0x15800</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_SONIC,
AV_CODEC_ID_SONIC_LS,
AV_CODEC_ID_EVRC,
AV_CODEC_ID_SMV,
AV_CODEC_ID_DSD_LSBF,
AV_CODEC_ID_DSD_MSBF,
AV_CODEC_ID_DSD_LSBF_PLANAR,
AV_CODEC_ID_DSD_MSBF_PLANAR,
AV_CODEC_ID_4GV,
AV_CODEC_ID_INTERPLAY_ACM,
AV_CODEC_ID_XMA1,
AV_CODEC_ID_XMA2,
AV_CODEC_ID_DST,
AV_CODEC_ID_ATRAC3AL,
AV_CODEC_ID_ATRAC3PAL,
AV_CODEC_ID_DOLBY_E,
AV_CODEC_ID_APTX,
AV_CODEC_ID_APTX_HD,
AV_CODEC_ID_SBC,
AV_CODEC_ID_ATRAC9,
AV_CODEC_ID_HCOM,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> subtitle codecs </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_FIRST_SUBTITLE </span>= <span style="color: rgba(128, 0, 128, 1)">0x17000</span>, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< A dummy ID pointing at the start of subtitle codecs.
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_DVD_SUBTITLE = 0x17000,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_DVB_SUBTITLE,
AV_CODEC_ID_TEXT,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< raw UTF-8 text
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_XSUB,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_SSA,
AV_CODEC_ID_MOV_TEXT,
AV_CODEC_ID_HDMV_PGS_SUBTITLE,
AV_CODEC_ID_DVB_TELETEXT,
AV_CODEC_ID_SRT,
AV_CODEC_ID_MICRODVD </span>= <span style="color: rgba(128, 0, 128, 1)">0x17800</span><span style="color: rgba(0, 0, 0, 1)">,
AV_CODEC_ID_EIA_608,
AV_CODEC_ID_JACOSUB,
AV_CODEC_ID_SAMI,
AV_CODEC_ID_REALTEXT,
AV_CODEC_ID_STL,
AV_CODEC_ID_SUBVIEWER1,
AV_CODEC_ID_SUBVIEWER,
AV_CODEC_ID_SUBRIP,
AV_CODEC_ID_WEBVTT,
AV_CODEC_ID_MPL2,
AV_CODEC_ID_VPLAYER,
AV_CODEC_ID_PJS,
AV_CODEC_ID_ASS,
AV_CODEC_ID_HDMV_TEXT_SUBTITLE,
AV_CODEC_ID_TTML,
AV_CODEC_ID_ARIB_CAPTION,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> other specific kind of codecs (generally used for attachments) </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_FIRST_UNKNOWN </span>= <span style="color: rgba(128, 0, 128, 1)">0x18000</span>, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< A dummy ID pointing at the start of various fake codecs.
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_TTF = 0x18000,</span>
<span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_SCTE_35, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Contain timestamp estimated through PCR of program stream.
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_BINTEXT = 0x18800,</span>
<span style="color: rgba(0, 0, 0, 1)"> AV_CODEC_ID_XBIN,
AV_CODEC_ID_IDF,
AV_CODEC_ID_OTF,
AV_CODEC_ID_SMPTE_KLV,
AV_CODEC_ID_DVD_NAV,
AV_CODEC_ID_TIMED_ID3,
AV_CODEC_ID_BIN_DATA,
AV_CODEC_ID_PROBE </span>= <span style="color: rgba(128, 0, 128, 1)">0x19000</span>, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
</span>
AV_CODEC_ID_MPEG2TS = <span style="color: rgba(128, 0, 128, 1)">0x20000</span>, <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*< _FAKE_ codec to indicate a raw MPEG-2 TS
* stream (only used by libavformat) </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_MPEG4SYSTEMS </span>= <span style="color: rgba(128, 0, 128, 1)">0x20001</span>, <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*< _FAKE_ codec to indicate a MPEG-4 Systems
* stream (only used by libavformat) </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_CODEC_ID_FFMETADATA </span>= <span style="color: rgba(128, 0, 128, 1)">0x21000</span>, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Dummy codec for streams containing only metadata information.
</span><span style="color: rgba(0, 128, 0, 1)"> AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Passthrough codec, AVFrames wrapped in AVPacket
</span><span style="color: rgba(0, 128, 0, 1)"> }</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> AVHWDeviceType
{
AV_HWDEVICE_TYPE_NONE,
AV_HWDEVICE_TYPE_VDPAU,
AV_HWDEVICE_TYPE_CUDA,
AV_HWDEVICE_TYPE_VAAPI,
AV_HWDEVICE_TYPE_DXVA2,
AV_HWDEVICE_TYPE_QSV,
AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
AV_HWDEVICE_TYPE_D3D11VA,
AV_HWDEVICE_TYPE_DRM,
AV_HWDEVICE_TYPE_OPENCL,
AV_HWDEVICE_TYPE_MEDIACODEC,
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat
{
AV_PIX_FMT_NONE </span>= -<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">,
AV_PIX_FMT_YUV420P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUYV422, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB24, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 8:8:8, 24bpp, RGBRGB...
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR24, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 8:8:8, 24bpp, BGRBGR...
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV410P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:1:0,9bpp, (1 Cr & Cb sample per 4x4 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV411P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y ,8bpp
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_MONOWHITE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y ,1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_MONOBLACK, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y ,1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_PAL8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< 8 bits with AV_PIX_FMT_RGB32 palette
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVJ420P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVJ422P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVJ444P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_UYVY422, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_UYYVYY411, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 3:3:2,8bpp, (msb)2B 3G 3R(lsb)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR4, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 1:2:1 bitstream,4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR4_BYTE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 1:2:1,8bpp, (msb)1B 2G 1R(lsb)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 3:3:2,8bpp, (msb)2R 3G 3B(lsb)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB4, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 1:2:1 bitstream,4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB4_BYTE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 1:2:1,8bpp, (msb)1R 2G 1B(lsb)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_NV12, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_NV21, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< as above, but U and V bytes are swapped
</span>
AV_PIX_FMT_ARGB, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGBA, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_ABGR, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGRA, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
</span>
AV_PIX_FMT_GRAY16BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 16bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY16LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 16bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV440P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVJ440P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB48BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB48LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
</span>
AV_PIX_FMT_RGB565BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB565LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB555BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB555LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
</span>
AV_PIX_FMT_BGR565BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR565LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR555BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR555LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">* @name Deprecated pixel formats </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*@{</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_VAAPI_MOCO, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< HW acceleration through VA API at motion compensation entry-point, Picture.data contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_VAAPI_IDCT, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< HW acceleration through VA API at IDCT entry-point, Picture.data contains a vaapi_render_state struct which contains fields extracted from headers
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_VAAPI_VLD,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< HW decoding through VA API, Picture.data contains a VASurfaceID
</span><span style="color: rgba(0, 128, 0, 1)"> /**@}*/</span>
AV_PIX_FMT_VAAPI =<span style="color: rgba(0, 0, 0, 1)"> AV_PIX_FMT_VAAPI_VLD,
AV_PIX_FMT_YUV420P16LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P16BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P16LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P16BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P16LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P16BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_DXVA2_VLD, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< HW decoding through DXVA2, Picture.data contains a LPDIRECT3DSURFACE9 pointer
</span>
AV_PIX_FMT_RGB444LE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB444BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR444LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR444BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YA8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< 8 bits gray, 8 bits alpha
</span>
AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< alias for AV_PIX_FMT_YA8
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY8A = AV_PIX_FMT_YA8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< alias for AV_PIX_FMT_YA8
</span>
AV_PIX_FMT_BGR48BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR48LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* The following 12 formats have the disadvantage of needing 1 format for each bit depth.
* Notice that each 9/10 bits sample is stored in 16 bits with extra padding.
* If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_YUV420P9BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P9LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P10BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P10LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P10BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P10LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P9BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P9LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P10BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P10LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P9BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P9LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 24bpp
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP</span>
AV_PIX_FMT_GBRP9BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 27bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP9LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 27bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP10BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 30bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP10LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 30bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP16BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 48bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP16LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 48bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P9BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P9LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P9BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P9LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P9BE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P9LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P10BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P10LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P10BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P10LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P10BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P10LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA420P16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
</span>
AV_PIX_FMT_VDPAU, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< HW acceleration through VDPAU, Picture.data contains a VdpVideoSurface
</span>
AV_PIX_FMT_XYZ12LE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_XYZ12BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_NV16, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_NV20LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_NV20BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
</span>
AV_PIX_FMT_RGBA64BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGBA64LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGRA64BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGRA64LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
</span>
AV_PIX_FMT_YVYU422, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
</span>
AV_PIX_FMT_YA16BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< 16 bits gray, 16 bits alpha (big-endian)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YA16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< 16 bits gray, 16 bits alpha (little-endian)
</span>
AV_PIX_FMT_GBRAP, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBRA 4:4:4:4 32bpp
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRAP16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBRA 4:4:4:4 64bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRAP16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBRA 4:4:4:4 64bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> /**</span>
*HW acceleration through QSV, data[<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">] contains a pointer to the
</span>*<span style="color: rgba(0, 0, 0, 1)">mfxFrameSurface1 structure.
</span>*/<span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_QSV,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* HW acceleration though MMAL, data contains a pointer to the
* MMAL_BUFFER_HEADER_T structure.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_MMAL,
AV_PIX_FMT_D3D11VA_VLD,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< HW decoding through Direct3D11 via old API, Picture.data contains a ID3D11VideoDecoderOutputView pointer
</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* HW acceleration through CUDA. data contain CUdeviceptr pointers
* exactly as for system memory frames.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_CUDA,
AV_PIX_FMT_0RGB, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_RGB0, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_0BGR, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BGR0, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
</span>
AV_PIX_FMT_YUV420P12BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P14BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV420P14LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P12BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P14BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV422P14LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P12BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P14BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV444P14LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP12BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 36bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 36bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP14BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 42bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRP14LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4 42bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVJ411P, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range
</span>
AV_PIX_FMT_BAYER_BGGR8, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_RGGB8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_GBRG8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_GRBG8, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_BGGR16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_BGGR16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_RGGB16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_RGGB16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_GBRG16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_GBRG16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_GRBG16LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_BAYER_GRBG16BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */
</span>
AV_PIX_FMT_XVMC,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< XVideo Motion Acceleration via common packet passing
</span>
AV_PIX_FMT_YUV440P10LE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV440P10BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV440P12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUV440P12BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_AYUV64LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_AYUV64BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
</span>
AV_PIX_FMT_VIDEOTOOLBOX, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< hardware decoding through Videotoolbox
</span>
AV_PIX_FMT_P010LE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_P010BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian
</span>
AV_PIX_FMT_GBRAP12BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4:4 48bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRAP12LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4:4 48bpp, little-endian
</span>
AV_PIX_FMT_GBRAP10BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4:4 40bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRAP10LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar GBR 4:4:4:4 40bpp, little-endian
</span>
AV_PIX_FMT_MEDIACODEC, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< hardware decoding through MediaCodec
</span>
AV_PIX_FMT_GRAY12BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 12bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 12bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY10BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 10bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY10LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 10bpp, little-endian
</span>
AV_PIX_FMT_P016LE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< like NV12, with 16bpp per component, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_P016BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< like NV12, with 16bpp per component, big-endian
</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* Hardware surfaces for Direct3D11.
*
* This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11
* hwaccel API and filtering support AV_PIX_FMT_D3D11 only.
*
* data contains a ID3D11Texture2D pointer, and data contains the
* texture array index of the frame as intptr_t if the ID3D11Texture2D is
* an array texture (or always 0 if it's a normal texture).
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_D3D11,
AV_PIX_FMT_GRAY9BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 9bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY9LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 9bpp, little-endian
</span>
AV_PIX_FMT_GBRPF32BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRPF32LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRAPF32BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GBRAPF32LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian
</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* DRM-managed buffers exposed through PRIME buffer sharing.
*
* data points to an AVDRMFrameDescriptor.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_DRM_PRIME,
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* Hardware surfaces for OpenCL.
*
* data contain 2D image objects (typed in C as cl_mem, used
* in OpenCL as image2d_t) for each plane of the surface.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
AV_PIX_FMT_OPENCL,
AV_PIX_FMT_GRAY14BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 14bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAY14LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< Y , 14bpp, little-endian
</span>
AV_PIX_FMT_GRAYF32BE,<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< IEEE-754 single precision Y, 32bpp, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_GRAYF32LE,</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< IEEE-754 single precision Y, 32bpp, little-endian
</span>
AV_PIX_FMT_YUVA422P12BE, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA422P12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P12BE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_YUVA444P12LE, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian
</span>
AV_PIX_FMT_NV24, <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
</span><span style="color: rgba(0, 128, 0, 1)"> AV_PIX_FMT_NV42, </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< as above, but U and V bytes are swapped
</span>
AV_PIX_FMT_NB <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(128, 128, 128, 1)">< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
</span><span style="color: rgba(0, 128, 0, 1)"> }
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg中AVFrame结构体的前半部分,因为它太长了我不需要完全移植过来
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> AVFrame
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">#define AV_NUM_DATA_POINTERS 8
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> uint8_t* data;</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> IntPtr data1;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一般是y分量</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> IntPtr data2;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一般是v分量</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> IntPtr data3;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一般是u分量</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> IntPtr data4;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一般是surface(dxva2硬解时)</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> IntPtr data5;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> IntPtr data6;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> IntPtr data7;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> IntPtr data8;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> linesize1;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> y分量每行长度(stride)</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> linesize2;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> v分量每行长度(stride)</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> linesize3;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> u分量每行长度(stride)</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> linesize4;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> linesize5;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> linesize6;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> linesize7;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> linesize8;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">uint8_t **extended_data;</span>
<span style="color: rgba(0, 0, 0, 1)"> IntPtr extended_data;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> width;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> height;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> nb_samples;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat format;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> AVCodec { }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">unsafe</span> <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> AVPacket
{
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> <span style="color: rgba(0, 0, 255, 1)">byte</span> frontUnused[<span style="color: rgba(128, 0, 128, 1)">24</span>]; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 前部无关数据</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span>*<span style="color: rgba(0, 0, 0, 1)"> data;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> size;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> AVBufferRef { }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">unsafe</span> <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> AVCodecContext
{
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> <span style="color: rgba(0, 0, 255, 1)">byte</span> frontUnused[<span style="color: rgba(128, 0, 128, 1)">880</span>]; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 前部无关数据</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> AVBufferRef*<span style="color: rgba(0, 0, 0, 1)"> hw_frames_ctx;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> AVDictionary { }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">unsafe</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> FFHelper
{
</span><span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">string</span> avcodec = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">avcodec-58</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">string</span> avutil = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">avutil-56</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">const</span> CallingConvention callingConvention =<span style="color: rgba(0, 0, 0, 1)"> CallingConvention.Cdecl;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> avcodec_register_all();
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AVCodec*<span style="color: rgba(0, 0, 0, 1)"> avcodec_find_decoder(AVCodecID id);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AVPacket*<span style="color: rgba(0, 0, 0, 1)"> av_packet_alloc();
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> av_init_packet(AVPacket*<span style="color: rgba(0, 0, 0, 1)"> pkt);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">public extern static void av_packet_unref(AVPacket* pkt);</span>
<span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> av_packet_free(AVPacket**<span style="color: rgba(0, 0, 0, 1)"> pkt);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AVCodecContext* avcodec_alloc_context3(AVCodec*<span style="color: rgba(0, 0, 0, 1)"> codec);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> avcodec_open2(AVCodecContext* avctx, AVCodec* codec, AVDictionary**<span style="color: rgba(0, 0, 0, 1)"> options);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">public extern static int avcodec_decode_video2(IntPtr avctx, IntPtr picture, ref int got_picture_ptr, IntPtr avpkt);</span>
<span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> avcodec_free_context(AVCodecContext**<span style="color: rgba(0, 0, 0, 1)"> avctx);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> avcodec_send_packet(AVCodecContext* avctx, AVPacket*<span style="color: rgba(0, 0, 0, 1)"> pkt);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> avcodec_receive_frame(AVCodecContext* avctx, AVFrame*<span style="color: rgba(0, 0, 0, 1)"> frame);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> av_hwdevice_ctx_create(AVBufferRef** device_ctx, AVHWDeviceType type, <span style="color: rgba(0, 0, 255, 1)">string</span> device, AVDictionary* opts, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> flags);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AVBufferRef* av_buffer_ref(AVBufferRef*<span style="color: rgba(0, 0, 0, 1)"> buf);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> av_buffer_unref(AVBufferRef**<span style="color: rgba(0, 0, 0, 1)"> buf);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AVFrame*<span style="color: rgba(0, 0, 0, 1)"> av_frame_alloc();
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> av_frame_free(AVFrame**<span style="color: rgba(0, 0, 0, 1)"> frame);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> av_log_set_level(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> level);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> av_dict_set_int(AVDictionary** pm, <span style="color: rgba(0, 0, 255, 1)">string</span> key, <span style="color: rgba(0, 0, 255, 1)">long</span> value, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> flags);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> av_dict_free(AVDictionary**<span style="color: rgba(0, 0, 0, 1)"> m);
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">FFHelper.cs</span></div>
<p> 上文中主要有几个地方是知识点,大家做c#的如果需要和底层交互可以了解一下</p>
<ul>
<li>结构体的使用</li>
</ul>
<p> 结构体在c#与c/c++基本一致,都是内存连续变量的一种组合方式。与c/c++相同,在c#中,如果我们不知道(或者可以规避,因为结构体可能很复杂,很多无关字段)结构体细节只知道结构体整体大小时,我们可以用***Pack=1,SizeConst=***来表示一个大小已知的结构体。</p>
<ul>
<li>指针的使用</li>
</ul>
<p> c#中,有两种存储内存地址(指针)的方式,一是使用interop体系中的IntPtr类型(大家可以将其想象成void*),一是在不安全的上下文(unsafe)中使用结构体类型指针(此处不讨论c++类指针)</p>
<ul>
<li>unsafe和fixed使用</li>
</ul>
<p> 简单来说,有了unsafe你才能用指针;而有了fixed你才能确保指针指向位置不被GC压缩。我们使用fixed达到的效果就是显式跳过了结构体中前部无关数据(参考上文中AVCodecContext等结构体定义),后文中我们还会使用fixed。</p>
<p> </p>
<p> 现在我们开始编写解码和播放部分(即我们的具体应用)代码</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_15fb3a7e-eb08-470c-8014-247b02ea8ae2" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_15fb3a7e-eb08-470c-8014-247b02ea8ae2" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_15fb3a7e-eb08-470c-8014-247b02ea8ae2" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.DirectX;
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.DirectX.Direct3D;
</span><span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Drawing;
</span><span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Runtime.InteropServices;
</span><span style="color: rgba(0, 128, 128, 1)">6</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 128, 128, 1)">7</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Windows.Forms;
</span><span style="color: rgba(0, 128, 128, 1)">8</span> <span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> MultiPlayer.FFHelper;
</span><span style="color: rgba(0, 128, 128, 1)">9</span>
<span style="color: rgba(0, 128, 128, 1)"> 10</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> MultiPlayer
</span><span style="color: rgba(0, 128, 128, 1)"> 11</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 12</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">unsafe</span> <span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> FFPlayer : UserControl
</span><span style="color: rgba(0, 128, 128, 1)"> 13</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 14</span>
</span><span style="color: rgba(0, 128, 128, 1)"> 15</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">void</span> memcpy(IntPtr dest, IntPtr src, <span style="color: rgba(0, 0, 255, 1)">int</span> count);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用于在解码器和directx间拷贝内存的c函数</span>
<span style="color: rgba(0, 128, 128, 1)"> 16</span>
<span style="color: rgba(0, 128, 128, 1)"> 17</span>
<span style="color: rgba(0, 128, 128, 1)"> 18</span> <span style="color: rgba(0, 0, 255, 1)">private</span> IntPtr contentPanelHandle; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 画面渲染的控件句柄,因为画面渲染时可能出于非UI线程,因此先保存句柄避免CLR报错</span>
<span style="color: rgba(0, 128, 128, 1)"> 19</span>
<span style="color: rgba(0, 128, 128, 1)"> 20</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span> lastIWidth, lastIHeight; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 上次控件大小,用于在控件大小改变时做出判定重新初始化渲染上下文</span>
<span style="color: rgba(0, 128, 128, 1)"> 21</span> <span style="color: rgba(0, 0, 255, 1)">private</span> Rectangle lastCBounds; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 临时变量,存储上次控件区域(屏幕坐标)</span>
<span style="color: rgba(0, 128, 128, 1)"> 22</span> <span style="color: rgba(0, 0, 255, 1)">private</span> Rectangle lastVRect; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 临时变量,存储上次解码出的图像大小</span>
<span style="color: rgba(0, 128, 128, 1)"> 23</span> <span style="color: rgba(0, 0, 255, 1)">private</span> Device device; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当使用软解时,这个变量生效,它是IDirect3Device9*对象,用于绘制YUV</span>
<span style="color: rgba(0, 128, 128, 1)"> 24</span> <span style="color: rgba(0, 0, 255, 1)">private</span> Surface surface; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当使用软解时,这个变量生效,它是IDirect3Surface9*对象,用于接受解码后的YUV数据</span>
<span style="color: rgba(0, 128, 128, 1)"> 25</span> AVPixelFormat lastFmt; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 上次解码出的图像数据类型,这个理论上不会变</span>
<span style="color: rgba(0, 128, 128, 1)"> 26</span>
<span style="color: rgba(0, 128, 128, 1)"> 27</span> AVCodec* codec; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的解码器</span>
<span style="color: rgba(0, 128, 128, 1)"> 28</span> AVCodecContext* ctx; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的解码上下文</span>
<span style="color: rgba(0, 128, 128, 1)"> 29</span> AVBufferRef* hw_ctx; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的解码器硬件加速上下文,作为ctx的扩展存在</span>
<span style="color: rgba(0, 128, 128, 1)"> 30</span> AVPacket* avpkt; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的数据包,用于封送待解码数据</span>
<span style="color: rgba(0, 128, 128, 1)"> 31</span> IntPtr nalData; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一块预分配内存,作为avpkt中真正存储数据的内存地址</span>
<span style="color: rgba(0, 128, 128, 1)"> 32</span> AVFrame* frame; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的已解码帧,用于回传解码后的图像</span>
<span style="color: rgba(0, 128, 128, 1)"> 33</span>
<span style="color: rgba(0, 128, 128, 1)"> 34</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">volatile</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> _released = <span style="color: rgba(0, 0, 255, 1)">false</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 资源释放标识,与锁配合使用避免重复释放资源(由于底层是c/c++,多线程下double free会导致程序崩溃)</span>
<span style="color: rgba(0, 128, 128, 1)"> 35</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">object</span> _codecLocker = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">object</span>(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 锁,用于多线程下的互斥</span>
<span style="color: rgba(0, 128, 128, 1)"> 36</span>
<span style="color: rgba(0, 128, 128, 1)"> 37</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> FFPlayer()
</span><span style="color: rgba(0, 128, 128, 1)"> 38</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 39</span> avcodec_register_all(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 静态块中注册ffmpeg解码器</span>
<span style="color: rgba(0, 128, 128, 1)"> 40</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 41</span>
<span style="color: rgba(0, 128, 128, 1)"> 42</span> <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> FFPlayer()
</span><span style="color: rgba(0, 128, 128, 1)"> 43</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 44</span> <span style="color: rgba(0, 0, 0, 1)"> InitializeComponent();
</span><span style="color: rgba(0, 128, 128, 1)"> 45</span>
<span style="color: rgba(0, 128, 128, 1)"> 46</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过程中,下列对象只需初始化一次</span>
<span style="color: rgba(0, 128, 128, 1)"> 47</span> frame =<span style="color: rgba(0, 0, 0, 1)"> av_frame_alloc();
</span><span style="color: rgba(0, 128, 128, 1)"> 48</span> avpkt =<span style="color: rgba(0, 0, 0, 1)"> av_packet_alloc();
</span><span style="color: rgba(0, 128, 128, 1)"> 49</span> <span style="color: rgba(0, 0, 0, 1)"> av_init_packet(avpkt);
</span><span style="color: rgba(0, 128, 128, 1)"> 50</span> nalData = Marshal.AllocHGlobal(<span style="color: rgba(128, 0, 128, 1)">1024</span> * <span style="color: rgba(128, 0, 128, 1)">1024</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 51</span> codec =<span style="color: rgba(0, 0, 0, 1)"> avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
</span><span style="color: rgba(0, 128, 128, 1)"> 52</span> avpkt->data = (<span style="color: rgba(0, 0, 255, 1)">void</span>*<span style="color: rgba(0, 0, 0, 1)">)nalData;
</span><span style="color: rgba(0, 128, 128, 1)"> 53</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 54</span>
<span style="color: rgba(0, 128, 128, 1)"> 55</span> ~<span style="color: rgba(0, 0, 0, 1)">FFPlayer()
</span><span style="color: rgba(0, 128, 128, 1)"> 56</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 57</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过程中,下列对象只需释放一次</span>
<span style="color: rgba(0, 128, 128, 1)"> 58</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> frame)
</span><span style="color: rgba(0, 128, 128, 1)"> 59</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVFrame** LPframe = &<span style="color: rgba(0, 0, 0, 1)">frame)
</span><span style="color: rgba(0, 128, 128, 1)"> 60</span> <span style="color: rgba(0, 0, 0, 1)"> av_frame_free(LPframe);
</span><span style="color: rgba(0, 128, 128, 1)"> 61</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> avpkt)
</span><span style="color: rgba(0, 128, 128, 1)"> 62</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVPacket** LPpkt = &<span style="color: rgba(0, 0, 0, 1)">avpkt)
</span><span style="color: rgba(0, 128, 128, 1)"> 63</span> <span style="color: rgba(0, 0, 0, 1)"> av_packet_free(LPpkt);
</span><span style="color: rgba(0, 128, 128, 1)"> 64</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">default</span> !=<span style="color: rgba(0, 0, 0, 1)"> nalData)
</span><span style="color: rgba(0, 128, 128, 1)"> 65</span> <span style="color: rgba(0, 0, 0, 1)"> Marshal.FreeHGlobal(nalData);
</span><span style="color: rgba(0, 128, 128, 1)"> 66</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 67</span>
<span style="color: rgba(0, 128, 128, 1)"> 68</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 释放资源
</span><span style="color: rgba(0, 128, 128, 1)"> 69</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 此函数并非表示“终止”,更多的是表示“改变”和“重置”,实际上对此函数的调用更多的是发生在界面大小发生变化时和网络掉包导致硬解异常时</span>
<span style="color: rgba(0, 128, 128, 1)"> 70</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Releases()
</span><span style="color: rgba(0, 128, 128, 1)"> 71</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 72</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过程中,下列对象会重复创建和销毁多次</span>
<span style="color: rgba(0, 128, 128, 1)"> 73</span> <span style="color: rgba(0, 0, 255, 1)">lock</span><span style="color: rgba(0, 0, 0, 1)"> (_codecLocker)
</span><span style="color: rgba(0, 128, 128, 1)"> 74</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 75</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (_released) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 76</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> ctx)
</span><span style="color: rgba(0, 128, 128, 1)"> 77</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVCodecContext** LPctx = &<span style="color: rgba(0, 0, 0, 1)">ctx)
</span><span style="color: rgba(0, 128, 128, 1)"> 78</span> <span style="color: rgba(0, 0, 0, 1)"> avcodec_free_context(LPctx);
</span><span style="color: rgba(0, 128, 128, 1)"> 79</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> hw_ctx)
</span><span style="color: rgba(0, 128, 128, 1)"> 80</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVBufferRef** LPhw_ctx = &<span style="color: rgba(0, 0, 0, 1)">hw_ctx)
</span><span style="color: rgba(0, 128, 128, 1)"> 81</span> <span style="color: rgba(0, 0, 0, 1)"> av_buffer_unref(LPhw_ctx);
</span><span style="color: rgba(0, 128, 128, 1)"> 82</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (PS:device和surface我们将其置为null,让GC帮我们调用Finalize,它则会自行释放资源)</span>
<span style="color: rgba(0, 128, 128, 1)"> 83</span> surface = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 84</span> device = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 85</span> lastFmt =<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_NONE;
</span><span style="color: rgba(0, 128, 128, 1)"> 86</span> _released = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 87</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 88</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 89</span>
<span style="color: rgba(0, 128, 128, 1)"> 90</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Load事件中保存控件句柄</span>
<span style="color: rgba(0, 128, 128, 1)"> 91</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> FFPlayer_Load(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, EventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)"> 92</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 93</span> contentPanelHandle = Handle; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这个句柄也可以是你控件内真正要渲染画面的句柄</span>
<span style="color: rgba(0, 128, 128, 1)"> 94</span> lastCBounds = ClientRectangle; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 同理,区域也不一定是自身显示区域</span>
<span style="color: rgba(0, 128, 128, 1)"> 95</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 96</span>
<span style="color: rgba(0, 128, 128, 1)"> 97</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 解码函数,由外部调用,送一一个分片好的nal</span>
<span style="color: rgba(0, 128, 128, 1)"> 98</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> H264Received(<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">[] nal)
</span><span style="color: rgba(0, 128, 128, 1)"> 99</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">100</span> <span style="color: rgba(0, 0, 255, 1)">lock</span><span style="color: rgba(0, 0, 0, 1)"> (_codecLocker)
</span><span style="color: rgba(0, 128, 128, 1)">101</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">102</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断界面大小更改了,先重置一波
</span><span style="color: rgba(0, 128, 128, 1)">103</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (因为DirectX中界面大小改变是一件大事,没得法绕过,只能推倒从来)
</span><span style="color: rgba(0, 128, 128, 1)">104</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果你的显示控件不是当前控件本身,此处需要做修改</span>
<span style="color: rgba(0, 128, 128, 1)">105</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">ClientRectangle.Equals(lastCBounds))
</span><span style="color: rgba(0, 128, 128, 1)">106</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">107</span> lastCBounds =<span style="color: rgba(0, 0, 0, 1)"> ClientRectangle;
</span><span style="color: rgba(0, 128, 128, 1)">108</span> <span style="color: rgba(0, 0, 0, 1)"> Releases();
</span><span style="color: rgba(0, 128, 128, 1)">109</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">110</span>
<span style="color: rgba(0, 128, 128, 1)">111</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> ==<span style="color: rgba(0, 0, 0, 1)"> ctx)
</span><span style="color: rgba(0, 128, 128, 1)">112</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">113</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 第一次接收到待解码数据时初始化一个解码器上下文</span>
<span style="color: rgba(0, 128, 128, 1)">114</span> ctx =<span style="color: rgba(0, 0, 0, 1)"> avcodec_alloc_context3(codec);
</span><span style="color: rgba(0, 128, 128, 1)">115</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> ==<span style="color: rgba(0, 0, 0, 1)"> ctx)
</span><span style="color: rgba(0, 128, 128, 1)">116</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">117</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">118</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">119</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过参数传递控件句柄给硬件加速上下文</span>
<span style="color: rgba(0, 128, 128, 1)">120</span> AVDictionary*<span style="color: rgba(0, 0, 0, 1)"> dic;
</span><span style="color: rgba(0, 128, 128, 1)">121</span> av_dict_set_int(&dic, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hWnd</span><span style="color: rgba(128, 0, 0, 1)">"</span>, contentPanelHandle.ToInt64(), <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">122</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVBufferRef** LPhw_ctx = &<span style="color: rgba(0, 0, 0, 1)">hw_ctx)
</span><span style="color: rgba(0, 128, 128, 1)">123</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">124</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (av_hwdevice_ctx_create(LPhw_ctx, AVHWDeviceType.AV_HWDEVICE_TYPE_DXVA2,
</span><span style="color: rgba(0, 128, 128, 1)">125</span> <span style="color: rgba(0, 0, 255, 1)">null</span>, dic, <span style="color: rgba(128, 0, 128, 1)">0</span>) >= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">126</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">127</span> ctx->hw_frames_ctx =<span style="color: rgba(0, 0, 0, 1)"> av_buffer_ref(hw_ctx);
</span><span style="color: rgba(0, 128, 128, 1)">128</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">129</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">130</span> av_dict_free(&<span style="color: rgba(0, 0, 0, 1)">dic);
</span><span style="color: rgba(0, 128, 128, 1)">131</span> ctx->hw_frames_ctx =<span style="color: rgba(0, 0, 0, 1)"> av_buffer_ref(hw_ctx);
</span><span style="color: rgba(0, 128, 128, 1)">132</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (avcodec_open2(ctx, codec, <span style="color: rgba(0, 0, 255, 1)">null</span>) < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">133</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">134</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVCodecContext** LPctx = &<span style="color: rgba(0, 0, 0, 1)">ctx)
</span><span style="color: rgba(0, 128, 128, 1)">135</span> <span style="color: rgba(0, 0, 0, 1)"> avcodec_free_context(LPctx);
</span><span style="color: rgba(0, 128, 128, 1)">136</span> <span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVBufferRef** LPhw_ctx = &<span style="color: rgba(0, 0, 0, 1)">hw_ctx)
</span><span style="color: rgba(0, 128, 128, 1)">137</span> <span style="color: rgba(0, 0, 0, 1)"> av_buffer_unref(LPhw_ctx);
</span><span style="color: rgba(0, 128, 128, 1)">138</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">139</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">140</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">141</span> _released = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">142</span>
<span style="color: rgba(0, 128, 128, 1)">143</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开始解码</span>
<span style="color: rgba(0, 128, 128, 1)">144</span> Marshal.Copy(nal, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, nalData, nal.Length);
</span><span style="color: rgba(0, 128, 128, 1)">145</span> avpkt->size =<span style="color: rgba(0, 0, 0, 1)"> nal.Length;
</span><span style="color: rgba(0, 128, 128, 1)">146</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (avcodec_send_packet(ctx, avpkt) < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">147</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">148</span> Releases(); <span style="color: rgba(0, 0, 255, 1)">return</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果程序走到了这里,一般是因为网络掉包导致nal数据不连续,没办法, 推倒从来</span>
<span style="color: rgba(0, 128, 128, 1)">149</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">150</span> <span style="color: rgba(0, 0, 0, 1)"> receive_frame:
</span><span style="color: rgba(0, 128, 128, 1)">151</span> <span style="color: rgba(0, 0, 255, 1)">int</span> err =<span style="color: rgba(0, 0, 0, 1)"> avcodec_receive_frame(ctx, frame);
</span><span style="color: rgba(0, 128, 128, 1)">152</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (err == -<span style="color: rgba(128, 0, 128, 1)">11</span>) <span style="color: rgba(0, 0, 255, 1)">return</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> EAGAIN</span>
<span style="color: rgba(0, 128, 128, 1)">153</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (err < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">154</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">155</span> Releases(); <span style="color: rgba(0, 0, 255, 1)">return</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 同上,一般这里很少出错,但一旦发生,只能推倒从来</span>
<span style="color: rgba(0, 128, 128, 1)">156</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">157</span>
<span style="color: rgba(0, 128, 128, 1)">158</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 尝试播放一帧画面</span>
<span style="color: rgba(0, 128, 128, 1)">159</span> AVFrame s_frame = *<span style="color: rgba(0, 0, 0, 1)">frame;
</span><span style="color: rgba(0, 128, 128, 1)">160</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里由于我无论如何都要加速,而一般显卡最兼容的是yv12格式,因此我只对dxva2和420p做了处理,如果你的h264解出来不是这些,我建议转成rgb(那你就需要编译和使用swscale模块了)</span>
<span style="color: rgba(0, 128, 128, 1)">161</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (s_frame.format != AVPixelFormat.AV_PIX_FMT_DXVA2_VLD && s_frame.format != AVPixelFormat.AV_PIX_FMT_YUV420P && s_frame.format != AVPixelFormat.AV_PIX_FMT_YUVJ420P) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">162</span> <span style="color: rgba(0, 0, 255, 1)">try</span>
<span style="color: rgba(0, 128, 128, 1)">163</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">164</span> <span style="color: rgba(0, 0, 255, 1)">int</span> width =<span style="color: rgba(0, 0, 0, 1)"> s_frame.width;
</span><span style="color: rgba(0, 128, 128, 1)">165</span> <span style="color: rgba(0, 0, 255, 1)">int</span> height =<span style="color: rgba(0, 0, 0, 1)"> s_frame.height;
</span><span style="color: rgba(0, 128, 128, 1)">166</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (lastIWidth != width || lastIHeight != height || lastFmt != s_frame.format) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这个if判定的是第一次尝试渲染,因为一般码流的宽高和格式不会变</span>
<span style="color: rgba(0, 128, 128, 1)">167</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">168</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (s_frame.format !=<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
</span><span style="color: rgba(0, 128, 128, 1)">169</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">170</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 假如硬解不成功(例如h264是baseline的,ffmpeg新版不支持baseline的dxva2硬解)
</span><span style="color: rgba(0, 128, 128, 1)">171</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 我们就尝试用directx渲染yuv,至少省去yuv转rgb,可以略微节省一丢丢cpu</span>
<span style="color: rgba(0, 128, 128, 1)">172</span> PresentParameters pp = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PresentParameters();
</span><span style="color: rgba(0, 128, 128, 1)">173</span> pp.Windowed = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">174</span> pp.SwapEffect =<span style="color: rgba(0, 0, 0, 1)"> SwapEffect.Discard;
</span><span style="color: rgba(0, 128, 128, 1)">175</span> pp.BackBufferCount = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">176</span> pp.DeviceWindowHandle =<span style="color: rgba(0, 0, 0, 1)"> contentPanelHandle;
</span><span style="color: rgba(0, 128, 128, 1)">177</span> pp.BackBufferFormat =<span style="color: rgba(0, 0, 0, 1)"> Manager.Adapters.Default.CurrentDisplayMode.Format;
</span><span style="color: rgba(0, 128, 128, 1)">178</span> pp.EnableAutoDepthStencil = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">179</span> pp.PresentFlag =<span style="color: rgba(0, 0, 0, 1)"> PresentFlag.Video;
</span><span style="color: rgba(0, 128, 128, 1)">180</span> pp.FullScreenRefreshRateInHz = <span style="color: rgba(128, 0, 128, 1)">0</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">D3DPRESENT_RATE_DEFAULT</span>
<span style="color: rgba(0, 128, 128, 1)">181</span> pp.PresentationInterval = <span style="color: rgba(128, 0, 128, 1)">0</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">D3DPRESENT_INTERVAL_DEFAULT</span>
<span style="color: rgba(0, 128, 128, 1)">182</span> Caps caps =<span style="color: rgba(0, 0, 0, 1)"> Manager.GetDeviceCaps(Manager.Adapters.Default.Adapter, DeviceType.Hardware);
</span><span style="color: rgba(0, 128, 128, 1)">183</span> CreateFlags behaviorFlas = CreateFlags.MultiThreaded |<span style="color: rgba(0, 0, 0, 1)"> CreateFlags.FpuPreserve;
</span><span style="color: rgba(0, 128, 128, 1)">184</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (caps.DeviceCaps.SupportsHardwareTransformAndLight)
</span><span style="color: rgba(0, 128, 128, 1)">185</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">186</span> behaviorFlas |=<span style="color: rgba(0, 0, 0, 1)"> CreateFlags.HardwareVertexProcessing;
</span><span style="color: rgba(0, 128, 128, 1)">187</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">188</span> <span style="color: rgba(0, 0, 255, 1)">else</span>
<span style="color: rgba(0, 128, 128, 1)">189</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">190</span> behaviorFlas |=<span style="color: rgba(0, 0, 0, 1)"> CreateFlags.SoftwareVertexProcessing;
</span><span style="color: rgba(0, 128, 128, 1)">191</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">192</span> device = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Device(Manager.Adapters.Default.Adapter, DeviceType.Hardware, contentPanelHandle, behaviorFlas, pp);
</span><span style="color: rgba(0, 128, 128, 1)">193</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">(Format)842094158;</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">nv12</span>
<span style="color: rgba(0, 128, 128, 1)">194</span> surface = device.CreateOffscreenPlainSurface(width, height, (Format)<span style="color: rgba(128, 0, 128, 1)">842094169</span>, Pool.Default);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">yv12,显卡兼容性最好的格式</span>
<span style="color: rgba(0, 128, 128, 1)">195</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">196</span> lastIWidth =<span style="color: rgba(0, 0, 0, 1)"> width;
</span><span style="color: rgba(0, 128, 128, 1)">197</span> lastIHeight =<span style="color: rgba(0, 0, 0, 1)"> height;
</span><span style="color: rgba(0, 128, 128, 1)">198</span> lastVRect = <span style="color: rgba(0, 0, 255, 1)">new</span> Rectangle(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, lastIWidth, lastIHeight);
</span><span style="color: rgba(0, 128, 128, 1)">199</span> lastFmt =<span style="color: rgba(0, 0, 0, 1)"> s_frame.format;
</span><span style="color: rgba(0, 128, 128, 1)">200</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">201</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (lastFmt !=<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
</span><span style="color: rgba(0, 128, 128, 1)">202</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">203</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果硬解失败,我们还需要把yuv拷贝到surface
</span><span style="color: rgba(0, 128, 128, 1)">204</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ffmpeg没有yv12,只有i420,而一般显卡又支持的是yv12,因此下文中uv分量是反向的</span>
<span style="color: rgba(0, 128, 128, 1)">205</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> stride;
</span><span style="color: rgba(0, 128, 128, 1)">206</span> <span style="color: rgba(0, 0, 255, 1)">var</span> gs = surface.LockRectangle(LockFlags.DoNotWait, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> stride);
</span><span style="color: rgba(0, 128, 128, 1)">207</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (gs == <span style="color: rgba(0, 0, 255, 1)">null</span>) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">208</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < lastIHeight; i++<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">209</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">210</span> memcpy(gs.InternalData + i * stride, s_frame.data1 + i *<span style="color: rgba(0, 0, 0, 1)"> s_frame.linesize1, lastIWidth);
</span><span style="color: rgba(0, 128, 128, 1)">211</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">212</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < lastIHeight / <span style="color: rgba(128, 0, 128, 1)">2</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">213</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">214</span> memcpy(gs.InternalData + stride * lastIHeight + i * stride / <span style="color: rgba(128, 0, 128, 1)">2</span>, s_frame.data3 + i * s_frame.linesize3, lastIWidth / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">215</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">216</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < lastIHeight / <span style="color: rgba(128, 0, 128, 1)">2</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">217</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">218</span> memcpy(gs.InternalData + stride * lastIHeight + stride * lastIHeight / <span style="color: rgba(128, 0, 128, 1)">4</span> + i * stride / <span style="color: rgba(128, 0, 128, 1)">2</span>, s_frame.data2 + i * s_frame.linesize2, lastIWidth / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">219</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">220</span> <span style="color: rgba(0, 0, 0, 1)"> surface.UnlockRectangle();
</span><span style="color: rgba(0, 128, 128, 1)">221</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">222</span>
<span style="color: rgba(0, 128, 128, 1)">223</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 下面的代码开始烧脑了,如果是dxva2硬解出来的图像数据,则图像数据本身就是一个surface,并且它就绑定了device
</span><span style="color: rgba(0, 128, 128, 1)">224</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 因此我们可以直接用它,如果是x264软解出来的yuv,则我们需要用上文创建的device和surface搞事情</span>
<span style="color: rgba(0, 128, 128, 1)">225</span> Surface _surface = lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD ? <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(s_frame.data4) : surface;
</span><span style="color: rgba(0, 128, 128, 1)">226</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (lastFmt ==<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
</span><span style="color: rgba(0, 128, 128, 1)">227</span> GC.SuppressFinalize(_surface);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这一句代码是点睛之笔,如果不加,程序一会儿就崩溃了,熟悉GC和DX的童鞋估计一下就能看出门道;整篇代码,就这句折腾了我好几天,其他都好说</span>
<span style="color: rgba(0, 128, 128, 1)">228</span> Device _device = lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD ?<span style="color: rgba(0, 0, 0, 1)"> _surface.Device : device;
</span><span style="color: rgba(0, 128, 128, 1)">229</span> _device.Clear(ClearFlags.Target, Color.Black, <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">230</span> <span style="color: rgba(0, 0, 0, 1)"> _device.BeginScene();
</span><span style="color: rgba(0, 128, 128, 1)">231</span> Surface backBuffer = _device.GetBackBuffer(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, BackBufferType.Mono);
</span><span style="color: rgba(0, 128, 128, 1)">232</span> <span style="color: rgba(0, 0, 0, 1)"> _device.StretchRectangle(_surface, lastVRect, backBuffer, lastCBounds, TextureFilter.Linear);
</span><span style="color: rgba(0, 128, 128, 1)">233</span> <span style="color: rgba(0, 0, 0, 1)"> _device.EndScene();
</span><span style="color: rgba(0, 128, 128, 1)">234</span> <span style="color: rgba(0, 0, 0, 1)"> _device.Present();
</span><span style="color: rgba(0, 128, 128, 1)">235</span> <span style="color: rgba(0, 0, 0, 1)"> backBuffer.Dispose();
</span><span style="color: rgba(0, 128, 128, 1)">236</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">237</span> <span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (DirectXException ex)
</span><span style="color: rgba(0, 128, 128, 1)">238</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">239</span> StringBuilder msg = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuilder();
</span><span style="color: rgba(0, 128, 128, 1)">240</span> msg.Append(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*************************************** \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">241</span> msg.AppendFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 异常发生时间: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, DateTime.Now);
</span><span style="color: rgba(0, 128, 128, 1)">242</span> msg.AppendFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 导致当前异常的 Exception 实例: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.InnerException);
</span><span style="color: rgba(0, 128, 128, 1)">243</span> msg.AppendFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 导致异常的应用程序或对象的名称: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.Source);
</span><span style="color: rgba(0, 128, 128, 1)">244</span> msg.AppendFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 引发异常的方法: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.TargetSite);
</span><span style="color: rgba(0, 128, 128, 1)">245</span> msg.AppendFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 异常堆栈信息: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.StackTrace);
</span><span style="color: rgba(0, 128, 128, 1)">246</span> msg.AppendFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 异常消息: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.Message);
</span><span style="color: rgba(0, 128, 128, 1)">247</span> msg.Append(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">***************************************</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">248</span> <span style="color: rgba(0, 0, 0, 1)"> Console.WriteLine(msg);
</span><span style="color: rgba(0, 128, 128, 1)">249</span> <span style="color: rgba(0, 0, 0, 1)"> Releases();
</span><span style="color: rgba(0, 128, 128, 1)">250</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">251</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">252</span> <span style="color: rgba(0, 0, 255, 1)">goto</span> receive_frame; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 尝试解出第二幅画面(实际上不行,因为我们约定了单次传入nal是一个,当然,代码是可以改的)</span>
<span style="color: rgba(0, 128, 128, 1)">253</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">254</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">255</span>
<span style="color: rgba(0, 128, 128, 1)">256</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 外部调用停止解码以显示释放资源</span>
<span style="color: rgba(0, 128, 128, 1)">257</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Stop()
</span><span style="color: rgba(0, 128, 128, 1)">258</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">259</span> <span style="color: rgba(0, 0, 0, 1)"> Releases();
</span><span style="color: rgba(0, 128, 128, 1)">260</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">261</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">262</span> }</pre>
</div>
<span class="cnblogs_code_collapse">FFPlayer.cs</span></div>
<p> 下面讲解代码最主要的三个部分</p>
<ul>
<li>初始化ffmpeg</li>
</ul>
<p> 主要在静态块和构造函数中,过程中我没有将AVPacket和AVFrame局部化,很多网上的代码包括官方代码都是局部化这两个对象。我对此持保留意见(等我程序报错了再说)</p>
<ul>
<li>将收到的数据送入ffmpeg解码并将拿到的数据进行展示</li>
</ul>
<p> 这里值得一提的是get_format,官方有一个示例,下图</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123152844220-1814096341.png" alt="" loading="lazy"></p>
<p> 它有一个get_format过程(详见215行和63行),我没有采用。这里给大家解释一下原因:</p>
<p> 这个get_format的作用是ffmpeg给你提供了多个解码器让你来选一个,而且它内部有一个机制,如果你第一次选的解码器不生效(初始化错误等),它会调用get_format第二次(第三次。。。)让你再选一个,而我们首先认定了要用dxva2的硬件解码器,其次,如果dxva2初始化错误,ffmpeg内部会自动降级为内置264软解,因此我们无需多此一举。</p>
<ul>
<li>发现解码和播放过程中出现异常的解决办法</li>
<ul>
<li>不支持硬解</li>
</ul>
</ul>
<p> 代码中已经做出了一部分兼容,因为baseline的判定必须解出sps/pps才能知道,因此这个错误可能会延迟爆出(不过不用担心,如果此时报错,ffmpeg会自动降级为软解)</p>
<ul>
<li style="list-style-type: none"></li>
<ul>
<li>窗体大小改变</li>
</ul>
</ul>
<p> 基于DirectX中设备后台缓冲的宽高无法动态重设,我们只能在控件大小改变时推倒重来。如若不然,你绘制的画面会进行意向不到的缩放</p>
<ul>
<li style="list-style-type: none"></li>
<ul>
<li>网络掉包导致硬件解码器错误</li>
</ul>
</ul>
<p> 见代码</p>
<ul>
<li style="list-style-type: none"></li>
<ul>
<li>其他directx底层异常</li>
</ul>
</ul>
<p> 代码中我加了一个try-catch,捕获的异常类型是DirectXException,在c/c++中,我们一般是调用完函数后会得到一个HRESULT,并通过FAILED宏判定他,而这个步骤在c#自动帮我们做了,取而代之的是一个throw DirectXException过程,我们通过try-catch进行可能的异常处理(实际上还是推倒重来)</p>
<p> </p>
<p> 番外篇:C#对DiretX调用的封装</p>
<p> 上文中我们使用DirectX的方式看起来即非COM组件,又非C-DLL的P/Invoke,难道DirectX真有托管代码?</p>
<p> 答案是否定的,C#的dll当然也是调用系统的d3d9.dll。不过我们有必要一探究竟,因为这里面有一个隐藏副本</p>
<p> 首先请大家准备好ildasm和visual studio,我们打开visual studio,创建一个c++工程(类型随意),然后新建一个cpp文件,然后填入下面的代码</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123160207570-1836617287.png" alt="" loading="lazy"></p>
<p> 如果你能执行,你会发现输出是136(0x88);然后我们使用ildasm找到StrechRectangle的代码</p>
<p> <img src="https://img2018.cnblogs.com/blog/372875/201911/372875-20191123160609044-1538394186.png" alt="" loading="lazy"></p>
<p> 你会发现也有一个+0x88的过程,那么其实道理就很容易懂了,c#通过calli(CLR指令)可以执行内存call,而得益于微软com组件的函数表偏移量约定,我们可以通过头文件知道函数对于对象指针的偏移(其实就是一个简单的ThisCall)。具体细节大家查阅d3d9.h和calli的网络文章即可。</p>
<p> </p>
<p>At 2020-12-2 20:11</p>
<p> 当然,你也可以用sharpdx替换旧的官方库</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_6aff6887-d0cb-4a89-9dc3-cfba191715cc" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_6aff6887-d0cb-4a89-9dc3-cfba191715cc" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_6aff6887-d0cb-4a89-9dc3-cfba191715cc" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> SharpDX;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> SharpDX.Direct3D9;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Drawing;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Runtime.InteropServices;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Windows.Forms;
</span><span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> WindowsFormsApp1.FFHelper;
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> WindowsFormsApp1
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">unsafe</span> <span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> FFH264Player : UserControl
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">void</span> memcpy(IntPtr dest, IntPtr src, <span style="color: rgba(0, 0, 255, 1)">int</span> count);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用于在解码器和directx间拷贝内存的c函数</span>
<span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> Direct3D d3d;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> IntPtr contentPanelHandle; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 画面渲染的控件句柄,因为画面渲染时可能出于非UI线程,因此先保存句柄避免CLR报错</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span> lastIWidth, lastIHeight; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 上次控件大小,用于在控件大小改变时做出判定重新初始化渲染上下文</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> System.Drawing.Rectangle lastCBounds; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 临时变量,存储上次控件区域(屏幕坐标)</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> System.Drawing.Rectangle lastVRect; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 临时变量,存储上次解码出的图像大小</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> Device device; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当使用软解时,这个变量生效,它是IDirect3Device9*对象,用于绘制YUV</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> Surface surface; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当使用软解时,这个变量生效,它是IDirect3Surface9*对象,用于接受解码后的YUV数据</span>
AVPixelFormat lastFmt; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 上次解码出的图像数据类型,这个理论上不会变</span>
<span style="color: rgba(0, 0, 0, 1)">
AVCodec</span>* codec; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的解码器</span>
AVCodecContext* ctx; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的解码上下文</span>
AVBufferRef* hw_ctx; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的解码器硬件加速上下文,作为ctx的扩展存在</span>
AVPacket* avpkt; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的数据包,用于封送待解码数据</span>
IntPtr nalData; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一块预分配内存,作为avpkt中真正存储数据的内存地址</span>
AVFrame* frame; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ffmpeg的已解码帧,用于回传解码后的图像</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">volatile</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> _released = <span style="color: rgba(0, 0, 255, 1)">false</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 资源释放标识,与锁配合使用避免重复释放资源(由于底层是c/c++,多线程下double free会导致程序崩溃)</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">object</span> _codecLocker = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">object</span>(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 锁,用于多线程下的互斥</span>
<span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> FFH264Player()
{
avcodec_register_all(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 静态块中注册ffmpeg解码器</span>
d3d = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Direct3D();
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> FFH264Player()
{
InitializeComponent();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过程中,下列对象只需初始化一次</span>
frame =<span style="color: rgba(0, 0, 0, 1)"> av_frame_alloc();
avpkt </span>=<span style="color: rgba(0, 0, 0, 1)"> av_packet_alloc();
av_init_packet(avpkt);
nalData </span>= Marshal.AllocHGlobal(<span style="color: rgba(128, 0, 128, 1)">1024</span> * <span style="color: rgba(128, 0, 128, 1)">1024</span><span style="color: rgba(0, 0, 0, 1)">);
codec </span>=<span style="color: rgba(0, 0, 0, 1)"> avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
avpkt</span>->data = (<span style="color: rgba(0, 0, 255, 1)">void</span>*<span style="color: rgba(0, 0, 0, 1)">)nalData;
}
</span>~<span style="color: rgba(0, 0, 0, 1)">FFH264Player()
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过程中,下列对象只需释放一次</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> frame)
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVFrame** LPframe = &<span style="color: rgba(0, 0, 0, 1)">frame)
av_frame_free(LPframe);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> avpkt)
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVPacket** LPpkt = &<span style="color: rgba(0, 0, 0, 1)">avpkt)
av_packet_free(LPpkt);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">default</span> !=<span style="color: rgba(0, 0, 0, 1)"> nalData)
Marshal.FreeHGlobal(nalData);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 释放资源
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 此函数并非表示“终止”,更多的是表示“改变”和“重置”,实际上对此函数的调用更多的是发生在界面大小发生变化时和网络掉包导致硬解异常时</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Releases()
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过程中,下列对象会重复创建和销毁多次</span>
<span style="color: rgba(0, 0, 255, 1)">lock</span><span style="color: rgba(0, 0, 0, 1)"> (_codecLocker)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (_released) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> ctx)
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVCodecContext** LPctx = &<span style="color: rgba(0, 0, 0, 1)">ctx)
avcodec_free_context(LPctx);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> hw_ctx)
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVBufferRef** LPhw_ctx = &<span style="color: rgba(0, 0, 0, 1)">hw_ctx)
av_buffer_unref(LPhw_ctx);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (PS:device和surface我们将其置为null,让GC帮我们调用Finalize,它则会自行释放资源)</span>
surface = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
device </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
lastFmt </span>=<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_NONE;
_released </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Load事件中保存控件句柄</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> FFPlayer_Load(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, EventArgs e)
{
contentPanelHandle </span>= Handle; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这个句柄也可以是你控件内真正要渲染画面的句柄</span>
lastCBounds = ClientRectangle; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 同理,区域也不一定是自身显示区域</span>
<span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 解码函数,由外部调用,送一一个分片好的nal</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> H264Received(<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">[] nal)
{
</span><span style="color: rgba(0, 0, 255, 1)">lock</span><span style="color: rgba(0, 0, 0, 1)"> (_codecLocker)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断界面大小更改了,先重置一波
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (因为DirectX中界面大小改变是一件大事,没得法绕过,只能推倒从来)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果你的显示控件不是当前控件本身,此处需要做修改</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">ClientRectangle.Equals(lastCBounds))
{
lastCBounds </span>=<span style="color: rgba(0, 0, 0, 1)"> ClientRectangle;
Releases();
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> ==<span style="color: rgba(0, 0, 0, 1)"> ctx)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 第一次接收到待解码数据时初始化一个解码器上下文</span>
ctx =<span style="color: rgba(0, 0, 0, 1)"> avcodec_alloc_context3(codec);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> ==<span style="color: rgba(0, 0, 0, 1)"> ctx)
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过参数传递控件句柄给硬件加速上下文</span>
AVDictionary*<span style="color: rgba(0, 0, 0, 1)"> dic;
av_dict_set_int(</span>&dic, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hWnd</span><span style="color: rgba(128, 0, 0, 1)">"</span>, contentPanelHandle.ToInt64(), <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVBufferRef** LPhw_ctx = &<span style="color: rgba(0, 0, 0, 1)">hw_ctx)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (av_hwdevice_ctx_create(LPhw_ctx, AVHWDeviceType.AV_HWDEVICE_TYPE_DXVA2,
</span><span style="color: rgba(0, 0, 255, 1)">null</span>, dic, <span style="color: rgba(128, 0, 128, 1)">0</span>) >= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
ctx</span>->hw_device_ctx =<span style="color: rgba(0, 0, 0, 1)"> av_buffer_ref(hw_ctx);
}
}
av_dict_free(</span>&<span style="color: rgba(0, 0, 0, 1)">dic);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (avcodec_open2(ctx, codec, <span style="color: rgba(0, 0, 255, 1)">null</span>) < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVCodecContext** LPctx = &<span style="color: rgba(0, 0, 0, 1)">ctx)
avcodec_free_context(LPctx);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> hw_ctx)
</span><span style="color: rgba(0, 0, 255, 1)">fixed</span> (AVBufferRef** LPhw_ctx = &<span style="color: rgba(0, 0, 0, 1)">hw_ctx)
av_buffer_unref(LPhw_ctx);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
_released </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开始解码</span>
Marshal.Copy(nal, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, nalData, nal.Length);
avpkt</span>->size =<span style="color: rgba(0, 0, 0, 1)"> nal.Length;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (avcodec_send_packet(ctx, avpkt) < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
Releases(); </span><span style="color: rgba(0, 0, 255, 1)">return</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果程序走到了这里,一般是因为网络掉包导致nal数据不连续,没办法, 推倒从来</span>
<span style="color: rgba(0, 0, 0, 1)"> }
receive_frame:
</span><span style="color: rgba(0, 0, 255, 1)">int</span> err =<span style="color: rgba(0, 0, 0, 1)"> avcodec_receive_frame(ctx, frame);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err == -<span style="color: rgba(128, 0, 128, 1)">11</span>) <span style="color: rgba(0, 0, 255, 1)">return</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> EAGAIN</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (err < <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
Releases(); </span><span style="color: rgba(0, 0, 255, 1)">return</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 同上,一般这里很少出错,但一旦发生,只能推倒从来</span>
<span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 尝试播放一帧画面</span>
AVFrame s_frame = *<span style="color: rgba(0, 0, 0, 1)">frame;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里由于我无论如何都要加速,而一般显卡最兼容的是yv12格式,因此我只对dxva2和420p做了处理,如果你的h264解出来不是这些,我建议转成rgb(那你就需要编译和使用swscale模块了)</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (s_frame.format != AVPixelFormat.AV_PIX_FMT_DXVA2_VLD && s_frame.format != AVPixelFormat.AV_PIX_FMT_YUV420P && s_frame.format != AVPixelFormat.AV_PIX_FMT_YUVJ420P) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(0, 0, 255, 1)">int</span> width =<span style="color: rgba(0, 0, 0, 1)"> s_frame.width;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> height =<span style="color: rgba(0, 0, 0, 1)"> s_frame.height;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (lastIWidth != width || lastIHeight != height || lastFmt != s_frame.format) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这个if判定的是第一次尝试渲染,因为一般码流的宽高和格式不会变</span>
<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (s_frame.format !=<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 假如硬解不成功(例如h264是baseline的,ffmpeg新版不支持baseline的dxva2硬解)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 我们就尝试用directx渲染yuv,至少省去yuv转rgb,可以略微节省一丢丢cpu</span>
PresentParameters pp = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PresentParameters();
pp.Windowed </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
pp.SwapEffect </span>=<span style="color: rgba(0, 0, 0, 1)"> SwapEffect.Discard;
pp.BackBufferCount </span>= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
pp.DeviceWindowHandle </span>=<span style="color: rgba(0, 0, 0, 1)"> contentPanelHandle;
pp.BackBufferFormat </span>= d3d.Adapters[<span style="color: rgba(128, 0, 128, 1)">0</span>].CurrentDisplayMode.Format;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Manager.Adapters.Default.CurrentDisplayMode.Format;</span>
pp.EnableAutoDepthStencil = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
pp.PresentFlags </span>=<span style="color: rgba(0, 0, 0, 1)"> PresentFlags.Video;
pp.FullScreenRefreshRateInHz </span>= <span style="color: rgba(128, 0, 128, 1)">0</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">D3DPRESENT_RATE_DEFAULT</span>
pp.PresentationInterval = <span style="color: rgba(128, 0, 128, 1)">0</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">D3DPRESENT_INTERVAL_DEFAULT</span>
Capabilities caps = d3d.GetDeviceCaps(d3d.Adapters[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">].Adapter, DeviceType.Hardware);
CreateFlags behaviorFlas </span>= CreateFlags.Multithreaded |<span style="color: rgba(0, 0, 0, 1)"> CreateFlags.FpuPreserve;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ((caps.DeviceCaps & DeviceCaps.HWTransformAndLight) != <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
behaviorFlas </span>|=<span style="color: rgba(0, 0, 0, 1)"> CreateFlags.HardwareVertexProcessing;
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
behaviorFlas </span>|=<span style="color: rgba(0, 0, 0, 1)"> CreateFlags.SoftwareVertexProcessing;
}
device </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Device(d3d, d3d.Adapters[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">].Adapter, DeviceType.Hardware, contentPanelHandle, behaviorFlas, pp);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">(Format)842094158;</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">nv12</span>
surface = Surface.CreateOffscreenPlain(device, width, height, (Format)<span style="color: rgba(128, 0, 128, 1)">842094169</span>, Pool.Default);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">yv12,显卡兼容性最好的格式</span>
<span style="color: rgba(0, 0, 0, 1)"> }
lastIWidth </span>=<span style="color: rgba(0, 0, 0, 1)"> width;
lastIHeight </span>=<span style="color: rgba(0, 0, 0, 1)"> height;
lastVRect </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> System.Drawing.Rectangle(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, lastIWidth, lastIHeight);
lastFmt </span>=<span style="color: rgba(0, 0, 0, 1)"> s_frame.format;
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (lastFmt !=<span style="color: rgba(0, 0, 0, 1)"> AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果硬解失败,我们还需要把yuv拷贝到surface
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ffmpeg没有yv12,只有i420,而一般显卡又支持的是yv12,因此下文中uv分量是反向的</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> gs =<span style="color: rgba(0, 0, 0, 1)"> surface.LockRectangle(LockFlags.DoNotWait);
</span><span style="color: rgba(0, 0, 255, 1)">int</span> stride =<span style="color: rgba(0, 0, 0, 1)"> gs.Pitch;
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < lastIHeight; i++<span style="color: rgba(0, 0, 0, 1)">)
{
memcpy(gs.DataPointer </span>+ i * stride, s_frame.data1 + i *<span style="color: rgba(0, 0, 0, 1)"> s_frame.linesize1, lastIWidth);
}
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < lastIHeight / <span style="color: rgba(128, 0, 128, 1)">2</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
{
memcpy(gs.DataPointer </span>+ stride * lastIHeight + i * stride / <span style="color: rgba(128, 0, 128, 1)">2</span>, s_frame.data3 + i * s_frame.linesize3, lastIWidth / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < lastIHeight / <span style="color: rgba(128, 0, 128, 1)">2</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
{
memcpy(gs.DataPointer </span>+ stride * lastIHeight + stride * lastIHeight / <span style="color: rgba(128, 0, 128, 1)">4</span> + i * stride / <span style="color: rgba(128, 0, 128, 1)">2</span>, s_frame.data2 + i * s_frame.linesize2, lastIWidth / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
}
surface.UnlockRectangle();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 下面的代码开始烧脑了,如果是dxva2硬解出来的图像数据,则图像数据本身就是一个surface
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 因此我们可以直接用它,如果是x264软解出来的yuv,则我们需要用上文创建的device和surface搞事情</span>
Surface _surface = lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD ? <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(s_frame.data4) : surface;
Device _device </span>= lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD ?<span style="color: rgba(0, 0, 0, 1)"> _surface.Device : device;
_device.Clear(ClearFlags.Target, SharpDX.Color.Black, </span><span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
_device.BeginScene();
Surface backBuffer </span>= _device.GetBackBuffer(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
Size dst </span>=<span style="color: rgba(0, 0, 0, 1)"> lastCBounds.Size;
GetScale(lastVRect.Size, </span><span style="color: rgba(0, 0, 255, 1)">ref</span><span style="color: rgba(0, 0, 0, 1)"> dst);
System.Drawing.Rectangle dstRect </span>=<span style="color: rgba(0, 0, 0, 1)"> lastCBounds;
dstRect.X </span>+= (lastCBounds.Width - dst.Width) / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
dstRect.Y </span>+= (lastCBounds.Height - dst.Height) / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
dstRect.Size </span>=<span style="color: rgba(0, 0, 0, 1)"> dst;
_device.StretchRectangle(_surface,
</span><span style="color: rgba(0, 0, 255, 1)">new</span> SharpDX.RectangleF(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, lastVRect.Width, lastVRect.Height),
backBuffer,
</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SharpDX.RectangleF(dstRect.X, dstRect.Y, dstRect.Width, dstRect.Height),
TextureFilter.Linear);
_device.EndScene();
_device.Present();
backBuffer.Dispose();
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SharpDXException ex)
{
StringBuilder msg </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuilder();
msg.Append(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*************************************** \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
msg.AppendFormat(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 异常发生时间: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, DateTime.Now);
msg.AppendFormat(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 导致当前异常的 Exception 实例: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.InnerException);
msg.AppendFormat(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 导致异常的应用程序或对象的名称: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.Source);
msg.AppendFormat(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 引发异常的方法: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.TargetSite);
msg.AppendFormat(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 异常堆栈信息: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.StackTrace);
msg.AppendFormat(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> 异常消息: {0} \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ex.Message);
msg.Append(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">***************************************</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
Console.WriteLine(msg);
Releases();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">goto</span> receive_frame; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 尝试解出第二幅画面(实际上不行,因为我们约定了单次传入nal是一个,当然,代码是可以改的)</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> GetScale(Size src, <span style="color: rgba(0, 0, 255, 1)">ref</span><span style="color: rgba(0, 0, 0, 1)"> Size dst)
{
</span><span style="color: rgba(0, 0, 255, 1)">int</span> width = <span style="color: rgba(128, 0, 128, 1)">0</span>, height = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">按比例缩放</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> sourWidth =<span style="color: rgba(0, 0, 0, 1)"> src.Width;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> sourHeight =<span style="color: rgba(0, 0, 0, 1)"> src.Height;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (sourHeight > dst.Height || sourWidth ><span style="color: rgba(0, 0, 0, 1)"> dst.Width)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ((sourWidth * dst.Height) > (sourHeight *<span style="color: rgba(0, 0, 0, 1)"> dst.Width))
{
width </span>=<span style="color: rgba(0, 0, 0, 1)"> dst.Width;
height </span>= dst.Width * sourHeight /<span style="color: rgba(0, 0, 0, 1)"> sourWidth;
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
height </span>=<span style="color: rgba(0, 0, 0, 1)"> dst.Height;
width </span>= sourWidth * dst.Height /<span style="color: rgba(0, 0, 0, 1)"> sourHeight;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
width </span>=<span style="color: rgba(0, 0, 0, 1)"> sourWidth;
height </span>=<span style="color: rgba(0, 0, 0, 1)"> sourHeight;
}
dst.Width </span>=<span style="color: rgba(0, 0, 0, 1)"> width;
dst.Height </span>=<span style="color: rgba(0, 0, 0, 1)"> height;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 外部调用停止解码以显示释放资源</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Stop()
{
Releases();
}
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">FFH264Player.cs</span></div>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
认真你就输了,一直认真你就赢了!<br><br>
来源:https://www.cnblogs.com/Johness/p/use-csharp-and-ffmpeg-todo-h264-decode-throw-dxva2.html
頁:
[1]