C++ 媒体基金会设置视频交织和解码
我有一个MOV文件,我想解码它,并将所有帧作为单独的图像 因此,我尝试以下列方式配置未压缩的媒体类型:C++ 媒体基金会设置视频交织和解码,c++,decoding,ms-media-foundation,mov,interlacing,C++,Decoding,Ms Media Foundation,Mov,Interlacing,我有一个MOV文件,我想解码它,并将所有帧作为单独的图像 因此,我尝试以下列方式配置未压缩的媒体类型: // configure the source reader IMFSourceReader* m_pReader; MFCreateSourceReaderFromURL(filePath, NULL, &m_pReader); // get the compressed media type IMFMediaType* pFileVideoMediaType; m_pReader
// 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\u MT\u INTERLACE\u模式
设置为MFVideoInterlace\u Progressive
最终配置仍然使用旧模式MFVideoInterlace\u mixedinterlace或Progressive
之后,我循环浏览所有样本并查看它们的大小:
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;
IMFSample*videoSample=nullptr;
IMFMediaBuffer*mbuffer=nullptr;
隆隆时间戳;
德沃德河流指数,旗帜;
m_pReader->ReadSample(
MF\u源\u读卡器\u第一个\u视频\u流,
0,//标志。
&streamIndex,//接收实际的流索引。
&标志,//接收状态标志。
&llTimeStamp,//接收时间戳。
&videoSample)//接收样本或为空。
视频采样->转换到连续缓冲区(&mbuffer);
字节*videoData=nullptr;
DWORD sampleBufferLength=0;
mbuffer->Lock(&videoData、nullptr和sampleBufferLength);
cout为了使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\u SOURCE\u READERF\u CURRENTMEDIATYPECHANGED发生时,您不应该中断循环。现在,您将拥有相同大小的所有样品。
否则,您可以使用MFVideoFormat\u NV12子类型,然后在创建读取器时不需要指定MF\u SOURCE\u READER\u ENABLE\u VIDEO\u PROCESSING属性。也许您应该尝试先调用GetNativeMediaType,而不是m\u Preder->GetCurrentMediaType(MF\u SOURCE\u READER\u first\u VIDEO\u STREAM,&pFileVideoMediaType);。您是否还检查了每个样本是否交错:pSample->GetUINT32(MFSampleExtension\u交错,&isSampleInterlaced);您可以在此处检查ConfigureDecoder函数:。调用ReadSample时,您还可以在接收状态标志中检查MF\u SOURCE\u READERF\u CURRENTMEDIATYPECHANGED,以查看类型是否已更改。@VuVirt,谢谢您的评论。获取本机媒体类型不会改变任何内容。检查样本的隔行扫描结果出现错误。媒体类型没有改变。你还有别的想法吗?如果你能抽出几分钟来看看我的代码:。非常感谢您的帮助。请尝试不使用ptypeumpc->CopyAllItems。只需使用所有必要的属性手动构建未压缩的视频媒体类型,如本链接所示:您不应该为子类型设置MFVideoFormat_Base。试试MFVideoFormat_RGB32。对我有用。非常感谢。让我再问你一个问题。对于一些文件,我得到的buffersize与图像heightwidth*4完全匹配,并且数据是正确的。对于其他一些文件,我得到的缓冲区大小大于heightwidth*4。你知道这些额外的数据代表什么吗?VuVirt,我看到了你的答案,非常好。正如您所说,我试图将IMFSample锁定为2D数据,但最终出现了一个错误。您还可以分享一段代码,演示如何使用2D正确锁定和访问示例数据吗?谢谢你advance@mbaros什么错误?有些样品不暴露IMF2DBuffer。在这种情况下,您可能需要直接锁定IMFMediaBuffer。或查询D3D纹理。按照另一个答案中的链接,有足够的源代码和解释开始。至于较大的宽度,则称为跨步:。谢谢武维特看。最有可能的情况是,样本不暴露IMF2DBuffer。我确实使用IMFMediaBuffer。我已经测试了3个媒体文件。在所有情况下,步幅=宽度*4。问题是,在某些情况下,样本缓冲区长度大于hw*4。获取第一个hw*4字节的数据会产生错误的输出图像。每当我的缓冲区长度为h*w*4时,数据都是正确的。