2017-04-19 79 views
1

我有一個MOV文件,我想解碼它,並將所有幀作爲單獨的圖像。媒體基金會設置視頻隔行掃描和解碼

所以我嘗試按以下方式配置未壓縮的媒體類型:

// configure the source reader 
IMFSourceReader* m_pReader; 
MFCreateSourceReaderFromURL(filePath, NULL, &m_pReader); 

// get the compressed media type 
IMFMediaType* pFileVideoMediaType; 
m_pReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pFileVideoMediaType); 

// create new media type for uncompressed type 
IMFMediaType* pTypeUncomp; 
MFCreateMediaType(&pTypeUncomp); 

// copy all settings from compressed to uncompressed type 
pFileVideoMediaType->CopyAllItems(pTypeUncomp); 

// set the uncompressed video attributes 
pTypeUncomp->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB8); 
pTypeUncomp->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); 
pTypeUncomp->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); 

// set the new uncompressed type to source reader 
m_pReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, pTypeUncomp); 

// get the full uncompressed media type 
m_pReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pTypeUncomp); 

我注意到,即使我明確設置MF_MT_INTERLACE_MODEMFVideoInterlace_Progressive最終配置仍與舊模式MFVideoInterlace_MixedInterlaceOrProgressive配置。

之後,我遍歷所有的樣本,看看它們的大小:

IMFSample* videoSample = nullptr; 
IMFMediaBuffer* mbuffer = nullptr; 
LONGLONG llTimeStamp; 
DWORD streamIndex, flags; 

m_pReader->ReadSample(
      MF_SOURCE_READER_FIRST_VIDEO_STREAM, 
      0,        // Flags. 
      &streamIndex,     // Receives the actual stream index. 
      &flags,       // Receives status flags. 
      &llTimeStamp,     // Receives the time stamp. 
      &videoSample)     // Receives the sample or NULL. 

videoSample->ConvertToContiguousBuffer(&mbuffer); 

BYTE* videoData = nullptr; 
DWORD sampleBufferLength = 0; 

mbuffer->Lock(&videoData, nullptr, &sampleBufferLength); 
cout << sampleBufferLength << endl; 

我也得到了相當的樣本大小不同:從31bytes到18000bytes。 即使將格式更改爲MFVideoFormat_RGB32也不會影響樣本大小。

This問題似乎有同樣的問題,但解決方案沒有解決它。

爲什麼我不能改變隔行掃描以及如何正確解碼視頻幀並從樣本中獲取圖像數據?

非常感謝提前。

+1

也許你應該嘗試先調用GetNativeMediaType而不是m_pReader-> GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,&pFileVideoMediaType);.你還檢查每個樣本是否交錯:pSample-> GetUINT32(MFSampleExtension_Interlaced,&isSampleInterlaced); – VuVirt

+1

您可以在此檢查ConfigureDecoder函數:https://msdn.microsoft.com/en-us/library/windows/desktop/dd389281(v=vs.85).aspx#setting_output_formats。調用ReadSample時,您還可以在收到狀態標誌中檢查MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED,以查看類型是否已更改。 – VuVirt

+0

@VuVirt,感謝您的評論。獲取本地媒體類型不會改變任何內容。檢查隔行掃描樣本最終出現錯誤。並沒有媒體類型的變化。你腦子裏還有別的東西嗎?如果你能找到幾分鐘看我的代碼:https://github.com/mbaros100/Media-Foundation-video-decoder。非常感謝您的幫助。 – mbaros

回答

1

爲了使SourceReader轉換樣本爲RGB,你需要這樣的創建:

IMFAttributes* pAttr = NULL; 
MFCreateAttributes(&pAttr, 1); 
pAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE); 
pAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE); 

IMFSourceReader* m_pReader; 
throwIfFailed(MFCreateSourceReaderFromURL(filePath, pAttr, &m_pReader), Can't create source reader from url"); 
pAttr->Release(); 

後來,你不應該從循環時MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED發生斷裂。現在您將擁有相同尺寸的所有樣本。 否則,您可以使用MFVideoFormat_NV12子類型,然後在創建閱讀器時不需要指定MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING屬性。 注意:MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING僅在Windows 8和更高版本上受支持。

+0

爲我工作。非常感謝你。 – mbaros

+0

讓我再問你一個問題。對於某些文件,我得到的緩衝區大小完全匹配圖像高度*寬度* 4,數據是正確的。對於其他一些文件,我得到的緩衝區大小比高*寬* 4大。你知道這些額外的數據代表什麼嗎? – mbaros

+0

VuVirt,我看到你的答案http://stackoverflow.com/questions/43014780/extarct-rgb32-byte-data-from-imfsample/43027190#43027190,這是非常好的。正如你所說的,我試圖將我的IMFSample鎖定爲2D數據,但是我最終出現了一個錯誤。你能否也請分享一段代碼,展示如何正確鎖定和訪問2D樣本數據?在此先感謝 – mbaros