本文门槛较高,因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵

如果你跟随这篇文章实现了播放器,那你会得到一个高效率,低cpu占用(单路720p视频解码播放占用1%左右cpu),且代码和引用精简(无其他托管和非托管的dll依赖,更无需安装任何插件,你的程序完全绿色运行);并且如果硬解不可用,切换到软件是自动过程

  首先需要准备好visual studio/msys2/ffmpeg源码/dx9sdk。因为我们要自己编译ffmpeg,并且是改动代码后编译,ffmpeg我们编译时会裁剪。

  • ffmpeg源码大家使用4.2.1,和我保持同步,这样比较好对应,下载地址为ffmpeg-4.2.1.tar.gz
  • msys2安装好后不需要装mingw和其他东西,只需要安装make(见下方图片;我们编译工具链会用msvc而非mingw-gcc)

  • visual studio版本按道理是不需要新版本的,应该是2008-2019都可以(不过还是得看看ffmpeg代码里是否用了c99 c11等低版本不支持的东西),vs需要安装c++和c#的模块(见下方图片;应该也不需要特意去打开什么功能)

  • dx9的sdk理论上是不用安装的(如果你是高手,可以用c#的ilgenerator直接写calli;亦或者写unsafe代码直接进行内存call,文章最后我会为大家揭秘如何用c#调用c++甚至com组件)。我用了directx的managecode,由官方为我们做了dx的调用(见下方图片)

  第二步是修改ffmpeg源码并编译,我们要修改的源码只有一个文件的十余行,而且是增量修改。

修改的文件位于libavutil/hwcontext_dxva2.c文件,我先将修改部分贴出来然后再给大家解释

hwcontext_dxva2.c修改部分

  1. static int dxva2_device_create9_extend(AVHWDeviceContext *ctx, UINT adapter, HWND hWnd)
  2. {
  3. DXVA2DevicePriv *priv = ctx->user_opaque;
  4. D3DPRESENT_PARAMETERS d3dpp = {0};
  5. D3DDISPLAYMODE d3ddm;
  6. HRESULT hr;
  7. pDirect3DCreate9 *createD3D = (pDirect3DCreate9 *)dlsym(priv->d3dlib, "Direct3DCreate9");
  8. if (!createD3D) {
  9. av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n");
  10. return AVERROR_UNKNOWN;
  11. }
  12. priv->d3d9 = createD3D(D3D_SDK_VERSION);
  13. if (!priv->d3d9) {
  14.     av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n");
  15.     return AVERROR_UNKNOWN;
  16. }
  17. IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm);
  18. d3dpp.BackBufferFormat = d3ddm.Format;
  19. d3dpp.Windowed = TRUE;           // 是否窗口显示
  20. d3dpp.hDeviceWindow = hWnd;    // 显示窗口句柄
  21. d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // 交换链设置,后台缓冲使用后直接丢弃
  22. d3dpp.Flags = D3DPRESENTFLAG_VIDEO;          // 附加特性,显示视频
  23. DWORD behaviorFlags = D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
  24. D3DDEVTYPE devType = D3DDEVTYPE_HAL;
  25. D3DCAPS9 caps;
  26. if (IDirect3D9_GetDeviceCaps(priv->d3d9, D3DADAPTER_DEFAULT, devType, &caps) >= 0)
  27. {
  28. 	if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  29. 	{
  30. 		behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
  31. 	}
  32. 	else
  33. 	{
  34. 		behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  35. 	}
  36. }
  37. if(!hWnd)
  38. 	hWnd = GetDesktopWindow();
  39. hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, hWnd,
  40.                              behaviorFlags,
  41.                              &d3dpp, &priv->d3d9device);
  42. if (FAILED(hr)) {
  43.     av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
  44.     return AVERROR_UNKNOWN;
  45. }
  46. return 0;
  47. }

  48. static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device,

  49. AVDictionary *opts, int flags)

  50. {

  51. AVDXVA2DeviceContext *hwctx = ctx->hwctx;

  52. DXVA2DevicePriv *priv;

  53. pCreateDeviceManager9 *createDeviceManager = NULL;

  54. unsigned resetToken = 0;

  55. UINT adapter = D3DADAPTER_DEFAULT;

  56. HRESULT hr;

  57. int err;

  58. AVDictionaryEntry *t = NULL;

  59. HWND hWnd = NULL;

  60. if (device)
  61.     adapter = atoi(device);
  62. priv = av_mallocz(sizeof(*priv));
  63. if (!priv)
  64.     return AVERROR(ENOMEM);
  65. ctx->user_opaque = priv;
  66. ctx->free        = dxva2_device_free;
  67. priv->device_handle = INVALID_HANDLE_VALUE;
  68. priv->d3dlib = dlopen("d3d9.dll", 0);
  69. if (!priv->d3dlib) {
  70.     av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n");
  71.     return AVERROR_UNKNOWN;
  72. }
  73. priv->dxva2lib = dlopen("dxva2.dll", 0);
  74. if (!priv->dxva2lib) {
  75.     av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n");
  76.     return AVERROR_UNKNOWN;
  77. }
  78. createDeviceManager = (pCreateDeviceManager9 *)dlsym(priv->dxva2lib,
  79.                                                      "DXVA2CreateDirect3DDeviceManager9");
  80. if (!createDeviceManager) {
  81.     av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
  82.     return AVERROR_UNKNOWN;
  83. }
  84. t = av_dict_get(opts, "hWnd", NULL, 0);
  85. if(t) {
  86. 	hWnd = (HWND)atoi(t->value);
  87. }
  88. if(hWnd) {
  89. 	if((err = dxva2_device_create9_extend(ctx, adapter, hWnd)) < 0)
  90. 		return err;
  91. } else {
  92. 	if (dxva2_device_create9ex(ctx, adapter) < 0) {
  93. 		// Retry with "classic" d3d9
  94. 		err = dxva2_device_create9(ctx, adapter);
  95. 		if (err < 0)
  96. 			return err;
  97. 	}
  98. }
  99. hr = createDeviceManager(&resetToken, &hwctx->devmgr);
  100. if (FAILED(hr)) {
  101.     av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n");
  102.     return AVERROR_UNKNOWN;
  103. }
  104. hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken);
  105. if (FAILED(hr)) {
  106.     av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n");
  107.     return AVERROR_UNKNOWN;
  108. }
  109. hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle);
  110. if (FAILED(hr)) {
  111.     av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n");
  112.     return AVERROR_UNKNOWN;
  113. }
  114. return 0;
  115. }

  代码中dxva2_device_create9_extend函数是我新加入的,并且在dxva2_device_create函数(这个函数是ffmpeg原始流程中的,我的改动不影响原本任何功能)中适时调用;简单来说,原来的ffmpeg也能基于dxva2硬件解码,但是它没法将解码得到的surface用于前台播放,因为它创建device时并未指定窗口和其他相关参数,大家可以参考我代码实现,我将窗口句柄传入后创建过程完全改变(其他人如果使用我们编译的代码,他没有传入窗口句柄,就执行原来的创建,因此百分百兼容)。

原始文件(版本不一致,仅供参考)

  (ps:在这里我讲一下网络上另外一种写法(两年前我也用的他们的,因为没时间详细看ffmpeg源码),他们是在外面创建的device和surface然后想办法传到ffmpeg内部进行替换,这样做有好处,就是不用自己修改和编译ffmpeg,坏处是得自己维护device和surface。至于二进制兼容方面考虑,两种做法都不是太好)

代码修改完成后我们使用msys2编译

  • 首先是需要把编译器设置为msvc,这个步骤通过使用vs的命令行工具即可,如下图

  • 然后是设置msys2继承环境变量(这样make时才能找到cl/link)

  • 打开msys,查看变量是否正确

  • 编译ffmpeg
  1. ./configure --enable-shared --enable-small --disable-all --disable-autodetect --enable-avcodec --enable-decoder=h264 --enable-dxva2 --enable-hwaccel=h264_dxva2 --toolchain=msvc --prefix=host
  2. make && make install

编译完成后头文件和dll在host文件夹内(编译产出的dll也是clear的,不依赖msvc**.dll)

  在C#中使用我们产出的方式需要使用p/invoke和unsafe代码。

我先贴出我针对ffmpeg写的一个工具类,然后给大家稍微讲解一下

