本主題描述何時以及如何使用 H.264/AVC Remux MFT 和 MP4 接收器。
使用 H.264/AVC Remux MFT 的時機
MPEG-4 檔案格式要求每個壓縮樣本都包含一個主要圖片,其中的 NAL 單位必須按照正確的順序排列。 (請參閱 H.264 AVC 規格中對主要圖片和 NAL 單元強制順序的定義,關於 NAL 單元順序與編碼圖片的關聯及其對存取單元的關係的部分。它還要求每個壓縮樣本都必須與呈現時間戳、解碼時間戳和樣本持續時間相關聯。)
在許多情況下,當應用程式需要在 MPEG-4 檔案容器中錄製 H.264/AVC 視訊時,壓縮的範例可能無法滿足上述需求。 例如,一個壓縮的範例可能不會包含完整的主要圖片,或可能沒有與其相關聯的正確簡報時間戳。 一些應用程式範例如下:
- 將 H.264/AVC 串流基本視訊寫入 MPEG-4 檔案容器。
- 錄製相機在 MPEG-4 檔案容器中擷取 H.264/AVC 基本視訊。
- 在 MPEG-4 檔案容器中錄製 H.264/AVC 視訊會議。
- 在 MPEG-2 TS 或 MP4 中串連兩個 H.264/AVC 視訊,並寫入具有正確時間戳的 MPEG-4 檔案容器。
- 重混 H.264/AVC 視訊,將 AVCHD、MPEG-2 TS/PS 檔案格式轉為 MPEG-4 檔案格式。
- 修剪 H.264/AVC 視訊檔案而不轉碼。
在此情況下,應用程式必須使用 H.264/AVC remux MFT,將未包含完整主要圖片的壓縮樣本轉換後,再寫入 MPEG-4 檔案容器。
如何使用 H.264/AVC Remux MFT 和 MP4 匯點
將來源輸出媒體類型設定為 MFVideoFormat_H264_ES,表示每個範例可能不包含完整的主要圖片。 將 MP4 匯出的輸入媒體類型設定為 MFVideoFormat_H264。 因此,H.264/AVC remux MFT 的輸入媒體類型是 MFVideoFormat_H264_ES,而 H.264/AVC remux MFT 的輸出媒體類型是 MFVideoFormat_H264,這些類型會被自動插入到拓撲解析程式中。
H.264/AVC remux 會忽略樣本持續時間,因為不含完整主要圖片的樣本持續時間沒有明確的意義。 而是從幀速率計算樣本持續時間。 幀速率是從時序參數計算而來。 如果序列參數中沒有資訊,則會從輸入媒體類型中的參數計算幀速率。 如果無法使用幀速率資訊,則會使用預設幀速率 29.97 fps。
H.264/AVC remux MFT 會根據幀速率,以線性方式插補每個壓縮畫面的解碼時間戳(DTS)。 H.264/AVC remux MFT 會接受輸入範例中的輸入簡報時間戳 (PTS),並在它們存在時傳遞至輸出。 它會根據幀速率、先前的 PTS 以及圖片輸出順序,透過所述的 附件 C.4.5.3 中的解碼圖片緩衝(DBP)跳動處理程序來執行 PTS 插補,這是 H.264 AVC 規格中的 所規定的。 H.264/AVC remux MFT 的每個輸出範例都應該具有 PTS、DTS 和範例持續時間。 H.264/AVC remux MFT 也會在位元資料流中識別 IDR 圖片,並使用 MFSampleExtension_CleanPoint的 MF 屬性將它們設為關鍵點。
目前 H.264/AVC remux MFT 最多可處理 64 個重新排序的畫面。 如果重新排序的畫面數目超過 64,且有長期參考畫面存在,則 H.264/AVC remux MFT 會為該畫面進行錯誤的 PTS 插值計算,並在錯誤的時間輸出該畫面。
若要具現化 H.264/AVC remux MFT,請在 H.264/AVC remux MFT 上設定正確的輸入和輸出媒體類型,設定 MP4 接收的輸入媒體類型,並解析拓撲。
下列範例程式碼示範如何初始化 H.264/AVC remux MFT 和 MP4 匯入點。
針對 H.264/AVC remux MFT,
hr = CoCreateInstance(
CLSID_CMSH264RemuxMFT,
NULL,
CLSCTX_INPROC_SERVER,
IID_IMFTransform,
(void**) &pIMFTransform
);
不需要進一步的設定。
針對 MP4 匯入端,
IMFByteStream* pMFBSOutputFile = NULL;
hr = MFCreateFile(
MF_ACCESSMODE_READWRITE,
MF_OPENMODE_DELETE_IF_EXIST,
MF_FILEFLAGS_NONE,
m_pszOutputFile,
&pMFBSOutputFile);
if(FAILED(hr))
{
Log(L"ERROR>> Failed to create output file for MP4 Sink (hr=0x%x)", hr);
break;
}
hr = MFCreateMPEG4MediaSink(
pMFBSOutputFile,
(guidMajorType == MFMediaType_Video) ? pMediaType : NULL, // pMediaType comes from the output type of the remux MFT
(guidMajorType == MFMediaType_Audio) ? pMediaType : NULL,
&m_pMediaSink);
if(FAILED(hr))
{
Log(L"ERROR>> Failed to create MP4 Sink (hr=0x%x)", hr);
break;
}
hr = m_pMediaSink->GetStreamSinkByIndex(0, &pStream);
相關主題