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
相关产品推荐
相关产品推荐

