IMFSourceReaderCallback :: OnReadSample函数

时间:2015-03-08 12:29:12

标签: ms-media-foundation

要从网络摄像头中读取样本并将其写入文件,您可以实施 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时我得到了一个巨大的文件所以它们是否被编码?" 还有一个问题如何在将它们写入文件后对其进行测试(它们是原始格式)

1 个答案:

答案 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上提供的上述代码段的示例控制台应用。