寫在前面
我是個講文明的人…… 不過有的時候實在忍不住了也要吐槽幾句:
1. 我真是跟不上時代,到現在了還在研究 Windows 應用開發…… 咳;
2. DirectShow 是傻X!我只是想要獲取 Camera 裸數據,尼瑪卻要讓我學習神馬各種 .ax, filter, graph... 相關資料少、又晦澀;
3. 在此祝願 Windows XP 及其之前的版本早點退出歷史舞台,這樣 DirectShow 就不是必須的了!
音視頻采集
Windows 7 以后, Media Foundation 支持音視頻采集。
視頻采集設備必須支持 UVC 1.1 驅動。
音頻采集設備通過 Windows Audio Session API (WASAPI) 來支持。
采集設備在 Media Foundation 中表現為 Media Source 對象,暴露出 IMFMediaSource 接口。但是一般情況下應用程序不會直接用這個接口,而會使用更高層的API,比如 Source Reader IMFSourceReader 來控制采集設備。
列舉設備並設置設備
1. 調用 MFCreateAttributes 函數創建屬性庫;
2. 設置 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 屬性(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID 或 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
3. 調用 MFEnumDeviceSources 函數就會得到一組 IMFActivate 指針。每個指針指向一個設備;
4. 調用 GetAllocatedString 函數 可以獲取設備名稱,其中,
4.1. 用 GetAllocatedString 函數 的 MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME 參數可以獲取顯示名稱
4.2. 用 GetAllocatedString 函數 的 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK 參數可以獲取視頻采集設備的物理名稱,名稱是唯一的,但不好閱讀
4.3. 用 GetAllocatedString 函數 的 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID 參數可以獲取音頻采集設備的物理名稱,名稱是唯一的,但不好閱讀
5. 調用 IMFActivate::ActivateObject 或 MFCreateDeviceSource 方法來創建一個可用的 Media Source 對象實例。對於具體的一個采集設備(創建好了的 Media Source),獲取設備所支持的格式,並設置采集格式:
5.1. 調用 IMFMediaSource::CreatePresentationDescriptor 獲取媒體源(Media Source)的表現描述符(presentation descriptor)
5.2. 調用 IMFPresentationDescriptor::GetStreamDescriptorByIndex 獲取視頻流的流描述符(Stream Descriptor)
5.3. 調用 IMFStreamDescriptor::GetMediaTypeHandler 獲取流描述符的媒體類型句柄(IMFMediaTypeHandler)
5.4. 調用 IMFMediaTypeHandler:: 的 GetMediaTypeCount 和 GetMediaTypeByIndex 來獲取每一條目的格式(IMFMediaType,每一條目的格式包含許多屬性,如寬高、采樣格式、幀率),另外,教程還有一些實用函數,用於打印 IMFAttributes 。
6. 最后, IMFMediaTypeHandler::SetCurrentMediaType 設置指定條目的格式(IMFMediaType)。如果要修改 IMFMediaType 的某個屬性(比如 Frame Rate)的話,就調用 IMFMediaType::SetItem 來設置具體的屬性(比如 MF_MT_FRAME_RATE)。具體要看代碼來理解。
通過 Source Reader 讀取媒體
當獲取到設備以后,一般用 Source Reader 來獲取媒體
1. 調用 MFCreateSourceReaderFromMediaSource 關聯 IMFMediaSource 和 IMFSourceReader;
2. 調用 IMFSourceReader::GetNativeMediaType 獲取各種 Source 提供的媒體類型;
3. 調用 IMFSourceReader::SetCurrentMediaType 設置想要的媒體類型;
4. 調用 IMFSourceReader::ReadSample 來獲取音頻采樣或視頻采樣(視頻幀)。如果想要使用異步方式來 ReadSample,則需要設置一下 MF_SOURCE_READER_ASYNC_CALLBACK 。
相關文檔:
https://msdn.microsoft.com/en-us/library/dd743690.aspx
https://msdn.microsoft.com/en-us/library/dd317912.aspx
https://msdn.microsoft.com/en-us/library/dd940326.aspx
https://msdn.microsoft.com/en-us/library/dd940328.aspx (設備使用時中途丟失的處理,待學)
https://msdn.microsoft.com/en-us/library/ee663602.aspx
https://msdn.microsoft.com/en-us/library/aa473818.aspx (媒體類型)
其他功能
音視頻采集 + 編碼(Transcode): https://msdn.microsoft.com/en-us/library/ff485863.aspx
播放媒體文件:https://msdn.microsoft.com/en-us/library/ms703190.aspx
代碼地址
在 Windows SDK 的 Samples\multimedia\mediafoundation 目錄中