1. 程式人生 > >手機直播系統偶爾會需要到的:Windows 下視頻采集技術

手機直播系統偶爾會需要到的:Windows 下視頻采集技術

desktop ida ssh top 種類 設置 其中 activate map

Windows下視頻采集的方法

在 Windows 下主要有兩種方法來采集視頻: 一種是通過 Media Foundation,另一種是通過 DirectShow。

Meida Foundation 是 Windows 從 vista 之後推出的一套全新的 多媒體SDK,簡單方便,從 Win7 開始成熟起來。

另一種是 DirectShow,它主要用於 win7 之前的采集視頻。使用 DirectShow 編寫代碼比較麻煩,主要是因為 Windows 工程師按照邏輯電路的思維方式設計了 DirectsShow 的開發接口,引入了什麽 filter, pin之類的概念。這些老掉牙的東西現在估計沒幾個人能搞明白,除非你是從那個時代過來的,哈哈。

這也解釋了為啥現在很少有人學習 Windows 程序開發了,就是因為跟不上時代。你看人家 Android/iOS做視頻采集多簡單,你整的這麽麻煩,誰還願意學!

Media Foundation的一些概念

DirectShow 方案我們放到以後再分析,今天我們主要講下 MediaFoundation 如何進行視頻采集。

在講之前,我們先要補充一些基本概念。這些概念大家可以從Media Foundation Programming Guide 找到。下面的文字基本是翻譯的 Windows 的官方文檔。

MF(MediaFoundation)的整體結構圖如下:

技術分享圖片

MF 提供了兩種不同的編程模型。第一種是上圖的左半部分,媒體數據通過端到端的管道傳遞。Application首先初始化管道,然後調用相應方法控制管道中的流。第二種如上圖的右半部分,Application可以從 Source Reader拉數據,也可以向 Sink Writer 推數據。這種模型對於處理數據非常有用。

Primitives 和 Platfrom

圖底部的 Primitives 是一些輔助API:

  • Attributes: 相當於一個 Map, 由 key/value 組成。
  • Media Type: 描述媒體數據流的格式。
  • Media Buffers: 存放一段媒體數據。
  • Media Samples: 存放 Media Buffers 的容器,相當於一個 Buffter List。

MF Platform 提供了一些核心功能的API。例如異步調用、工作隊列。

Media Pipeline

Media Pipeline 包括三種類型對象:Media Sources、MFTs(Media Foundation Transfors)、Media Sink。

  • Media Sources: 將數據引入到管道裏。數據可以來自本地文件,網絡流或都是硬件設備。
  • MFTs: 處理流數據。在 MFTs 裏實現了編解碼器。
  • Media Sink: 消費數據。顯示視頻到顯示屏上,播放聲音或寫數據到媒體文件。

Media Session 通過管道控制數據流。如質量控制,音頻/視頻同步,格式的改變。

Source Reader 和 Sink Writer

Source Reader 和 Sink Writer提供了使用 Media Foundation 的另一種方法(相較於 media source, transforms, media sink)。

  • Source Reader 控制著 media source 和 多個解碼器。
  • Sink Writer 控制著 media sink 和 多個編碼器。

你可以使用 Source Reader 從 media source 獲取到壓縮或未壓縮的數據,並使用 Sinker Writer 編碼數據並發送給 media sink。

下面我們就來看看 MF 是如何采集視頻數據的。

采集視頻數據

通過上面的介紹,我們基本可以知道 MF 采用 從源采集數據,編解碼,輸出渲染這種架構來處理多媒體。這種方式通俗易懂,使用起來非常方便。

MF采集視頻的基本步驟

MF采集數據使用的是架構中的第二種編程模型,其步驟如下:

  • 初始化 COM 組件。
  • 獲取視頻設備列表。
  • 激活某個視頻設備,獲取該設備的 Media Source。
  • 根據請求命令和 Media Source 創建 Source Reader。
  • 為 Source Reader 設置 Media Type。
  • 通過 Source Reader 從設備中讀取 Media Type 格式的視頻數據。

以上就是 MF 從視頻設備采集數所的基本步驟,下面我們來詳細介紹每一步。

詳細分析

由於每一步的代碼都實分簡單,我這裏就不做過多的文字描述了,通過下面的代碼及其註釋大家很容易理解其中的每一步。

初始化 COM 組件並啟動 MF

CoInitializeEx(NULL, COINIT_APARTMENTTHREAD | COINIT_DISABLE_OLEDDE)
MFStartup(MF_VERSION)

獲取所有的視頻設備

IMFAttributes *videoCmd = NULL; 
IMFActivate **videoDevices = NULL;
UINT32 videoDeviceCount = 0;

//設置獲取視頻設備的命令
MFCreateAttributes(videoCmd, 1/*表示只分配一項*/);
videoCmd->setGUID(
                MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,  //key
                MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); //value
//獲取視頻設備列表  
MFEnumDeviceSources(
                videoCmd,
                &videoDevices, //這裏是設備列表
                &videoDeviceCount); //這裏存放的是設備的個數

激活某個視頻設備

IMFMediaSource *mediaSource = NULL;

//激活第一個視頻設備,並為該設置備生成邏輯上的媒體源(Media Source)
videoDevices[0]->ActivateObject(IID_PPV_ARGS(&mediaSource));

創建 Source Reader

IMFSourceReader *soureReader = NULL;

//通過媒體源和請求命令,可以獲取source reader。(第二種開發模型)
MFCreateSourceReaderFromMediaSource(
                mediaSource,
                videoCmd,
                &sourceReader);

設置 Media Type

IMFMediaType *mediaType = NULL;

MFCreateMediaType(&mediaType);
//設置媒體為視頻
mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
//YUV格式為 I420
mediaType->SetGUID(MF_MT_SUBTYPE, WMMEDIASUBTYPE_I420); 
//每個視頻幀的大小為 640 * 480
MFSetAttributeSize(mediaType, MF_MT_FRAME_SIZE, 640, 480);
sourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
                         NULL,
                         mediaType);

讀取數據

IMFSample *sample = NULL;
DWORD index, flags;
LONGLONG llVideoTs;

while(runing){
    sourceReader->ReadSample(
                    MF_SOURCE_READER_FIRST_VIDEO_STREAM,
                    0,
                    &index, //實際流的index
                    &flags, //staus flags
                    &llVideoTs, //時間戳
                    &sample); //存放采集到的視頻數據
}

通過上面簡單的幾步,就可以輕松的從視頻設備裏取到視頻數據了。MF相對於 DirectShow真是簡單太多了。

上面介紹的是使用同步方式使用MF采集視頻數據,MF還提供了效率更高的異步方式獲取視頻數據,有興趣的朋友可以以本篇文章為基礎去學習它的異步方式。

小結

今天向大家介紹了在 Windows下使用 MF 如何采集視頻的方法。通過以下 6 步即可做到:

  • 初始化 COM 組件。
  • 獲取視頻設備列表。
  • 激活某個視頻設備,獲取該設備的 Media Source。
  • 根據請求命令和 Media Source 創建 Source Reader。
  • 為 Source Reader 設置 Media Type。
  • 通過 Source Reader 從設備中讀取 Media Type 格式的視頻數據。

另外, MF 的采集方案只適用於 Win7 以後的系統,對於之前的系統還是要使用 DirectShow 方案。我也會在後面再為大家介紹如何使用 DirectShow 采集視頻。

手機直播系統偶爾會需要到的:Windows 下視頻采集技術