首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Microsoft Media Foundation -解码h264示例

Microsoft Media Foundation -解码h264示例
EN

Stack Overflow用户
提问于 2010-09-21 22:09:29
回答 2查看 8.1K关注 0票数 3

我使用Microsoft Media Foundation示例(即MFCaptureToFile)从我的网络摄像头捕获H264帧,并将其写入文件。

我正在尝试使用IMFTransform来解码捕获的帧,并得到下划线图像(YUV,BMP,无论什么)。

但是,ProcessInput方法从不返回MF_E_NOTACCEPTING,而ProcessOutput方法始终返回MF_E_TRANSFORM_NEED_MORE_INPUT。

我基本上读取了每一帧,并调用了ProcessInput。

有什么想法吗?是否有人可以修改MFCaptureToFile示例以向我展示它是如何完成的?我在CCapture::OnReadSample下执行所有处理。

任何帮助都将不胜感激!

Ido

EN

回答 2

Stack Overflow用户

发布于 2015-03-16 18:08:21

我已经能够成功地使用MF H264解码器MFT将存储在.mp4文件中的帧解码为原始YUV。完整的代码示例可以在here上找到。

关键部分是创建H264解码器MFT,然后为其提供示例。我已经包含了下面这两个部分的代码片段。

代码语言:javascript
代码运行次数:0
运行
复制
// Create H.264 decoder.
CHECK_HR(CoCreateInstance(CLSID_CMSH264DecoderMFT, NULL, CLSCTX_INPROC_SERVER,
    IID_IUnknown, (void**)&spDecTransformUnk), "Failed to create H264 decoder MFT.\n");

CHECK_HR(spDecTransformUnk->QueryInterface(IID_PPV_ARGS(&pDecoderTransform)), "Failed to get IMFTransform interface from H264 decoder MFT object.\n");

MFCreateMediaType(&pDecInputMediaType);
CHECK_HR(pFileVideoMediaType->CopyAllItems(pDecInputMediaType), "Error copying media type attributes to decoder input media type.\n");
CHECK_HR(pDecoderTransform->SetInputType(0, pDecInputMediaType, 0), "Failed to set input media type on H.264 decoder MFT.\n");

MFCreateMediaType(&pDecOutputMediaType);
pDecOutputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
pDecOutputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV);
CHECK_HR(MFSetAttributeSize(pDecOutputMediaType, MF_MT_FRAME_SIZE, VIDEO_SAMPLE_WIDTH, VIDEO_SAMPLE_HEIGHT), "Failed to set frame size on H264 MFT out type.\n");
CHECK_HR(MFSetAttributeRatio(pDecOutputMediaType, MF_MT_FRAME_RATE, 30, 1), "Failed to set frame rate on H264 MFT out type.\n");
CHECK_HR(MFSetAttributeRatio(pDecOutputMediaType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1), "Failed to set aspect ratio on H264 MFT out type.\n");
pDecOutputMediaType->SetUINT32(MF_MT_INTERLACE_MODE, 2);

CHECK_HR(pDecoderTransform->SetOutputType(0, pDecOutputMediaType, 0), "Failed to set output media type on H.264 decoder MFT.\n");

CHECK_HR(pDecoderTransform->GetInputStatus(0, &mftStatus), "Failed to get input status from H.264 decoder MFT.\n");
if (MFT_INPUT_STATUS_ACCEPT_DATA != mftStatus) {
    printf("H.264 decoder MFT is not accepting data.\n");
    goto done;
}

CHECK_HR(pDecoderTransform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, NULL), "Failed to process FLUSH command on H.264 decoder MFT.\n");
CHECK_HR(pDecoderTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL), "Failed to process BEGIN_STREAMING command on H.264 decoder MFT.\n");
CHECK_HR(pDecoderTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL), "Failed to process START_OF_STREAM command on H.264 decoder MFT.\n")

一旦创建了解码器,并且您从某个地方获得了编码的H264帧,您需要将它们传递到上面创建的MFT。

代码语言:javascript
代码运行次数:0
运行
复制
    MFCreateSample(&reConstructedVideoSample);
