You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MediaFoundation写入MP4时首帧时间戳未正确设为0,而是被设为帧时长的问题求助

MediaFoundation写入MP4时首帧时间戳未正确设为0,而是被设为帧时长的问题求助

我现在在用Media Foundation处理视频写入,遇到一个奇怪的时间戳问题,想请各位帮忙分析下。我的需求很简单:把两个单独存在二进制文件(frame1.bin、frame2.bin)里的帧数据,合成输出一个名为sample.mp4的MP4视频文件。

核心写入逻辑

我读取单帧数据后,会创建媒体样本、关联时间戳再交给Sink Writer写入,相关代码如下:

CComPtr<IMFMediaBuffer> mediaBuffer(createMediaBuffer(input));

// Create a media sample and add the buffer to the sample.
CComPtr<IMFSample> sample;
MFWRITER_RETURN_ON_ERROR(throwIf(MFCreateSample(&sample)));
MFWRITER_RETURN_ON_ERROR(throwIf(sample->AddBuffer(mediaBuffer)));

// Set the time stamp and the duration.
MFWRITER_RETURN_ON_ERROR(throwIf(sample->SetSampleTime(_frameStart)));
MFWRITER_RETURN_ON_ERROR(throwIf(sample->SetSampleDuration(_frameDuration)));

// Send the sample to the Sink Writer.
MFWRITER_RETURN_ON_ERROR(throwIf(_sinkWriter->WriteSample(_videoStreamIndex, sample)));

// Advance the starting position for the next frame
_frameStart += _frameDuration;

Sink Writer的创建与配置

Sink Writer的初始化和媒体类型配置我是这么实现的:

std::wstring wideFile = L"sample.mp4";
CComPtr<IMFMediaType> pMediaTypeOut, pMediaTypeIn;
MFWRITER_RETURN_HRESULT_ON_ERROR(MFCreateSinkWriterFromURL(wideFile.c_str(), NULL, NULL, &_sinkWriter));

// Set the output media type.
MFWRITER_RETURN_HRESULT_ON_ERROR(MFCreateMediaType(&pMediaTypeOut));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main));

// Set the Bit rate.  NOTE this assumes the input data is natively 24 bits per pixel (8 per band, 3 bands)
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, computeH264BitRate(_quality, width, height, _frameRate, 24)));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));

MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, width, height));

_frameDuration = static_cast<long long>(std::round((1.0 / _frameRate) * HUNDRED_NANOSECONDS));

// Derive the frame rate from 
UINT32 rateNumerator = 0, rateDenominator = 0;
MFWRITER_RETURN_HRESULT_ON_ERROR(MFAverageTimePerFrameToFrameRate(_frameDuration, &rateNumerator, &rateDenominator));

MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, rateNumerator, rateDenominator));

MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
MFWRITER_RETURN_HRESULT_ON_ERROR(_sinkWriter->AddStream(pMediaTypeOut, &_videoStreamIndex));


// Set the input media type.
MFWRITER_RETURN_HRESULT_ON_ERROR(MFCreateMediaType(&pMediaTypeIn));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, width, height));
MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, rateNumerator, rateDenominator));
MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));

MFWRITER_RETURN_HRESULT_ON_ERROR(_sinkWriter->SetInputMediaType(_videoStreamIndex, pMediaTypeIn, NULL));


_frameStart = 0;

// Tell the sink writer to start accepting data.
MFWRITER_RETURN_HRESULT_ON_ERROR(_sinkWriter->BeginWriting());

return true;

问题详情

我遇到的关键问题是:生成的MP4文件中,第一帧的时间戳不是预期的0,而是自动变成了帧时长(大约0.0333秒)。

我做了基础排查:在调用sample->SetSampleTime(_frameStart)的前后,都打印了_frameStart的值,结果都是0,完全符合预期。但最终输出的MP4里,首帧的时间戳就是不对,我实在找不到问题出在哪,有没有朋友遇到过类似的情况?


备注:内容来源于stack exchange,提问作者Eswaramoorthy K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:28:02