程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> FFmpegInterop 庫在 Windows 10 應用中的編譯使用

FFmpegInterop 庫在 Windows 10 應用中的編譯使用

編輯:關於.NET

FFmpegInterop 簡介

FFmpegInterop 是微軟推出的封裝 FFmpeg 的一個開源庫,旨在方便在 Windows 10、Windows 8.1 以及 Windows Phone 8.1 應用中使用 FFmpeg 進行媒體內容播放。FFmpegInterop 實現了一個 MediaStreamSource 以便通過 FFmpeg 對媒體內容進行解碼後輸送到 Windows 多媒體管線進行播放。

FFmpegInterop 項目托管於 Github,項目地址:FFmpegInterop 。

 

編譯步驟

FFmpegInterop 是對 FFmpeg 的封裝,依賴 FFmpeg 庫本身。要使用 FFmpegInterop 需要首先手動編譯 FFmpeg 和 FFmpegInterop 庫。

獲取文件到本地

使用 git 命令或任意 git 工具將 FFmpegInterop 項目文件 clone 到本地:

git clone --recursive git://github.com/microsoft/FFmpegInterop.git

獲取最新的 FFmpeg 代碼:

 git clone git://github.com/microsoft/FFmpegInterop.git
 cd FFmpegInterop
 git clone git://source.ffmpeg.org/ffmpeg.git

FFmpegInterop 的 github 倉庫 中鏈接的是 commit 620197d 的 FFmpeg 代碼。不同版本的 FFmpeg 編譯後實際表現可能有所不同。

進行以上操作後,你的本地目錄結構應該同以下結構相同:

FFmpegInterop\
├ ffmpeg\ - FFmpeg 庫代碼目錄
├ FFmpegInterop\ - FFmpegInterop WinRT 組件代碼目錄
├ Samples\ - 使用 C++, C# 以及 JavaScript 分別實現的例子
├ Tests\ - FFmpegInterop 的單元測試
├ BuildFFmpeg.bat - 用於編譯 FFmpeg 庫的批處理文件
├ FFmpegConfig.sh - FFmpeg 配置腳本
├ FFmpegWin8.1.sln - 用於 Windows 8.1 Windows Phone 8.1 開發的 Visual Studio 2013 解決方案
├ FFmpegWin10.sln - 用於 Windows 10 開發的 Visual Studio 2015 解決方案
├ LICENSE
└ README.md

編譯 FFmpeg

編譯 FFmpegInterop 之前,我們首先需要編譯 FFmpeg 本體。編譯 FFmpeg 需要先准備特定的編譯環境。

Visual Studio

對於 Windows 8.1,要求使用 Visual Studio 2013 Update 3 RTM 或更新的版本。 對於 Windows 10,要求使用 Visual Studio 2015。

安裝配置 MSYS2

MSYS2 是一個用於 Windows 平台的 GNU 編譯環境套件。要編譯 FFmpeg,必須安裝使用 MSYS2。

MSYS2 下載地址:http://msys2.github.io/

下載頁面提供了 x86 和 x64 兩種架構對應的版本,選擇當前計算機對應版本下載即可。下載啟動安裝程序後選擇一個安裝路徑,注意盡量選擇類似 C:\msys32 這樣由字母數字構成的簡單短路徑,路徑中不能包含中文、特殊字符、空格等。安裝完成後立即運行 MSYS2。

啟動 MSYS2 後,需要更新 MSYS2 提供的 GNU 環境,在 MSYS2 的終端中輸入命令 update-core 進行更新。更新完畢後,關閉 MSYS2 再通過開始菜單重啟 MSYS2。重啟後,再輸入 pacman -Su 同步 MSYS2 環境的包數據庫。

有關 MSYS2 安裝使用的更多內容,可參閱 MSYS2 Wiki

安裝配置 YASM

YASM 一個完全重寫 NASM 編譯器的匯編語言編譯器,也是編譯 FFmpeg 的必要工具之一。有關 YASM 的更多信息,可以訪問其官網 yasm.tortall.net。

