IMFSourceReaderCallback::OnReadSample 函数

IMFSourceReaderCallback::OnReadSample Function

要从您的网络摄像头读取样本并将它们写入文件,您可以实现 IMFSourceReaderCallback 并且回调函数 OnReadSample 将发送 IMFSample *pSample 以及一些其他参数,例如时间戳,您可以将它们与 ISinkWriter 一起使用以将它们写入文件(您可以查看 MSDN 示例 MFCaptureToFile Sample

STDMETHODIMP OnReadSample(
    HRESULT hrStatus,
    DWORD dwStreamIndex,
    DWORD dwStreamFlags,
    LONGLONG llTimestamp,
    IMFSample *pSample

);

我已将我的编码参数设置为 H264。我将 pSample 转换为原始数据(字节集)并删除了 ISinkWriter。 我有一个棘手的问题 *"is IMFSample pSample encoded or they become encoded inside ISinkWriter as when I convert them to RawData I got a huge file so are they encoded?" 还有一个问题 将它们写入文件后如何测试它们(它们是原始格式)

示例将采用原始格式,例如 YUV 或 RGB。您不能在视频设备源 reader 上将输出媒体类型设置为 H264(除非该设备恰好本身支持 H264)。当您引入带有 .mp4 文件的 SinkWriter 作为目标时,媒体基础将负责解析拓扑,在这种情况下这意味着包括 H264 媒体基础转换。

我用来测试 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.