FFHelper.cs

  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace MultiPlayer

  4. {

  5. public enum AVCodecID

  6. {

  7. AV_CODEC_ID_NONE,
  8.     /* video codecs */
  9.     AV_CODEC_ID_MPEG1VIDEO,
  10.     AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding
  11.     AV_CODEC_ID_H261,
  12.     AV_CODEC_ID_H263,
  13.     AV_CODEC_ID_RV10,
  14.     AV_CODEC_ID_RV20,
  15.     AV_CODEC_ID_MJPEG,
  16.     AV_CODEC_ID_MJPEGB,
  17.     AV_CODEC_ID_LJPEG,
  18.     AV_CODEC_ID_SP5X,
  19.     AV_CODEC_ID_JPEGLS,
  20.     AV_CODEC_ID_MPEG4,
  21.     AV_CODEC_ID_RAWVIDEO,
  22.     AV_CODEC_ID_MSMPEG4V1,
  23.     AV_CODEC_ID_MSMPEG4V2,
  24.     AV_CODEC_ID_MSMPEG4V3,
  25.     AV_CODEC_ID_WMV1,
  26.     AV_CODEC_ID_WMV2,
  27.     AV_CODEC_ID_H263P,
  28.     AV_CODEC_ID_H263I,
  29.     AV_CODEC_ID_FLV1,
  30.     AV_CODEC_ID_SVQ1,
  31.     AV_CODEC_ID_SVQ3,
  32.     AV_CODEC_ID_DVVIDEO,
  33.     AV_CODEC_ID_HUFFYUV,
  34.     AV_CODEC_ID_CYUV,
  35.     AV_CODEC_ID_H264,
  36.     AV_CODEC_ID_INDEO3,
  37.     AV_CODEC_ID_VP3,
  38.     AV_CODEC_ID_THEORA,
  39.     AV_CODEC_ID_ASV1,
  40.     AV_CODEC_ID_ASV2,
  41.     AV_CODEC_ID_FFV1,
  42.     AV_CODEC_ID_4XM,
  43.     AV_CODEC_ID_VCR1,
  44.     AV_CODEC_ID_CLJR,
  45.     AV_CODEC_ID_MDEC,
  46.     AV_CODEC_ID_ROQ,
  47.     AV_CODEC_ID_INTERPLAY_VIDEO,
  48.     AV_CODEC_ID_XAN_WC3,
  49.     AV_CODEC_ID_XAN_WC4,
  50.     AV_CODEC_ID_RPZA,
  51.     AV_CODEC_ID_CINEPAK,
  52.     AV_CODEC_ID_WS_VQA,
  53.     AV_CODEC_ID_MSRLE,
  54.     AV_CODEC_ID_MSVIDEO1,
  55.     AV_CODEC_ID_IDCIN,
  56.     AV_CODEC_ID_8BPS,
  57.     AV_CODEC_ID_SMC,
  58.     AV_CODEC_ID_FLIC,
  59.     AV_CODEC_ID_TRUEMOTION1,
  60.     AV_CODEC_ID_VMDVIDEO,
  61.     AV_CODEC_ID_MSZH,
  62.     AV_CODEC_ID_ZLIB,
  63.     AV_CODEC_ID_QTRLE,
  64.     AV_CODEC_ID_TSCC,
  65.     AV_CODEC_ID_ULTI,
  66.     AV_CODEC_ID_QDRAW,
  67.     AV_CODEC_ID_VIXL,
  68.     AV_CODEC_ID_QPEG,
  69.     AV_CODEC_ID_PNG,
  70.     AV_CODEC_ID_PPM,
  71.     AV_CODEC_ID_PBM,
  72.     AV_CODEC_ID_PGM,
  73.     AV_CODEC_ID_PGMYUV,
  74.     AV_CODEC_ID_PAM,
  75.     AV_CODEC_ID_FFVHUFF,
  76.     AV_CODEC_ID_RV30,
  77.     AV_CODEC_ID_RV40,
  78.     AV_CODEC_ID_VC1,
  79.     AV_CODEC_ID_WMV3,
  80.     AV_CODEC_ID_LOCO,
  81.     AV_CODEC_ID_WNV1,
  82.     AV_CODEC_ID_AASC,
  83.     AV_CODEC_ID_INDEO2,
  84.     AV_CODEC_ID_FRAPS,
  85.     AV_CODEC_ID_TRUEMOTION2,
  86.     AV_CODEC_ID_BMP,
  87.     AV_CODEC_ID_CSCD,
  88.     AV_CODEC_ID_MMVIDEO,
  89.     AV_CODEC_ID_ZMBV,
  90.     AV_CODEC_ID_AVS,
  91.     AV_CODEC_ID_SMACKVIDEO,
  92.     AV_CODEC_ID_NUV,
  93.     AV_CODEC_ID_KMVC,
  94.     AV_CODEC_ID_FLASHSV,
  95.     AV_CODEC_ID_CAVS,
  96.     AV_CODEC_ID_JPEG2000,
  97.     AV_CODEC_ID_VMNC,
  98.     AV_CODEC_ID_VP5,
  99.     AV_CODEC_ID_VP6,
  100.     AV_CODEC_ID_VP6F,
  101.     AV_CODEC_ID_TARGA,
  102.     AV_CODEC_ID_DSICINVIDEO,
  103.     AV_CODEC_ID_TIERTEXSEQVIDEO,
  104.     AV_CODEC_ID_TIFF,
  105.     AV_CODEC_ID_GIF,
  106.     AV_CODEC_ID_DXA,
  107.     AV_CODEC_ID_DNXHD,
  108.     AV_CODEC_ID_THP,
  109.     AV_CODEC_ID_SGI,
  110.     AV_CODEC_ID_C93,
  111.     AV_CODEC_ID_BETHSOFTVID,
  112.     AV_CODEC_ID_PTX,
  113.     AV_CODEC_ID_TXD,
  114.     AV_CODEC_ID_VP6A,
  115.     AV_CODEC_ID_AMV,
  116.     AV_CODEC_ID_VB,
  117.     AV_CODEC_ID_PCX,
  118.     AV_CODEC_ID_SUNRAST,
  119.     AV_CODEC_ID_INDEO4,
  120.     AV_CODEC_ID_INDEO5,
  121.     AV_CODEC_ID_MIMIC,
  122.     AV_CODEC_ID_RL2,
  123.     AV_CODEC_ID_ESCAPE124,
  124.     AV_CODEC_ID_DIRAC,
  125.     AV_CODEC_ID_BFI,
  126.     AV_CODEC_ID_CMV,
  127.     AV_CODEC_ID_MOTIONPIXELS,
  128.     AV_CODEC_ID_TGV,
  129.     AV_CODEC_ID_TGQ,
  130.     AV_CODEC_ID_TQI,
  131.     AV_CODEC_ID_AURA,
  132.     AV_CODEC_ID_AURA2,
  133.     AV_CODEC_ID_V210X,
  134.     AV_CODEC_ID_TMV,
  135.     AV_CODEC_ID_V210,
  136.     AV_CODEC_ID_DPX,
  137.     AV_CODEC_ID_MAD,
  138.     AV_CODEC_ID_FRWU,
  139.     AV_CODEC_ID_FLASHSV2,
  140.     AV_CODEC_ID_CDGRAPHICS,
  141.     AV_CODEC_ID_R210,
  142.     AV_CODEC_ID_ANM,
  143.     AV_CODEC_ID_BINKVIDEO,
  144.     AV_CODEC_ID_IFF_ILBM,
  145.     //#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM
  146.     AV_CODEC_ID_KGV1,
  147.     AV_CODEC_ID_YOP,
  148.     AV_CODEC_ID_VP8,
  149.     AV_CODEC_ID_PICTOR,
  150.     AV_CODEC_ID_ANSI,
  151.     AV_CODEC_ID_A64_MULTI,
  152.     AV_CODEC_ID_A64_MULTI5,
  153.     AV_CODEC_ID_R10K,
  154.     AV_CODEC_ID_MXPEG,
  155.     AV_CODEC_ID_LAGARITH,
  156.     AV_CODEC_ID_PRORES,
  157.     AV_CODEC_ID_JV,
  158.     AV_CODEC_ID_DFA,
  159.     AV_CODEC_ID_WMV3IMAGE,
  160.     AV_CODEC_ID_VC1IMAGE,
  161.     AV_CODEC_ID_UTVIDEO,
  162.     AV_CODEC_ID_BMV_VIDEO,
  163.     AV_CODEC_ID_VBLE,
  164.     AV_CODEC_ID_DXTORY,
  165.     AV_CODEC_ID_V410,
  166.     AV_CODEC_ID_XWD,
  167.     AV_CODEC_ID_CDXL,
  168.     AV_CODEC_ID_XBM,
  169.     AV_CODEC_ID_ZEROCODEC,
  170.     AV_CODEC_ID_MSS1,
  171.     AV_CODEC_ID_MSA1,
  172.     AV_CODEC_ID_TSCC2,
  173.     AV_CODEC_ID_MTS2,
  174.     AV_CODEC_ID_CLLC,
  175.     AV_CODEC_ID_MSS2,
  176.     AV_CODEC_ID_VP9,
  177.     AV_CODEC_ID_AIC,
  178.     AV_CODEC_ID_ESCAPE130,
  179.     AV_CODEC_ID_G2M,
  180.     AV_CODEC_ID_WEBP,
  181.     AV_CODEC_ID_HNM4_VIDEO,
  182.     AV_CODEC_ID_HEVC,
  183.     //#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC
  184.     AV_CODEC_ID_FIC,
  185.     AV_CODEC_ID_ALIAS_PIX,
  186.     AV_CODEC_ID_BRENDER_PIX,
  187.     AV_CODEC_ID_PAF_VIDEO,
  188.     AV_CODEC_ID_EXR,
  189.     AV_CODEC_ID_VP7,
  190.     AV_CODEC_ID_SANM,
  191.     AV_CODEC_ID_SGIRLE,
  192.     AV_CODEC_ID_MVC1,
  193.     AV_CODEC_ID_MVC2,
  194.     AV_CODEC_ID_HQX,
  195.     AV_CODEC_ID_TDSC,
  196.     AV_CODEC_ID_HQ_HQA,
  197.     AV_CODEC_ID_HAP,
  198.     AV_CODEC_ID_DDS,
  199.     AV_CODEC_ID_DXV,
  200.     AV_CODEC_ID_SCREENPRESSO,
  201.     AV_CODEC_ID_RSCC,
  202.     AV_CODEC_ID_AVS2,
  203.     AV_CODEC_ID_Y41P = 0x8000,
  204.     AV_CODEC_ID_AVRP,
  205.     AV_CODEC_ID_012V,
  206.     AV_CODEC_ID_AVUI,
  207.     AV_CODEC_ID_AYUV,
  208.     AV_CODEC_ID_TARGA_Y216,
  209.     AV_CODEC_ID_V308,
  210.     AV_CODEC_ID_V408,
  211.     AV_CODEC_ID_YUV4,
  212.     AV_CODEC_ID_AVRN,
  213.     AV_CODEC_ID_CPIA,
  214.     AV_CODEC_ID_XFACE,
  215.     AV_CODEC_ID_SNOW,
  216.     AV_CODEC_ID_SMVJPEG,
  217.     AV_CODEC_ID_APNG,
  218.     AV_CODEC_ID_DAALA,
  219.     AV_CODEC_ID_CFHD,
  220.     AV_CODEC_ID_TRUEMOTION2RT,
  221.     AV_CODEC_ID_M101,
  222.     AV_CODEC_ID_MAGICYUV,
  223.     AV_CODEC_ID_SHEERVIDEO,
  224.     AV_CODEC_ID_YLC,
  225.     AV_CODEC_ID_PSD,
  226.     AV_CODEC_ID_PIXLET,
  227.     AV_CODEC_ID_SPEEDHQ,
  228.     AV_CODEC_ID_FMVC,
  229.     AV_CODEC_ID_SCPR,
  230.     AV_CODEC_ID_CLEARVIDEO,
  231.     AV_CODEC_ID_XPM,
  232.     AV_CODEC_ID_AV1,
  233.     AV_CODEC_ID_BITPACKED,
  234.     AV_CODEC_ID_MSCC,
  235.     AV_CODEC_ID_SRGC,
  236.     AV_CODEC_ID_SVG,
  237.     AV_CODEC_ID_GDV,
  238.     AV_CODEC_ID_FITS,
  239.     AV_CODEC_ID_IMM4,
  240.     AV_CODEC_ID_PROSUMER,
  241.     AV_CODEC_ID_MWSC,
  242.     AV_CODEC_ID_WCMV,
  243.     AV_CODEC_ID_RASC,
  244.     AV_CODEC_ID_HYMT,
  245.     AV_CODEC_ID_ARBC,
  246.     AV_CODEC_ID_AGM,
  247.     AV_CODEC_ID_LSCR,
  248.     AV_CODEC_ID_VP4,
  249.     /* various PCM "codecs" */
  250.     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
  251.     AV_CODEC_ID_PCM_S16LE = 0x10000,
  252.     AV_CODEC_ID_PCM_S16BE,
  253.     AV_CODEC_ID_PCM_U16LE,
  254.     AV_CODEC_ID_PCM_U16BE,
  255.     AV_CODEC_ID_PCM_S8,
  256.     AV_CODEC_ID_PCM_U8,
  257.     AV_CODEC_ID_PCM_MULAW,
  258.     AV_CODEC_ID_PCM_ALAW,
  259.     AV_CODEC_ID_PCM_S32LE,
  260.     AV_CODEC_ID_PCM_S32BE,
  261.     AV_CODEC_ID_PCM_U32LE,
  262.     AV_CODEC_ID_PCM_U32BE,
  263.     AV_CODEC_ID_PCM_S24LE,
  264.     AV_CODEC_ID_PCM_S24BE,
  265.     AV_CODEC_ID_PCM_U24LE,
  266.     AV_CODEC_ID_PCM_U24BE,
  267.     AV_CODEC_ID_PCM_S24DAUD,
  268.     AV_CODEC_ID_PCM_ZORK,
  269.     AV_CODEC_ID_PCM_S16LE_PLANAR,
  270.     AV_CODEC_ID_PCM_DVD,
  271.     AV_CODEC_ID_PCM_F32BE,
  272.     AV_CODEC_ID_PCM_F32LE,
  273.     AV_CODEC_ID_PCM_F64BE,
  274.     AV_CODEC_ID_PCM_F64LE,
  275.     AV_CODEC_ID_PCM_BLURAY,
  276.     AV_CODEC_ID_PCM_LXF,
  277.     AV_CODEC_ID_S302M,
  278.     AV_CODEC_ID_PCM_S8_PLANAR,
  279.     AV_CODEC_ID_PCM_S24LE_PLANAR,
  280.     AV_CODEC_ID_PCM_S32LE_PLANAR,
  281.     AV_CODEC_ID_PCM_S16BE_PLANAR,
  282.     AV_CODEC_ID_PCM_S64LE = 0x10800,
  283.     AV_CODEC_ID_PCM_S64BE,
  284.     AV_CODEC_ID_PCM_F16LE,
  285.     AV_CODEC_ID_PCM_F24LE,
  286.     AV_CODEC_ID_PCM_VIDC,
  287.     /* various ADPCM codecs */
  288.     AV_CODEC_ID_ADPCM_IMA_QT = 0x11000,
  289.     AV_CODEC_ID_ADPCM_IMA_WAV,
  290.     AV_CODEC_ID_ADPCM_IMA_DK3,
  291.     AV_CODEC_ID_ADPCM_IMA_DK4,
  292.     AV_CODEC_ID_ADPCM_IMA_WS,
  293.     AV_CODEC_ID_ADPCM_IMA_SMJPEG,
  294.     AV_CODEC_ID_ADPCM_MS,
  295.     AV_CODEC_ID_ADPCM_4XM,
  296.     AV_CODEC_ID_ADPCM_XA,
  297.     AV_CODEC_ID_ADPCM_ADX,
  298.     AV_CODEC_ID_ADPCM_EA,
  299.     AV_CODEC_ID_ADPCM_G726,
  300.     AV_CODEC_ID_ADPCM_CT,
  301.     AV_CODEC_ID_ADPCM_SWF,
  302.     AV_CODEC_ID_ADPCM_YAMAHA,
  303.     AV_CODEC_ID_ADPCM_SBPRO_4,
  304.     AV_CODEC_ID_ADPCM_SBPRO_3,
  305.     AV_CODEC_ID_ADPCM_SBPRO_2,
  306.     AV_CODEC_ID_ADPCM_THP,
  307.     AV_CODEC_ID_ADPCM_IMA_AMV,
  308.     AV_CODEC_ID_ADPCM_EA_R1,
  309.     AV_CODEC_ID_ADPCM_EA_R3,
  310.     AV_CODEC_ID_ADPCM_EA_R2,
  311.     AV_CODEC_ID_ADPCM_IMA_EA_SEAD,
  312.     AV_CODEC_ID_ADPCM_IMA_EA_EACS,
  313.     AV_CODEC_ID_ADPCM_EA_XAS,
  314.     AV_CODEC_ID_ADPCM_EA_MAXIS_XA,
  315.     AV_CODEC_ID_ADPCM_IMA_ISS,
  316.     AV_CODEC_ID_ADPCM_G722,
  317.     AV_CODEC_ID_ADPCM_IMA_APC,
  318.     AV_CODEC_ID_ADPCM_VIMA,
  319.     AV_CODEC_ID_ADPCM_AFC = 0x11800,
  320.     AV_CODEC_ID_ADPCM_IMA_OKI,
  321.     AV_CODEC_ID_ADPCM_DTK,
  322.     AV_CODEC_ID_ADPCM_IMA_RAD,
  323.     AV_CODEC_ID_ADPCM_G726LE,
  324.     AV_CODEC_ID_ADPCM_THP_LE,
  325.     AV_CODEC_ID_ADPCM_PSX,
  326.     AV_CODEC_ID_ADPCM_AICA,
  327.     AV_CODEC_ID_ADPCM_IMA_DAT4,
  328.     AV_CODEC_ID_ADPCM_MTAF,
  329.     AV_CODEC_ID_ADPCM_AGM,
  330.     /* AMR */
  331.     AV_CODEC_ID_AMR_NB = 0x12000,
  332.     AV_CODEC_ID_AMR_WB,
  333.     /* RealAudio codecs*/
  334.     AV_CODEC_ID_RA_144 = 0x13000,
  335.     AV_CODEC_ID_RA_288,
  336.     /* various DPCM codecs */
  337.     AV_CODEC_ID_ROQ_DPCM = 0x14000,
  338.     AV_CODEC_ID_INTERPLAY_DPCM,
  339.     AV_CODEC_ID_XAN_DPCM,
  340.     AV_CODEC_ID_SOL_DPCM,
  341.     AV_CODEC_ID_SDX2_DPCM = 0x14800,
  342.     AV_CODEC_ID_GREMLIN_DPCM,
  343.     /* audio codecs */
  344.     AV_CODEC_ID_MP2 = 0x15000,
  345.     AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3
  346.     AV_CODEC_ID_AAC,
  347.     AV_CODEC_ID_AC3,
  348.     AV_CODEC_ID_DTS,
  349.     AV_CODEC_ID_VORBIS,
  350.     AV_CODEC_ID_DVAUDIO,
  351.     AV_CODEC_ID_WMAV1,
  352.     AV_CODEC_ID_WMAV2,
  353.     AV_CODEC_ID_MACE3,
  354.     AV_CODEC_ID_MACE6,
  355.     AV_CODEC_ID_VMDAUDIO,
  356.     AV_CODEC_ID_FLAC,
  357.     AV_CODEC_ID_MP3ADU,
  358.     AV_CODEC_ID_MP3ON4,
  359.     AV_CODEC_ID_SHORTEN,
  360.     AV_CODEC_ID_ALAC,
  361.     AV_CODEC_ID_WESTWOOD_SND1,
  362.     AV_CODEC_ID_GSM, ///< as in Berlin toast format
  363.     AV_CODEC_ID_QDM2,
  364.     AV_CODEC_ID_COOK,
  365.     AV_CODEC_ID_TRUESPEECH,
  366.     AV_CODEC_ID_TTA,
  367.     AV_CODEC_ID_SMACKAUDIO,
  368.     AV_CODEC_ID_QCELP,
  369.     AV_CODEC_ID_WAVPACK,
  370.     AV_CODEC_ID_DSICINAUDIO,
  371.     AV_CODEC_ID_IMC,
  372.     AV_CODEC_ID_MUSEPACK7,
  373.     AV_CODEC_ID_MLP,
  374.     AV_CODEC_ID_GSM_MS, /* as found in WAV */
  375.     AV_CODEC_ID_ATRAC3,
  376.     AV_CODEC_ID_APE,
  377.     AV_CODEC_ID_NELLYMOSER,
  378.     AV_CODEC_ID_MUSEPACK8,
  379.     AV_CODEC_ID_SPEEX,
  380.     AV_CODEC_ID_WMAVOICE,
  381.     AV_CODEC_ID_WMAPRO,
  382.     AV_CODEC_ID_WMALOSSLESS,
  383.     AV_CODEC_ID_ATRAC3P,
  384.     AV_CODEC_ID_EAC3,
  385.     AV_CODEC_ID_SIPR,
  386.     AV_CODEC_ID_MP1,
  387.     AV_CODEC_ID_TWINVQ,
  388.     AV_CODEC_ID_TRUEHD,
  389.     AV_CODEC_ID_MP4ALS,
  390.     AV_CODEC_ID_ATRAC1,
  391.     AV_CODEC_ID_BINKAUDIO_RDFT,
  392.     AV_CODEC_ID_BINKAUDIO_DCT,
  393.     AV_CODEC_ID_AAC_LATM,
  394.     AV_CODEC_ID_QDMC,
  395.     AV_CODEC_ID_CELT,
  396.     AV_CODEC_ID_G723_1,
  397.     AV_CODEC_ID_G729,
  398.     AV_CODEC_ID_8SVX_EXP,
  399.     AV_CODEC_ID_8SVX_FIB,
  400.     AV_CODEC_ID_BMV_AUDIO,
  401.     AV_CODEC_ID_RALF,
  402.     AV_CODEC_ID_IAC,
  403.     AV_CODEC_ID_ILBC,
  404.     AV_CODEC_ID_OPUS,
  405.     AV_CODEC_ID_COMFORT_NOISE,
  406.     AV_CODEC_ID_TAK,
  407.     AV_CODEC_ID_METASOUND,
  408.     AV_CODEC_ID_PAF_AUDIO,
  409.     AV_CODEC_ID_ON2AVC,
  410.     AV_CODEC_ID_DSS_SP,
  411.     AV_CODEC_ID_CODEC2,
  412.     AV_CODEC_ID_FFWAVESYNTH = 0x15800,
  413.     AV_CODEC_ID_SONIC,
  414.     AV_CODEC_ID_SONIC_LS,
  415.     AV_CODEC_ID_EVRC,
  416.     AV_CODEC_ID_SMV,
  417.     AV_CODEC_ID_DSD_LSBF,
  418.     AV_CODEC_ID_DSD_MSBF,
  419.     AV_CODEC_ID_DSD_LSBF_PLANAR,
  420.     AV_CODEC_ID_DSD_MSBF_PLANAR,
  421.     AV_CODEC_ID_4GV,
  422.     AV_CODEC_ID_INTERPLAY_ACM,
  423.     AV_CODEC_ID_XMA1,
  424.     AV_CODEC_ID_XMA2,
  425.     AV_CODEC_ID_DST,
  426.     AV_CODEC_ID_ATRAC3AL,
  427.     AV_CODEC_ID_ATRAC3PAL,
  428.     AV_CODEC_ID_DOLBY_E,
  429.     AV_CODEC_ID_APTX,
  430.     AV_CODEC_ID_APTX_HD,
  431.     AV_CODEC_ID_SBC,
  432.     AV_CODEC_ID_ATRAC9,
  433.     AV_CODEC_ID_HCOM,
  434.     /* subtitle codecs */
  435.     AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
  436.     AV_CODEC_ID_DVD_SUBTITLE = 0x17000,
  437.     AV_CODEC_ID_DVB_SUBTITLE,
  438.     AV_CODEC_ID_TEXT,  ///< raw UTF-8 text
  439.     AV_CODEC_ID_XSUB,
  440.     AV_CODEC_ID_SSA,
  441.     AV_CODEC_ID_MOV_TEXT,
  442.     AV_CODEC_ID_HDMV_PGS_SUBTITLE,
  443.     AV_CODEC_ID_DVB_TELETEXT,
  444.     AV_CODEC_ID_SRT,
  445.     AV_CODEC_ID_MICRODVD = 0x17800,
  446.     AV_CODEC_ID_EIA_608,
  447.     AV_CODEC_ID_JACOSUB,
  448.     AV_CODEC_ID_SAMI,
  449.     AV_CODEC_ID_REALTEXT,
  450.     AV_CODEC_ID_STL,
  451.     AV_CODEC_ID_SUBVIEWER1,
  452.     AV_CODEC_ID_SUBVIEWER,
  453.     AV_CODEC_ID_SUBRIP,
  454.     AV_CODEC_ID_WEBVTT,
  455.     AV_CODEC_ID_MPL2,
  456.     AV_CODEC_ID_VPLAYER,
  457.     AV_CODEC_ID_PJS,
  458.     AV_CODEC_ID_ASS,
  459.     AV_CODEC_ID_HDMV_TEXT_SUBTITLE,
  460.     AV_CODEC_ID_TTML,
  461.     AV_CODEC_ID_ARIB_CAPTION,
  462.     /* other specific kind of codecs (generally used for attachments) */
  463.     AV_CODEC_ID_FIRST_UNKNOWN = 0x18000,           ///< A dummy ID pointing at the start of various fake codecs.
  464.     AV_CODEC_ID_TTF = 0x18000,
  465.     AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream.
  466.     AV_CODEC_ID_BINTEXT = 0x18800,
  467.     AV_CODEC_ID_XBIN,
  468.     AV_CODEC_ID_IDF,
  469.     AV_CODEC_ID_OTF,
  470.     AV_CODEC_ID_SMPTE_KLV,
  471.     AV_CODEC_ID_DVD_NAV,
  472.     AV_CODEC_ID_TIMED_ID3,
  473.     AV_CODEC_ID_BIN_DATA,
  474.     AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
  475.     AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS
  476.                             * stream (only used by libavformat) */
  477.     AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems
  478.                             * stream (only used by libavformat) */
  479.     AV_CODEC_ID_FFMETADATA = 0x21000,   ///< Dummy codec for streams containing only metadata information.
  480.     AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket
  481. }
  482. public enum AVHWDeviceType
  483. {
  484.     AV_HWDEVICE_TYPE_NONE,
  485.     AV_HWDEVICE_TYPE_VDPAU,
  486.     AV_HWDEVICE_TYPE_CUDA,
  487.     AV_HWDEVICE_TYPE_VAAPI,
  488.     AV_HWDEVICE_TYPE_DXVA2,
  489.     AV_HWDEVICE_TYPE_QSV,
  490.     AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
  491.     AV_HWDEVICE_TYPE_D3D11VA,
  492.     AV_HWDEVICE_TYPE_DRM,
  493.     AV_HWDEVICE_TYPE_OPENCL,
  494.     AV_HWDEVICE_TYPE_MEDIACODEC,
  495. }
  496. public enum AVPixelFormat
  497. {
  498.     AV_PIX_FMT_NONE = -1,
  499.     AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
  500.     AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
  501.     AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
  502.     AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
  503.     AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
  504.     AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
  505.     AV_PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
  506.     AV_PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
  507.     AV_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
  508.     AV_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
  509.     AV_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
  510.     AV_PIX_FMT_PAL8,      ///< 8 bits with AV_PIX_FMT_RGB32 palette
  511.     AV_PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range
  512.     AV_PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range
  513.     AV_PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range
  514.     AV_PIX_FMT_UYVY422,   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
  515.     AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
  516.     AV_PIX_FMT_BGR8,      ///< packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
  517.     AV_PIX_FMT_BGR4,      ///< 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
  518.     AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
  519.     AV_PIX_FMT_RGB8,      ///< packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
  520.     AV_PIX_FMT_RGB4,      ///< 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
  521.     AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1R 2G 1B(lsb)
  522.     AV_PIX_FMT_NV12,      ///< 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)
  523.     AV_PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped
  524.     AV_PIX_FMT_ARGB,      ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
  525.     AV_PIX_FMT_RGBA,      ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
  526.     AV_PIX_FMT_ABGR,      ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
  527.     AV_PIX_FMT_BGRA,      ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
  528.     AV_PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
  529.     AV_PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
  530.     AV_PIX_FMT_YUV440P,   ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
  531.     AV_PIX_FMT_YUVJ440P,  ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
  532.     AV_PIX_FMT_YUVA420P,  ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
  533.     AV_PIX_FMT_RGB48BE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
  534.     AV_PIX_FMT_RGB48LE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
  535.     AV_PIX_FMT_RGB565BE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), big-endian
  536.     AV_PIX_FMT_RGB565LE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), little-endian
  537.     AV_PIX_FMT_RGB555BE,  ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian   , X=unused/undefined
  538.     AV_PIX_FMT_RGB555LE,  ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
  539.     AV_PIX_FMT_BGR565BE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), big-endian
  540.     AV_PIX_FMT_BGR565LE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), little-endian
  541.     AV_PIX_FMT_BGR555BE,  ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian   , X=unused/undefined
  542.     AV_PIX_FMT_BGR555LE,  ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
  543.     /** @name Deprecated pixel formats */
  544.     /**@{*/
  545.     AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
  546.     AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
  547.     AV_PIX_FMT_VAAPI_VLD,  ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID
  548.     /**@}*/
  549.     AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD,
  550.     AV_PIX_FMT_YUV420P16LE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
  551.     AV_PIX_FMT_YUV420P16BE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
  552.     AV_PIX_FMT_YUV422P16LE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
  553.     AV_PIX_FMT_YUV422P16BE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
  554.     AV_PIX_FMT_YUV444P16LE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
  555.     AV_PIX_FMT_YUV444P16BE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
  556.     AV_PIX_FMT_DXVA2_VLD,    ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
  557.     AV_PIX_FMT_RGB444LE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined
  558.     AV_PIX_FMT_RGB444BE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian,    X=unused/undefined
  559.     AV_PIX_FMT_BGR444LE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined
  560.     AV_PIX_FMT_BGR444BE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian,    X=unused/undefined
  561.     AV_PIX_FMT_YA8,       ///< 8 bits gray, 8 bits alpha
  562.     AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
  563.     AV_PIX_FMT_GRAY8A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
  564.     AV_PIX_FMT_BGR48BE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
  565.     AV_PIX_FMT_BGR48LE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
  566.     /**
  567.      * The following 12 formats have the disadvantage of needing 1 format for each bit depth.
  568.      * Notice that each 9/10 bits sample is stored in 16 bits with extra padding.
  569.      * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better.
  570.      */
  571.     AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
  572.     AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
  573.     AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
  574.     AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
  575.     AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
  576.     AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
  577.     AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
  578.     AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
  579.     AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
  580.     AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
  581.     AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
  582.     AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
  583.     AV_PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp
  584.     AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP
  585.     AV_PIX_FMT_GBRP9BE,   ///< planar GBR 4:4:4 27bpp, big-endian
  586.     AV_PIX_FMT_GBRP9LE,   ///< planar GBR 4:4:4 27bpp, little-endian
  587.     AV_PIX_FMT_GBRP10BE,  ///< planar GBR 4:4:4 30bpp, big-endian
  588.     AV_PIX_FMT_GBRP10LE,  ///< planar GBR 4:4:4 30bpp, little-endian
  589.     AV_PIX_FMT_GBRP16BE,  ///< planar GBR 4:4:4 48bpp, big-endian
  590.     AV_PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little-endian
  591.     AV_PIX_FMT_YUVA422P,  ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
  592.     AV_PIX_FMT_YUVA444P,  ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
  593.     AV_PIX_FMT_YUVA420P9BE,  ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian
  594.     AV_PIX_FMT_YUVA420P9LE,  ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian
  595.     AV_PIX_FMT_YUVA422P9BE,  ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian
  596.     AV_PIX_FMT_YUVA422P9LE,  ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian
  597.     AV_PIX_FMT_YUVA444P9BE,  ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
  598.     AV_PIX_FMT_YUVA444P9LE,  ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
  599.     AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
  600.     AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
  601.     AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
  602.     AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
  603.     AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
  604.     AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
  605.     AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
  606.     AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
  607.     AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
  608.     AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
  609.     AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
  610.     AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
  611.     AV_PIX_FMT_VDPAU,     ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface
  612.     AV_PIX_FMT_XYZ12LE,      ///< 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
  613.     AV_PIX_FMT_XYZ12BE,      ///< 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
  614.     AV_PIX_FMT_NV16,         ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
  615.     AV_PIX_FMT_NV20LE,       ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
  616.     AV_PIX_FMT_NV20BE,       ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
  617.     AV_PIX_FMT_RGBA64BE,     ///< 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
  618.     AV_PIX_FMT_RGBA64LE,     ///< 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
  619.     AV_PIX_FMT_BGRA64BE,     ///< 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
  620.     AV_PIX_FMT_BGRA64LE,     ///< 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
  621.     AV_PIX_FMT_YVYU422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
  622.     AV_PIX_FMT_YA16BE,       ///< 16 bits gray, 16 bits alpha (big-endian)
  623.     AV_PIX_FMT_YA16LE,       ///< 16 bits gray, 16 bits alpha (little-endian)
  624.     AV_PIX_FMT_GBRAP,        ///< planar GBRA 4:4:4:4 32bpp
  625.     AV_PIX_FMT_GBRAP16BE,    ///< planar GBRA 4:4:4:4 64bpp, big-endian
  626.     AV_PIX_FMT_GBRAP16LE,    ///< planar GBRA 4:4:4:4 64bpp, little-endian
  627.     /**
  628.      *  HW acceleration through QSV, data[3] contains a pointer to the
  629.      *  mfxFrameSurface1 structure.
  630.      */
  631.     AV_PIX_FMT_QSV,
  632.     /**
  633.      * HW acceleration though MMAL, data[3] contains a pointer to the
  634.      * MMAL_BUFFER_HEADER_T structure.
  635.      */
  636.     AV_PIX_FMT_MMAL,
  637.     AV_PIX_FMT_D3D11VA_VLD,  ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
  638.     /**
  639.      * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
  640.      * exactly as for system memory frames.
  641.      */
  642.     AV_PIX_FMT_CUDA,
  643.     AV_PIX_FMT_0RGB,        ///< packed RGB 8:8:8, 32bpp, XRGBXRGB...   X=unused/undefined
  644.     AV_PIX_FMT_RGB0,        ///< packed RGB 8:8:8, 32bpp, RGBXRGBX...   X=unused/undefined
  645.     AV_PIX_FMT_0BGR,        ///< packed BGR 8:8:8, 32bpp, XBGRXBGR...   X=unused/undefined
  646.     AV_PIX_FMT_BGR0,        ///< packed BGR 8:8:8, 32bpp, BGRXBGRX...   X=unused/undefined
  647.     AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
  648.     AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
  649.     AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
  650.     AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
  651.     AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
  652.     AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
  653.     AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
  654.     AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
  655.     AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
  656.     AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
  657.     AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
  658.     AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
  659.     AV_PIX_FMT_GBRP12BE,    ///< planar GBR 4:4:4 36bpp, big-endian
  660.     AV_PIX_FMT_GBRP12LE,    ///< planar GBR 4:4:4 36bpp, little-endian
  661.     AV_PIX_FMT_GBRP14BE,    ///< planar GBR 4:4:4 42bpp, big-endian
  662.     AV_PIX_FMT_GBRP14LE,    ///< planar GBR 4:4:4 42bpp, little-endian
  663.     AV_PIX_FMT_YUVJ411P,    ///< 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
  664.     AV_PIX_FMT_BAYER_BGGR8,    ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */
  665.     AV_PIX_FMT_BAYER_RGGB8,    ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */
  666.     AV_PIX_FMT_BAYER_GBRG8,    ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */
  667.     AV_PIX_FMT_BAYER_GRBG8,    ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */
  668.     AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */
  669.     AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */
  670.     AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */
  671.     AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */
  672.     AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */
  673.     AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */
  674.     AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */
  675.     AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */
  676.     AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing
  677.     AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
  678.     AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
  679.     AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
  680.     AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
  681.     AV_PIX_FMT_AYUV64LE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
  682.     AV_PIX_FMT_AYUV64BE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
  683.     AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox
  684.     AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian
  685.     AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian
  686.     AV_PIX_FMT_GBRAP12BE,  ///< planar GBR 4:4:4:4 48bpp, big-endian
  687.     AV_PIX_FMT_GBRAP12LE,  ///< planar GBR 4:4:4:4 48bpp, little-endian
  688.     AV_PIX_FMT_GBRAP10BE,  ///< planar GBR 4:4:4:4 40bpp, big-endian
  689.     AV_PIX_FMT_GBRAP10LE,  ///< planar GBR 4:4:4:4 40bpp, little-endian
  690.     AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec
  691.     AV_PIX_FMT_GRAY12BE,   ///<        Y        , 12bpp, big-endian
  692.     AV_PIX_FMT_GRAY12LE,   ///<        Y        , 12bpp, little-endian
  693.     AV_PIX_FMT_GRAY10BE,   ///<        Y        , 10bpp, big-endian
  694.     AV_PIX_FMT_GRAY10LE,   ///<        Y        , 10bpp, little-endian
  695.     AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian
  696.     AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian
  697.     /**
  698.      * Hardware surfaces for Direct3D11.
  699.      *
  700.      * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11
  701.      * hwaccel API and filtering support AV_PIX_FMT_D3D11 only.
  702.      *
  703.      * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the
  704.      * texture array index of the frame as intptr_t if the ID3D11Texture2D is
  705.      * an array texture (or always 0 if it's a normal texture).
  706.      */
  707.     AV_PIX_FMT_D3D11,
  708.     AV_PIX_FMT_GRAY9BE,   ///<        Y        , 9bpp, big-endian
  709.     AV_PIX_FMT_GRAY9LE,   ///<        Y        , 9bpp, little-endian
  710.     AV_PIX_FMT_GBRPF32BE,  ///< IEEE-754 single precision planar GBR 4:4:4,     96bpp, big-endian
  711.     AV_PIX_FMT_GBRPF32LE,  ///< IEEE-754 single precision planar GBR 4:4:4,     96bpp, little-endian
  712.     AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian
  713.     AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian
  714.     /**
  715.      * DRM-managed buffers exposed through PRIME buffer sharing.
  716.      *
  717.      * data[0] points to an AVDRMFrameDescriptor.
  718.      */
  719.     AV_PIX_FMT_DRM_PRIME,
  720.     /**
  721.      * Hardware surfaces for OpenCL.
  722.      *
  723.      * data[i] contain 2D image objects (typed in C as cl_mem, used
  724.      * in OpenCL as image2d_t) for each plane of the surface.
  725.      */
  726.     AV_PIX_FMT_OPENCL,
  727.     AV_PIX_FMT_GRAY14BE,   ///<        Y        , 14bpp, big-endian
  728.     AV_PIX_FMT_GRAY14LE,   ///<        Y        , 14bpp, little-endian
  729.     AV_PIX_FMT_GRAYF32BE,  ///< IEEE-754 single precision Y, 32bpp, big-endian
  730.     AV_PIX_FMT_GRAYF32LE,  ///< IEEE-754 single precision Y, 32bpp, little-endian
  731.     AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian
  732.     AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian
  733.     AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian
  734.     AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian
  735.     AV_PIX_FMT_NV24,      ///< 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)
  736.     AV_PIX_FMT_NV42,      ///< as above, but U and V bytes are swapped
  737.     AV_PIX_FMT_NB         ///< 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
  738. }
  739. /// <summary>
  740. /// ffmpeg中AVFrame结构体的前半部分,因为它太长了我不需要完全移植过来
  741. /// </summary>
  742. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 408)]
  743. public struct AVFrame
  744. {
  745.     //#define AV_NUM_DATA_POINTERS 8
  746.     //        uint8_t* data[AV_NUM_DATA_POINTERS];
  747.     public IntPtr data1;// 一般是y分量
  748.     public IntPtr data2;// 一般是v分量
  749.     public IntPtr data3;// 一般是u分量
  750.     public IntPtr data4;// 一般是surface(dxva2硬解时)
  751.     public IntPtr data5;
  752.     public IntPtr data6;
  753.     public IntPtr data7;
  754.     public IntPtr data8;
  755.     public int linesize1;// y分量每行长度(stride)
  756.     public int linesize2;// v分量每行长度(stride)
  757.     public int linesize3;// u分量每行长度(stride)
  758.     public int linesize4;
  759.     public int linesize5;
  760.     public int linesize6;
  761.     public int linesize7;
  762.     public int linesize8;
  763.     //uint8_t **extended_data;
  764.     IntPtr extended_data;
  765.     public int width;
  766.     public int height;
  767.     public int nb_samples;
  768.     public AVPixelFormat format;
  769. }
  770. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 128)]
  771. public struct AVCodec { }
  772. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 72)]
  773. public unsafe struct AVPacket
  774. {
  775.     fixed byte frontUnused[24]; // 前部无关数据
  776.     public void* data;
  777.     public int size;
  778. }
  779. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 12)]
  780. public struct AVBufferRef { }
  781. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 904)]
  782. public unsafe struct AVCodecContext
  783. {
  784.     fixed byte frontUnused[880]; // 前部无关数据
  785.     public AVBufferRef* hw_frames_ctx;
  786. }
  787. [StructLayout(LayoutKind.Sequential)]
  788. public struct AVDictionary { }
  789. public unsafe static class FFHelper
  790. {
  791.     const string avcodec = "avcodec-58";
  792.     const string avutil = "avutil-56";
  793.     const CallingConvention callingConvention = CallingConvention.Cdecl;
  794.     [DllImport(avcodec, CallingConvention = callingConvention)]
  795.     public extern static void avcodec_register_all();
  796.     [DllImport(avcodec, CallingConvention = callingConvention)]
  797.     public extern static AVCodec* avcodec_find_decoder(AVCodecID id);
  798.     [DllImport(avcodec, CallingConvention = callingConvention)]
  799.     public extern static AVPacket* av_packet_alloc();
  800.     [DllImport(avcodec, CallingConvention = callingConvention)]
  801.     public extern static void av_init_packet(AVPacket* pkt);
  802.     //[DllImport(avcodec, CallingConvention = callingConvention)]
  803.     //public extern static void av_packet_unref(AVPacket* pkt);
  804.     [DllImport(avcodec, CallingConvention = callingConvention)]
  805.     public extern static void av_packet_free(AVPacket** pkt);
  806.     [DllImport(avcodec, CallingConvention = callingConvention)]
  807.     public extern static AVCodecContext* avcodec_alloc_context3(AVCodec* codec);
  808.     [DllImport(avcodec, CallingConvention = callingConvention)]
  809.     public extern static int avcodec_open2(AVCodecContext* avctx, AVCodec* codec, AVDictionary** options);
  810.     //[DllImport(avcodec, CallingConvention = callingConvention)]
  811.     //public extern static int avcodec_decode_video2(IntPtr avctx, IntPtr picture, ref int got_picture_ptr, IntPtr avpkt);
  812.     [DllImport(avcodec, CallingConvention = callingConvention)]
  813.     public extern static void avcodec_free_context(AVCodecContext** avctx);
  814.     [DllImport(avcodec, CallingConvention = callingConvention)]
  815.     public extern static int avcodec_send_packet(AVCodecContext* avctx, AVPacket* pkt);
  816.     [DllImport(avcodec, CallingConvention = callingConvention)]
  817.     public extern static int avcodec_receive_frame(AVCodecContext* avctx, AVFrame* frame);
  818.     [DllImport(avutil, CallingConvention = callingConvention)]
  819.     public extern static int av_hwdevice_ctx_create(AVBufferRef** device_ctx, AVHWDeviceType type, string device, AVDictionary* opts, int flags);
  820.     [DllImport(avutil, CallingConvention = callingConvention)]
  821.     public extern static AVBufferRef* av_buffer_ref(AVBufferRef* buf);
  822.     [DllImport(avutil, CallingConvention = callingConvention)]
  823.     public extern static void av_buffer_unref(AVBufferRef** buf);
  824.     [DllImport(avutil, CallingConvention = callingConvention)]
  825.     public extern static AVFrame* av_frame_alloc();
  826.     [DllImport(avutil, CallingConvention = callingConvention)]
  827.     public extern static void av_frame_free(AVFrame** frame);
  828.     [DllImport(avutil, CallingConvention = callingConvention)]
  829.     public extern static void av_log_set_level(int level);
  830.     [DllImport(avutil, CallingConvention = callingConvention)]
  831.     public extern static int av_dict_set_int(AVDictionary** pm, string key, long value, int flags);
  832.     [DllImport(avutil, CallingConvention = callingConvention)]
  833.     public extern static void av_dict_free(AVDictionary** m);
  834. }
  835. }