YASM 下載地址:http://yasm.tortall.net/Download.html

截至目前 YASM 的最新版本為 2014 年 8 月 10 日發布的 1.3.0 版。注意 YASM 在其下載頁面上列舉了多個不同的版本可供下載:

  • Source .tar.gz (源代碼)
  • Win32 VS2010 .zip (用於 VS2010+ 和 32 位 Windows)
  • Win64 VS2010 .zip (用於 VS2010+ 和 64 位 Windows)
  • Win32 .exe (32 位 Windows 通用)
  • Win64 .exe (64 位 Windows 通用)
  • CygWin32 .exe (用於 CygWin)
  • DOS .exe (用於純 DOS 或 DJGPP)

注意我們需要的是上述列表中加粗的兩個通用版本。根據自己使用計算器的架構選擇對應的通用版本下載即可。下載後,將下載回來的 yasm-1.3.0-win64.exe 改名為 yaml.exe,並放置於 MSYS2 安裝目錄中。例如,MSYS2 安裝在 C:\msys64,則將 yaml.exe 放置到c:\msys64\usr\bin\ 中。

安裝配置 gas-preprocessor

gas-preprocessor 是用於編譯 FFmpeg 的 perl 預處理腳本。

gas-preprocessor 下載地址:https://github.com/FFmpeg/gas-preprocessor

下載 gas-preprocessor.pl 文件後放置於 MSYS2 安裝目錄中。例如,MSYS2 安裝在 C:\msys64,則將 gas-preprocessor.pl 放置到 c:\msys64\usr\bin\ 中。

驗證 FFmpeg 編譯環境

進行以上步驟之後,編譯 FFmpeg 的環境已經基本准備就緒。我們還需要對環境進行一下驗證,以保證環境確實准備完畢能夠順利進行編譯。

通過開始菜單找到 Visual Studio 2013 或 Visual Studio 2015 菜單組,在其中找到 VS2015 x86 ARM Cross Tools Command Prompt 啟動。注意,菜單組中可能存在多個名稱類似的命令行快捷方式,需要選擇 x86 ARM Cross Tools。 啟動 VS2015 x86 ARM Cross Tools Command Prompt 後,在命令行中定位到 MSYS2 的安裝目錄,啟動 MSYS2:C:\msys64\msys2_shell.bat。(這樣通過 VS 提供的命令行啟動 MSYS2 的目的在於讓 MSYS2 能夠檢測到部分由 VS 提供的編譯工具。)

在啟動的 MSYS2 終端中分別運行一下命令觀察各便於工具組件是否被正確找到:

$ which cl
/c/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/x86_ARM/cl

$ which link
/c/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/x86_ARM/link

$ which armasm
/c/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/x86_ARM/armasm

$ which yasm
/usr/bin/yasm

$ which cpp
/usr/bin/cpp

$ which gas-preprocessor.pl
/usr/bin/gas-preprocessor.pl

如果所有組件均在指定位置被找到,則表示 FFmpeg 編譯環境已經准備就緒,可以進入下一步驟編譯 FFmpeg。如果沒有通過 VS 提供的 x86 ARM Cross Tools 命令行啟動 MSYS2,則 cl, link, armasam 這幾個組件有可能定位不到。也可以選擇將 c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_ARM 這個目錄加入系統的環境變量。

編譯 FFmpeg

在 FFmpegInterop 中,微軟已經提供了方便的編譯批處理用於自動編譯 FFmpeg,如果你想手動編譯 FFmpeg,可以參閱 Compile and Use FFmpeg Libraries for Windows Runtime。

FFmpegInterop 項目中提供了一個名為 BuildFFmpeg.bat 的批處理文件,借助該批處理,可以輕松進行 FFmpeg 的編譯工作。BuildFFmpeg.bat 接受兩個可選參數,第一個參數表明目標平台,第二個參數表明目標架構,例如:

