將影片擷取至 AVI 檔案
[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine和媒體基金會中的 音訊/視訊擷取取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayer、IMFMediaEngine 和 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]
下圖顯示將影片擷取至 AVI 檔案的最簡單圖形。
AVI Mux 濾鏡會從擷取端取得視訊串流,並將其封裝到 AVI 視訊流。 音訊串流也可以連接到 AVI 多工器,在此情況下,多工器會交織這兩個數據流。 檔案寫入器 篩選器會將 AVI 數據流寫入磁碟。
若要建置圖形,請從呼叫 ICaptureGraphBuilder2::SetOutputFileName 方法開始,如下所示:
IBaseFilter *pMux;
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
L"C:\\Example.avi", // File name.
&pMux, // Receives a pointer to the mux.
NULL); // (Optional) Receives a pointer to the file sink.
第一個參數會指定檔案類型, 在此案例中為 AVI。 第二個參數會提供檔名。 若為 AVI,SetOutputFileName 方法會共同建立 AVI Mux 篩選和檔案寫入器篩選,並將其新增至圖形。 它還通過呼叫 IFileSinkFilter::SetFileName 方法,在檔案寫入器濾鏡上設定檔名,並連接這兩個濾鏡。 方法會在第三個參數中傳回指向 AVI Mux 的指標。 可選擇性地,它會在第四個參數中傳回指向 IFileSinkFilter 介面的指標。 如果您不需要這個介面,您可以將此參數設定為 NULL,如上一個範例所示。
接下來,呼叫 ICaptureGraphBuilder2::RenderStream 方法,將擷取篩選連接到 AVI Mux,如下所示:
hr = pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
pCap, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
// Release the mux filter.
pMux->Release();
第一個參數提供了引腳類別,其中用於擷取的類別是 PIN_CATEGORY_CAPTURE。 第二個參數會提供媒體類型。 第三個參數是指向擷取過濾器的 IBaseFilter 介面的指標。 第四個參數是可選的;它允許您先將視訊串流通過中間過濾器,如編碼器,然後再傳送至多工器篩選器。 否則,請將此參數設定為 NULL,如上一個範例所示。 第五個參數是多工篩選器的指標。 呼叫 SetOutputFileName 方法可取得此指標。
若要擷取音訊,請使用媒體類型呼叫 RenderStream MEDIATYPE_Audio。 如果您要從兩個不同的裝置擷取音訊和視訊,最好讓音訊串流成為主數據流。 這有助於防止兩個數據流之間的漂移,因為 AVI Mux 篩選器會調整視訊串流上的播放速率以符合音訊數據流。 若要設定主要數據流,請在 AVI Mux 篩選器上呼叫 IConfigAviMux::SetMasterStream 方法:
IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
pConfigMux->SetMasterStream(1);
pConfigMux->Release();
}
SetMasterStream 的參數是數據流號碼,由您呼叫 RenderStream 的順序決定。 例如,如果您先針對視訊呼叫 RenderStream,然後再呼叫音訊,則視訊是數據流 0,而音訊則是數據流 1。
您也可以呼叫 IConfigInterleaving::put_Mode 方法來設定 AVI Mux 濾鏡如何交錯音訊和視訊串流。
IConfigInterleaving *pInterleave = NULL;
hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
if (SUCCEEDED(hr))
{
pInterleave->put_Mode(INTERLEAVE_CAPTURE);
pInterleave->Release();
}
使用INTERLEAVE_CAPTURE旗標,AVI Mux 會以適合視訊擷取的速率執行交錯。 您也可以使用INTERLEAVE_NONE,這表示不會交錯 — AVI Mux 只會按照數據到達的順序來寫入數據。 INTERLEAVE_FULL 旗標表示 AVI Mux 執行完整交錯,不過,此模式不太適合視訊擷取,因為它需要更高的系統資源。
編碼視訊串流
您可以在擷取篩選與 AVI Mux 篩選之間插入編碼器篩選,以編碼視訊串流。 使用 系統裝置枚舉器 或 篩選映射器 以選擇編碼器篩選器。 (如需詳細資訊,請參閱 列舉裝置和篩選。
將編碼器篩選指定為 RenderStream 的第四個參數,如下列範例所示:
IBaseFilter *pEncoder;
/* Create the encoder filter (not shown). */
// Add it to the filter graph.
pGraph->AddFilter(pEncoder, L"Encoder");
/* Call SetOutputFileName as shown previously. */
// Render the stream.
hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
pCap,
pEncoder, pMux);
pEncoder->Release();
編碼器篩選器可能支援 IAMVideoCompression 或其他介面來設定編碼參數。 如需可能介面的清單,請參閱 檔案編碼和譯碼介面。
相關主題