CHECK_HR(MFCreateMemoryBuffer(srcBufLength, &reConstructedBuffer), "Failed to create memory buffer.\n");
CHECK_HR(reConstructedVideoSample->AddBuffer(reConstructedBuffer), "Failed to add buffer to re-constructed sample.\n");
CHECK_HR(reConstructedVideoSample->SetSampleTime(llVideoTimeStamp), "Error setting the recon video sample time.\n");
CHECK_HR(reConstructedVideoSample->SetSampleDuration(llSampleDuration), "Error setting recon video sample duration.\n");

byte *reconByteBuffer;
DWORD reconBuffCurrLen = 0;
DWORD reconBuffMaxLen = 0;
CHECK_HR(reConstructedBuffer->Lock(&reconByteBuffer, &reconBuffMaxLen, &reconBuffCurrLen), "Error locking recon buffer.\n");
memcpy(reconByteBuffer, srcByteBuffer, srcBuffCurrLen);
CHECK_HR(reConstructedBuffer->Unlock(), "Error unlocking recon buffer.\n");
reConstructedBuffer->SetCurrentLength(srcBuffCurrLen);

CHECK_HR(srcBuf->Unlock(), "Error unlocking source buffer.\n");

CHECK_HR(pDecoderTransform->ProcessInput(0, reConstructedVideoSample, 0), "The H264 decoder ProcessInput call failed.\n");

CHECK_HR(pDecoderTransform->GetOutputStatus(&mftOutFlags), "H264 MFT GetOutputStatus failed.\n");

//if (mftOutFlags == MFT_OUTPUT_STATUS_SAMPLE_READY)
//{
    CHECK_HR(pDecoderTransform->GetOutputStreamInfo(0, &StreamInfo), "Failed to get output stream info from H264 MFT.\n");

    while (true)
    {
        CHECK_HR(MFCreateSample(&mftOutSample), "Failed to create MF sample.\n");
        CHECK_HR(MFCreateMemoryBuffer(StreamInfo.cbSize, &pBuffer), "Failed to create memory buffer.\n");
        CHECK_HR(mftOutSample->AddBuffer(pBuffer), "Failed to add sample to buffer.\n");
        outputDataBuffer.dwStreamID = 0;
        outputDataBuffer.dwStatus = 0;
        outputDataBuffer.pEvents = NULL;
        outputDataBuffer.pSample = mftOutSample;

        mftProcessOutput = pDecoderTransform->ProcessOutput(0, 1, &outputDataBuffer, &processOutputStatus);

        if (mftProcessOutput != MF_E_TRANSFORM_NEED_MORE_INPUT)
        {
            // ToDo: These two lines are not right. Need to work out where to get timestamp and duration from the H264 decoder MFT.
            CHECK_HR(outputDataBuffer.pSample->SetSampleTime(llVideoTimeStamp), "Error getting YUV sample time.\n");
            CHECK_HR(outputDataBuffer.pSample->SetSampleDuration(llSampleDuration), "Error getting YUV sample duration.\n");

            IMFMediaBuffer *buf = NULL;
            DWORD bufLength;
            CHECK_HR(mftOutSample->ConvertToContiguousBuffer(&buf), "ConvertToContiguousBuffer failed.\n");
            CHECK_HR(buf->GetCurrentLength(&bufLength), "Get buffer length failed.\n");

            printf("Writing sample %i, sample time %I64d, sample duration %I64d, sample size %i.\n", sampleCount, yuvVideoTimeStamp, yuvSampleDuration, bufLength);

            byte *byteBuffer;
            DWORD buffCurrLen = 0;
            DWORD buffMaxLen = 0;
            buf->Lock(&byteBuffer, &buffMaxLen, &buffCurrLen);
            outputBuffer.write((char *)byteBuffer, bufLength);
            outputBuffer.flush();
        }
        else {
            break;
        }

        mftOutSample->Release();
   }
票数 7
EN

Stack Overflow用户

发布于 2011-04-29 18:58:28

微软的H264解码器MFT有些特别。它在内部缓冲了大量样本。(这就是为什么它不适用于实时场景的原因,因为由于这种内部缓冲,它总是引入大约一秒的延迟)。我想你至少要给它提供一个完整的GOP来接收一些输出样本。试试看

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3761146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档