BuildFFmpeg.bat win10                     - 為 Windows 10 的 ARM, x64 和 x86 編譯  
BuildFFmpeg.bat phone8.1 ARM              - 為 Windows Phone 8.1 的 ARM 編譯  
BuildFFmpeg.bat win8.1 x86 x64            - 為 Windows 8.1 的 x86 和 x64 編譯  
BuildFFmpeg.bat phone8.1 win10 ARM        - 為 Windows 10 和 Windows Phone 8.1 的 ARM 編譯  
BuildFFmpeg.bat win8.1 phone8.1 win10     - 為 所有平台所有架構編譯  

編譯時間較長,編譯完成後批處理會自動退出。編譯後的輸出的文件位於項目的 ffmpeg/Build/目標平台/架構 目錄內。

編譯 FFmpegInterop

打開 Win 8.1 或 Win 10 對應的 項目解決方案文件。可見到 FFmpegInterop 解決方案整體的結構:

Solution "FFmpegWin10"  
├ FFmpegInterop (Universal Windows, C++)
├ MediaPlayerCPP (Universal Windows, C++)
├ MediaPlayerCS (Universal Windows, C#)
├ MediaPlayerJS (Universal Windows, Javascript)
└ UnitTest

而解決方案的文件目錄結構為

FFmpegInterop-master  
├ FFmpegWin10.sln/ FFmpegWin8.1.sln (Visual Studio Solution)
├ BuildFFmpeg.bat (Build script)
├ FFmpegConfig.sh (Build script)
├ FFmpegInterop (Project folder of FFmpegInterop)
└ Samples (Project folder of sample players)
  ├ SamplesWin10
  └ SamplesWin8.1

需要注意的是,在項目中使用 FFmpegInterop 時需要按照 FFmpegInterop 的文件目錄結構對項目文件進行安放。如果沒有直接使用 FFmpegInterop 提供的項目文件,記得配置 interop 項目對 FFmpeg 的引用:

 

另外 FFmpeg 編譯後是區分 x86, x64, ARM 三種不同目標架構的,不同架構輸出的目錄並不相同,例如面向 ARM 平台的 Windows 10 版本的 FFmpeg 編譯輸出的文件位於 FFmpegInterop-master\ffmpeg\Build\Windows10\ARM 目錄中。在 C# 版的播放器示例項目中,FFmpeg 的幾個 .dll 文件是以鏈接的方式直接從 FFmpeg 的 build 目錄引入項目的,這樣在應用打包時,會將對應架構的 FFmpeg 庫文件自動封入應用包中。

FFmpegInterop 提供的 MediaPlayerCS 項目已經做好了相關配置,如果需要在自己的項目中使用如上文所述的鏈接方式為項目添加 FFmpeg 庫文件,需要手動配置項目文件:

C# 項目

使用文本編輯器(推薦 Sublime Text/Atom,不要使用記事本)或以 Visual Studio 文本模式(只打開文件不打開整個項目)打開項目的 .csproj 文件,找到 <ItemGroup></ItemGroup> 節點,在其中添加以下內容:

<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avcodec-56.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avdevice-56.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avfilter-5.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avformat-56.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avutil-54.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\swresample-1.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\swscale-3.dll" />  

<ItemGroup> 節點代表項目包含的文件組,<Content> 代表項目中的“內容”類型文件。$(SolutionDir) 和 $(PlatformTarget) 均為 Visual Studio 所用生成器可以識別的宏,$(SolutionDir) 代表解決方案目錄;$(PlatformTarget) 代表目標平台。采用以上配置,C# 項目即可引入對應平台的 FFmpeg 庫文件了。項目配置文件全文可參考MediaPlayerCS.csproj 。

Javascript 項目

Javascript 項目與 C# 項目類似,使用文本編輯器(推薦 Sublime Text/Atom,不要使用記事本)或以 Visual Studio 文本模式(只打開文件不打開整個項目)打開項目的 .jsproj 文件,找到 <ItemGroup></ItemGroup> 節點,在其中 <AppxManifest></AppxManifest>節點之後添加以下內容:

<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avcodec-56.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avdevice-56.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avfilter-5.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avformat-56.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avutil-54.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\swresample-1.dll" />  
<Content Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\swscale-3.dll" />  

項目配置文件全文可參考 MediaPlayerJS.jsproj 。

C++ 項目

C++ 項目與 C# 和 Javascript 項目稍有不同,使用文本編輯器(推薦 Sublime Text/Atom,不要使用記事本)或以 Visual Studio 文本模式(只打開文件不打開整個項目)打開項目的 .vcxproj 文件,找到 <ItemGroup></ItemGroup> 節點,在其中 <AppxManifest></AppxManifest> 節點之後添加以下內容:

<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avcodec-56.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  
<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avdevice-56.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  
<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avfilter-5.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  
<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avformat-56.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  
<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\avutil-54.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  
<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\swresample-1.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  
<None Include="$(SolutionDir)ffmpeg\Build\Windows10\$(PlatformTarget)\bin\swscale-3.dll">  
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
  <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</None>  

完整的 C++ 項目配置文件可以參考 MediaPlayerCPP.vcxproj 。

可以看到 FFmpeg 的幾個 .dll 文件名中都有數字,例如 avformat-56.dll,不同版本的 FFmpeg 編譯出來的文件名中這個版本號數字是不一樣的,如果手動獲取了不同版本的 FFmpeg 代碼進行編譯,注意在項目中添加 FFmpeg 的 .dll 時正確填寫文件名。

如果在之前獲取代碼文件到本地的步驟中,你獲取了最新版本的 FFmpeg 代碼,則需要對 FFmpegInterop 項目進行一些改動才能夠順利編譯。

在最新版本的 FFmpeg 代碼中,FFmpegInterop 在 FFmpegReader.cpp 中調用的 av_free_packet 已被棄用,FFmpeg 在 commit ce70f28a1732c74a9cd7fec2d56178750bd6e457 中已經使用 av_packet_unref 替換了 av_free_packet,因此我們需要在 FFmpegReader.cpp 中改為使用 av_packet_unref。相關討論可參見 Build error: avfreepacket deprecated 。

使用 FFmpegInterop

FFmpegInterop 的工作流程是:

  1. 讀取媒體文件流。
  2. 通過 FFmpegInteropMSS.CreateFFmpegInteropMSSFromStream() 方法創建一個 FFmpegInteropObject,並為其傳遞媒體文件流和強制軟解設置。
  3. 調用 FFmpegInteropObject 互操作對象的 GetMediaStreamSource() 方法獲得 MediaStreamSource
  4. 將 MediaStreamSource 設置給 MediaElement(C#) 或 VideoTag(Javascript)進行播放。

FFmpegInteropMSS 中提供了兩個用於創建 FFmpegInteropObject

  1. CreateFFmpegInteropMSSFromStream
  2. CreateFFmpegInteropMSSFromUri

CreateFFmpegInteropMSSFromStream 方法接收三個參數 IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecodestream 即輸入的待播放媒體文件流;forceAudioDecode 用於設置是否強制使用 FFmpeg 對音頻進行軟解;forceVideoDecode 用於設置是否強制使用 FFmpeg 對視頻進行軟解。如果不設置強制使用 FFmpeg 進行軟解,那麼 MediaStreamSource 會把壓縮數據直接送入 MediaElement進行播放,目前只有 mp3、aac 和 H.264 支持硬解播放。

關於 Windows 10 系統本身支持硬解的格式,可以參考 Supported codecs。

除了上述三個參數,CreateFFmpegInteropMSSFromStream 方法還有一個重載接收第四個參數 PropertySet^ ffmpegOptionsffmpegOptions 用於設置 FFmpeg 中 libavformat 庫所使用的訪問資源時要求的協議。所有屬性列表可以參閱 FFmpeg Protocols。

CreateFFmpegInteropMSSFromUri 方法用於播放一個 URI 提供的媒體流,其接收參數為 String^ uri, bool forceAudioDecode, bool forceVideoDecode,並且同樣有一個接收 PropertySet^ ffmpegOptions 參數的重載用於指定協議設置。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved