Reputation: 43321
Following the Microsoft tutorial "Using the Sink Writer to Encode Video" https://learn.microsoft.com/en-us/windows/win32/medfound/tutorial--using-the-sink-writer-to-encode-video I found that line hr = pWriter->WriteSample(streamIndex, pSample);
has low performance. I print the execution time by changing the code:
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
// Send the sample to the Sink Writer.
if (SUCCEEDED(hr))
{
hr = pWriter->WriteSample(streamIndex, pSample);
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << endl;
and get an average 225 ms execution time (Release configuration). So, I try to solve this problem by applying an attributes to IMFSinkWriter
, this is the changed code:
HRESULT InitializeSinkWriter(IMFSinkWriter **ppWriter, DWORD *pStreamIndex)
{
*ppWriter = NULL;
*pStreamIndex = NULL;
IMFSinkWriter *pSinkWriter = NULL;
IMFMediaType *pMediaTypeOut = NULL;
IMFMediaType *pMediaTypeIn = NULL;
IMFAttributes* attr = NULL;
DWORD streamIndex;
HRESULT hr;
hr = MFCreateAttributes(&attr, 2);
if (SUCCEEDED(hr))
{
hr = attr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
}
if (SUCCEEDED(hr))
{
hr = attr->SetUINT32(MF_SINK_WRITER_DISABLE_THROTTLING, TRUE);
}
if (SUCCEEDED(hr))
{
hr = MFCreateSinkWriterFromURL(L"output.wmv", NULL, attr, &pSinkWriter);
}
// ... the same as in the code sample
}
However, MF_SINK_WRITER_DISABLE_THROTTLING
attribute does not help, and WriteSample
function still takes 225 ms. This is the serious problem to my real program, which needs to handle a high number of frames.
Additional information: I am using uncompressed frames
const GUID VIDEO_ENCODING_FORMAT = MFVideoFormat_RGB32;
instead of MFVideoFormat_WMV3
. With MFVideoFormat_WMV3
WriteSample
is really fast, but 225 ms seems to be too much even for uncompressed frames.
One more point. I have another program, which reads MFVideoFormat_RGB32
file and writes to another MFVideoFormat_RGB32
file. So, the sample is read from IMFSourceReader
and added to IMFSinkWriter
, without any performance problems.
Is there anything else I can do to improve the program performance?
Upvotes: 1
Views: 887
Reputation: 43321
The following code solved the problem, added before pSinkWriter->AddStream
line:
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetUINT32(MF_MT_DEFAULT_STRIDE, VIDEO_WIDTH*4);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
}
if (SUCCEEDED(hr))
{
hr = pMediaTypeOut->SetUINT32(MF_MT_SAMPLE_SIZE, VIDEO_WIDTH*VIDEO_HEIGHT*4);
}
Specifically, WriteSample
time was reduced to 20 ms once MF_MT_ALL_SAMPLES_INDEPENDENT
is added. Note that these values are valid only for uncompressed fixed-sized frames.
Upvotes: 2