上文中主要有几个地方是知识点,大家做c#的如果需要和底层交互可以了解一下

  • 结构体的使用

      结构体在c#与c/c++基本一致,都是内存连续变量的一种组合方式。与c/c++相同,在c#中,如果我们不知道(或者可以规避,因为结构体可能很复杂,很多无关字段)结构体细节只知道结构体整体大小时,我们可以用Pack=1,SizeConst=来表示一个大小已知的结构体。
  • 指针的使用

      c#中,有两种存储内存地址(指针)的方式,一是使用interop体系中的IntPtr类型(大家可以将其想象成void*),一是在不安全的上下文(unsafe)中使用结构体类型指针(此处不讨论c++类指针)
  • unsafe和fixed使用

      简单来说,有了unsafe你才能用指针;而有了fixed你才能确保指针指向位置不被GC压缩。我们使用fixed达到的效果就是显式跳过了结构体中前部无关数据(参考上文中AVCodecContext等结构体定义),后文中我们还会使用fixed。

  现在我们开始编写解码和播放部分(即我们的具体应用)代码

FFPlayer.cs

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using static MultiPlayer.FFHelper; namespace MultiPlayer

{

public unsafe partial class FFPlayer : UserControl

{

[DllImport("msvcrt", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]

static extern void memcpy(IntPtr dest, IntPtr src, int count); // 用于在解码器和directx间拷贝内存的c函数
    private IntPtr contentPanelHandle;                              // 画面渲染的控件句柄,因为画面渲染时可能出于非UI线程,因此先保存句柄避免CLR报错

    private int lastIWidth, lastIHeight;                            // 上次控件大小,用于在控件大小改变时做出判定重新初始化渲染上下文
private Rectangle lastCBounds; // 临时变量,存储上次控件区域(屏幕坐标)
private Rectangle lastVRect; // 临时变量,存储上次解码出的图像大小
private Device device; // 当使用软解时,这个变量生效,它是IDirect3Device9*对象,用于绘制YUV
private Surface surface; // 当使用软解时,这个变量生效,它是IDirect3Surface9*对象,用于接受解码后的YUV数据
AVPixelFormat lastFmt; // 上次解码出的图像数据类型,这个理论上不会变 AVCodec* codec; // ffmpeg的解码器
AVCodecContext* ctx; // ffmpeg的解码上下文
AVBufferRef* hw_ctx; // ffmpeg的解码器硬件加速上下文,作为ctx的扩展存在
AVPacket* avpkt; // ffmpeg的数据包,用于封送待解码数据
IntPtr nalData; // 一块预分配内存,作为avpkt中真正存储数据的内存地址
AVFrame* frame; // ffmpeg的已解码帧,用于回传解码后的图像 private volatile bool _released = false; // 资源释放标识,与锁配合使用避免重复释放资源(由于底层是c/c++,多线程下double free会导致程序崩溃)
private object _codecLocker = new object(); // 锁,用于多线程下的互斥 static FFPlayer()
{
avcodec_register_all(); // 静态块中注册ffmpeg解码器
} public FFPlayer()
{
InitializeComponent(); // 过程中,下列对象只需初始化一次
frame = av_frame_alloc();
avpkt = av_packet_alloc();
av_init_packet(avpkt);
nalData = Marshal.AllocHGlobal(1024 * 1024);
codec = avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
avpkt->data = (void*)nalData;
} ~FFPlayer()
{
// 过程中,下列对象只需释放一次
if (null != frame)
fixed (AVFrame** LPframe = &frame)
av_frame_free(LPframe);
if (null != avpkt)
fixed (AVPacket** LPpkt = &avpkt)
av_packet_free(LPpkt);
if (default != nalData)
Marshal.FreeHGlobal(nalData);
} // 释放资源
// 此函数并非表示“终止”,更多的是表示“改变”和“重置”,实际上对此函数的调用更多的是发生在界面大小发生变化时和网络掉包导致硬解异常时
private void Releases()
{
// 过程中,下列对象会重复创建和销毁多次
lock (_codecLocker)
{
if (_released) return;
if (null != ctx)
fixed (AVCodecContext** LPctx = &ctx)
avcodec_free_context(LPctx);
if (null != hw_ctx)
fixed (AVBufferRef** LPhw_ctx = &hw_ctx)
av_buffer_unref(LPhw_ctx);
// (PS:device和surface我们将其置为null,让GC帮我们调用Finalize,它则会自行释放资源)
surface = null;
device = null;
lastFmt = AVPixelFormat.AV_PIX_FMT_NONE;
_released = true;
}
} // Load事件中保存控件句柄
private void FFPlayer_Load(object sender, EventArgs e)
{
contentPanelHandle = Handle; // 这个句柄也可以是你控件内真正要渲染画面的句柄
lastCBounds = ClientRectangle; // 同理,区域也不一定是自身显示区域
} // 解码函数,由外部调用,送一一个分片好的nal
public void H264Received(byte[] nal)
{
lock (_codecLocker)
{
// 判断界面大小更改了,先重置一波
// (因为DirectX中界面大小改变是一件大事,没得法绕过,只能推倒从来)
// 如果你的显示控件不是当前控件本身,此处需要做修改
if (!ClientRectangle.Equals(lastCBounds))
{
lastCBounds = ClientRectangle;
Releases();
} if (null == ctx)
{
// 第一次接收到待解码数据时初始化一个解码器上下文
ctx = avcodec_alloc_context3(codec);
if (null == ctx)
{
return;
}
// 通过参数传递控件句柄给硬件加速上下文
AVDictionary* dic;
av_dict_set_int(&dic, "hWnd", contentPanelHandle.ToInt64(), 0);
fixed (AVBufferRef** LPhw_ctx = &hw_ctx)
{
if (av_hwdevice_ctx_create(LPhw_ctx, AVHWDeviceType.AV_HWDEVICE_TYPE_DXVA2,
null, dic, 0) >= 0)
{
ctx->hw_frames_ctx = av_buffer_ref(hw_ctx);
}
}
av_dict_free(&dic);
ctx->hw_frames_ctx = av_buffer_ref(hw_ctx);
if (avcodec_open2(ctx, codec, null) < 0)
{
fixed (AVCodecContext** LPctx = &ctx)
avcodec_free_context(LPctx);
fixed (AVBufferRef** LPhw_ctx = &hw_ctx)
av_buffer_unref(LPhw_ctx);
return;
}
}
_released = false; // 开始解码
Marshal.Copy(nal, 0, nalData, nal.Length);
avpkt->size = nal.Length;
if (avcodec_send_packet(ctx, avpkt) < 0)
{
Releases(); return; // 如果程序走到了这里,一般是因为网络掉包导致nal数据不连续,没办法, 推倒从来
}
receive_frame:
int err = avcodec_receive_frame(ctx, frame);
if (err == -11) return; // EAGAIN
if (err < 0)
{
Releases(); return; // 同上,一般这里很少出错,但一旦发生,只能推倒从来
} // 尝试播放一帧画面
AVFrame s_frame = *frame;
// 这里由于我无论如何都要加速,而一般显卡最兼容的是yv12格式,因此我只对dxva2和420p做了处理,如果你的h264解出来不是这些,我建议转成rgb(那你就需要编译和使用swscale模块了)
if (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) return;
try
{
int width = s_frame.width;
int height = s_frame.height;
if (lastIWidth != width || lastIHeight != height || lastFmt != s_frame.format) // 这个if判定的是第一次尝试渲染,因为一般码流的宽高和格式不会变
{
if (s_frame.format != AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
{
// 假如硬解不成功(例如h264是baseline的,ffmpeg新版不支持baseline的dxva2硬解)
// 我们就尝试用directx渲染yuv,至少省去yuv转rgb,可以略微节省一丢丢cpu
PresentParameters pp = new PresentParameters();
pp.Windowed = true;
pp.SwapEffect = SwapEffect.Discard;
pp.BackBufferCount = 0;
pp.DeviceWindowHandle = contentPanelHandle;
pp.BackBufferFormat = Manager.Adapters.Default.CurrentDisplayMode.Format;
pp.EnableAutoDepthStencil = false;
pp.PresentFlag = PresentFlag.Video;
pp.FullScreenRefreshRateInHz = 0;//D3DPRESENT_RATE_DEFAULT
pp.PresentationInterval = 0;//D3DPRESENT_INTERVAL_DEFAULT
Caps caps = Manager.GetDeviceCaps(Manager.Adapters.Default.Adapter, DeviceType.Hardware);
CreateFlags behaviorFlas = CreateFlags.MultiThreaded | CreateFlags.FpuPreserve;
if (caps.DeviceCaps.SupportsHardwareTransformAndLight)
{
behaviorFlas |= CreateFlags.HardwareVertexProcessing;
}
else
{
behaviorFlas |= CreateFlags.SoftwareVertexProcessing;
}
device = new Device(Manager.Adapters.Default.Adapter, DeviceType.Hardware, contentPanelHandle, behaviorFlas, pp);
//(Format)842094158;//nv12
surface = device.CreateOffscreenPlainSurface(width, height, (Format)842094169, Pool.Default);//yv12,显卡兼容性最好的格式
}
lastIWidth = width;
lastIHeight = height;
lastVRect = new Rectangle(0, 0, lastIWidth, lastIHeight);
lastFmt = s_frame.format;
}
if (lastFmt != AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
{
// 如果硬解失败,我们还需要把yuv拷贝到surface
//ffmpeg没有yv12,只有i420,而一般显卡又支持的是yv12,因此下文中uv分量是反向的
int stride;
var gs = surface.LockRectangle(LockFlags.DoNotWait, out stride);
if (gs == null) return;
for (int i = 0; i < lastIHeight; i++)
{
memcpy(gs.InternalData + i * stride, s_frame.data1 + i * s_frame.linesize1, lastIWidth);
}
for (int i = 0; i < lastIHeight / 2; i++)
{
memcpy(gs.InternalData + stride * lastIHeight + i * stride / 2, s_frame.data3 + i * s_frame.linesize3, lastIWidth / 2);
}
for (int i = 0; i < lastIHeight / 2; i++)
{
memcpy(gs.InternalData + stride * lastIHeight + stride * lastIHeight / 4 + i * stride / 2, s_frame.data2 + i * s_frame.linesize2, lastIWidth / 2);
}
surface.UnlockRectangle();
} // 下面的代码开始烧脑了,如果是dxva2硬解出来的图像数据,则图像数据本身就是一个surface,并且它就绑定了device
// 因此我们可以直接用它,如果是x264软解出来的yuv,则我们需要用上文创建的device和surface搞事情
Surface _surface = lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD ? new Surface(s_frame.data4) : surface;
if (lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD)
GC.SuppressFinalize(_surface);// 这一句代码是点睛之笔,如果不加,程序一会儿就崩溃了,熟悉GC和DX的童鞋估计一下就能看出门道;整篇代码,就这句折腾了我好几天,其他都好说
Device _device = lastFmt == AVPixelFormat.AV_PIX_FMT_DXVA2_VLD ? _surface.Device : device;
_device.Clear(ClearFlags.Target, Color.Black, 1, 0);
_device.BeginScene();
Surface backBuffer = _device.GetBackBuffer(0, 0, BackBufferType.Mono);
_device.StretchRectangle(_surface, lastVRect, backBuffer, lastCBounds, TextureFilter.Linear);
_device.EndScene();
_device.Present();
backBuffer.Dispose();
}
catch (DirectXException ex)
{
StringBuilder msg = new StringBuilder();
msg.Append("*************************************** \n");
msg.AppendFormat(" 异常发生时间: {0} \n", DateTime.Now);
msg.AppendFormat(" 导致当前异常的 Exception 实例: {0} \n", ex.InnerException);
msg.AppendFormat(" 导致异常的应用程序或对象的名称: {0} \n", ex.Source);
msg.AppendFormat(" 引发异常的方法: {0} \n", ex.TargetSite);
msg.AppendFormat(" 异常堆栈信息: {0} \n", ex.StackTrace);
msg.AppendFormat(" 异常消息: {0} \n", ex.Message);
msg.Append("***************************************");
Console.WriteLine(msg);
Releases();
return;
}
goto receive_frame; // 尝试解出第二幅画面(实际上不行,因为我们约定了单次传入nal是一个,当然,代码是可以改的)
}
} // 外部调用停止解码以显示释放资源
public void Stop()
{
Releases();
}
}

}

下面讲解代码最主要的三个部分
- 初始化ffmpeg
  主要在静态块和构造函数中,过程中我没有将AVPacket和AVFrame局部化,很多网上的代码包括官方代码都是局部化这两个对象。我对此持保留意见(等我程序报错了再说)
- 将收到的数据送入ffmpeg解码并将拿到的数据进行展示
  这里值得一提的是get_format,官方有一个示例,下图

它有一个get_format过程(详见215行和63行),我没有采用。这里给大家解释一下原因:

这个get_format的作用是ffmpeg给你提供了多个解码器让你来选一个,而且它内部有一个机制,如果你第一次选的解码器不生效(初始化错误等),它会调用get_format第二次(第三次。。。)让你再选一个,而我们首先认定了要用dxva2的硬件解码器,其次,如果dxva2初始化错误,ffmpeg内部会自动降级为内置264软解,因此我们无需多此一举。

  • 发现解码和播放过程中出现异常的解决办法

    • 不支持硬解

      代码中已经做出了一部分兼容,因为baseline的判定必须解出sps/pps才能知道,因此这个错误可能会延迟爆出(不过不用担心,如果此时报错,ffmpeg会自动降级为软解)
    • 窗体大小改变

      基于DirectX中设备后台缓冲的宽高无法动态重设,我们只能在控件大小改变时推倒重来。如若不然,你绘制的画面会进行意向不到的缩放
    • 网络掉包导致硬件解码器错误

      见代码
    • 其他directx底层异常

      代码中我加了一个try-catch,捕获的异常类型是DirectXException,在c/c++中,我们一般是调用完函数后会得到一个HRESULT,并通过FAILED宏判定他,而这个步骤在c#自动帮我们做了,取而代之的是一个throw DirectXException过程,我们通过try-catch进行可能的异常处理(实际上还是推倒重来)

  番外篇:C#对DiretX调用的封装

上文中我们使用DirectX的方式看起来即非COM组件,又非C-DLL的P/Invoke,难道DirectX真有托管代码?

答案是否定的,C#的dll当然也是调用系统的d3d9.dll。不过我们有必要一探究竟,因为这里面有一个隐藏副本

首先请大家准备好ildasm和visual studio,我们打开visual studio,创建一个c++工程(类型随意),然后新建一个cpp文件,然后填入下面的代码



如果你能执行,你会发现输出是136(0x88);然后我们使用ildasm找到StrechRectangle的代码



你会发现也有一个+0x88的过程,那么其实道理就很容易懂了,c#通过calli(CLR指令)可以执行内存call,而得益于微软com组件的函数表偏移量约定,我们可以通过头文件知道函数对于对象指针的偏移(其实就是一个简单的ThisCall)。具体细节大家查阅d3d9.h和calli的网络文章即可。

使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流的更多相关文章

  1. ffmpeg实现dxva2硬件加速

    这几天在做dxva2硬件加速,找不到什么资料,翻译了一下微软的两篇相关文档.这是第二篇,记录用ffmpeg实现dxva2. 第一篇翻译的Direct3D device manager,链接:http: ...

  2. 【视频开发】ffmpeg实现dxva2硬件加速

    这几天在做dxva2硬件加速,找不到什么资料,翻译了一下微软的两篇相关文档.这是第二篇,记录用ffmpeg实现dxva2. 第一篇翻译的Direct3D device manager,链接:http: ...

  3. 基于FFmpeg的Dxva2硬解码及Direct3D显示(一)

    目录 前言 名词解释 代码实现逻辑 前言 关于视频软解码的资料网上比较多了,但是关于硬解可供参考的资料非常之有限,虽然总得来说软解和硬解的基本逻辑一样,但是实现细节上的差别还是比较多的.虽然目前功能已 ...

  4. 基于FFmpeg的Dxva2硬解码及Direct3D显示(四)

    初始化硬解码上下文 目录 初始化硬解码上下文 创建解码数据缓冲区 创建IDirectXVideoDecoder视频解码器 设置硬解码上下文 解码回调函数 创建解码数据缓冲区 这一步为了得到 LPDIR ...

  5. 基于FFmpeg的Dxva2硬解码及Direct3D显示(五)

    解码及显示 目录 解码及显示 解码 显示 资源清理 解码 循环读取视频帧 AVPacket packet = { 0 }; while (av_read_frame(m_pFmtCtx, &p ...

  6. 基于FFmpeg的Dxva2硬解码及Direct3D显示(三)

    初始化Direct3D 目录 初始化Direct3D 创建Direct3D物理设备对象实例 创建Direct3D渲染设备实例 创建Direct3D视频解码服务 Direct3D渲染可以通过Surfac ...

  7. 基于FFmpeg的Dxva2硬解码及Direct3D显示(二)

    解析视频源 目录 解析视频源 获取视频流 解析视频流 说明:这篇博文分为"获取视频流"和"解析视频流"两个部分,使用的是FFmpeg4.1的版本,与网上流传的低 ...

  8. 利用ffmpeg进行视频软解播放

    前段时间,公司的一个项目需要一个rtsp的播放库,原本打算直接用vlc播放的,但我觉得vlc太庞大了,很多功能没必要,还不如用ffmpeg+d3d简单的实现一个库,因此就有了今天讲的这个东西.一个解码 ...

  9. FFmpeg新版本(2016年10月份以后) 支持硬件解码

    FFmpeg provides a subsystem for hardware acceleration. Hardware acceleration allows to use specific ...

随机推荐

  1. java学习3-流程控制与数组

    1.顺序结构 2.分支结构 3.循环结构 4.控制循环结构 break continue return 5.数组

  2. MongoDB实现问卷/考试设计

    MongoDB的特点 MongoDB是一个面向文档存储的数据库.在MongoDB中,一条记录叫做document(文档),由类似于JSON结构的键值对组成. 由于类似于MongoDB直接存储JSON的 ...

  3. Catalan数的理解

    Catalan数的理解 f(0)=1 f(1)=1 f(2)=2 f(3)=5 f(4)=14 f(5)=42     f(2)=f(1)+f(1)   f(3)=f(2)+f(1)*f(1)*f(2 ...

  4. (一) kinect概述

    Kinect可以进行身体节点定位,姿势定位,人脸识别等功能,在此先做简单介绍,后续主要介绍插件的应用,毕竟自己开发识别过程太消耗时间. (注1:Kinect官方虽然提供了Unity的APi,但是方便起 ...

  5. Java多线程(十五):CountDownLatch,Semaphore,Exchanger,CyclicBarrier,Callable和Future

    CountDownLatch CountDownLatch用来使一个线程或多个线程等待到其他线程完成.CountDownLatch有个初始值count,await方法会阻塞线程,直到通过countDo ...

  6. Apache中Cookie长度的设置 414 request-uri too large apache

    起因: 今天在调试Ucenter的同步登陆和同步登出的过程中,浏览器突然出现以下错误提示: Your browser sent a request that this server could not ...

  7. Net Core中 使用Middleware 实现反向代理

    有这样的一个需求,我们要拦截某些特定的请求,并将它们重新定向到另一台服务器中,然而客户端并不知情. 在NetCore中我们可以用中间件来实现, 首先创建项目: 我这里只有2.1 Version 的 添 ...

  8. 学习笔记66_DBSCAN聚类算法

  9. Oracle“ORA-00911: 无效字符”解决方式

    在工作中碰到ORA-00911:无效字符的问题, 代码如下: <select id="querySendMsg" parameterType="map" ...

  10. NOIP模拟测试33

    这次考试很失败. T1sb题,40分钟切了,当我打完对拍全过去上厕所的时候,碰到了yxm. yxm:我又自闭了,没有一点进展. 我:…… yxm:你会做几个? 我(思考再三):T1只会暴力. (我这么 ...