要从网络摄像头中读取样本并将其写入文件,您可以实施 IMFSourceReaderCallback ,并且回调函数 OnReadSample 将发送 IMFSample * pSample 使用其他一些参数,例如时间戳,您可以将它们与ISinkWriter一起用于将它们写入文件中(您可以查看MSDN示例MFCaptureToFile Sample)
STDMETHODIMP OnReadSample(
HRESULT hrStatus,
DWORD dwStreamIndex,
DWORD dwStreamFlags,
LONGLONG llTimestamp,
IMFSample *pSample
);
我已将编码参数设置为 H264 。我将pSample转换为rawdata(字节集)并删除了ISinkWriter。 我有一个棘手的问题*" IMFSample pSample 编码或者它们在ISinkWriter中编码,因为当我将它们转换为RawData时我得到了一个巨大的文件所以它们是否被编码?" 还有一个问题如何在将它们写入文件后对其进行测试(它们是原始格式)
答案 0 :(得分:2)
样本将采用原始格式,如YUV或RGB。您无法在视频设备源阅读器上将输出媒体类型设置为H264(除非该设备本身支持H264)。当您引入带有.mp4文件的SinkWriter作为目标时,Media Foundation将负责解析拓扑,在这种情况下,这意味着包括H264 Media Foundation Transform。
我用来测试SourceReader的原始输出的一种方法是指定MFVideoFormat_IYUV的输出格式,然后在写入文件流之后使用ffmpeg提取jpeg或将其转换为avi视频文件。
std::ofstream outputBuffer("rawframes.yuv", std::ios::out | std::ios::binary);
IMFMediaBuffer *buf = NULL;
DWORD bufLength;
pSample->ConvertToContiguousBuffer(&buf);
buf->GetCurrentLength(&bufLength);
printf("Writing sample %i, sample time %i, sample duration %i, sample size .\n", sampleCount, llVideoTimeStamp, llSampleDuration);
byte *byteBuffer;
DWORD buffCurrLen = 0;
DWORD buffMaxLen = 0;
buf->Lock(&byteBuffer, &buffMaxLen, &buffCurrLen);
outputBuffer.write((char *)byteBuffer, bufLength);
outputBuffer.flush();
然后是ffmpeg命令:
ffmpeg -vcodec rawvideo -s 640x480 -pix_fmt yuv420p -i rawframes.yuv -vframes 1 output.jpeg
ffmpeg -vcodec rawvideo -s 640x480 -pix_fmt yuv420p -i rawframes.yuv out.avi
使用github上提供的上述代码段的示例控制台应用。