Configuring the buffer
If you use MDelay, you can export a part of the buffered video (or a whole buffer) into a local file. For this, you should change the "mdelay.video_codec" from the default "mjpeg" to any codec you like, for example, to NVIDIA NVENC - "n264", and with "mdelay.video_props" you can specify additional parameters of the encoding:
m_objDelay.PropsSet("mdelay.video_codec", "n264");
m_objDelay.PropsSet("mdelay.video_props", "b='5M' g='12'");
In this case, the video frames that you process with the MDelay are encoded and are kept in the SBE file (or in RAM) in the pre-encoded state, so the export operation is extremely fast since it is only buffered audio data that needs to be encoded.
Export from a buffer
When you start the buffering, the MDelay keeps information about the start time. You can get when you started the buffering and how much data is stored in the buffer with the DelayAvailable method, so with the results, you can calculate a position for the export.
To export a part of a buffered video, you should use the DelayExportBufferByTime method.
// MFormats
m_objDelay.DelayExportBufferByTime(@"d:\export.mp4",
"codec='libmp3lame", -10, 0, out operation);
// MPlatform
m_objMLive.ObjectGetInternal("delay", out delayObj);
(delayObj as IMFDelay).DelayExportBufferByTime(@"d:\export.mp4",
"codec='libmp3lame", -10, 0, out IMFAsyncOperation operation);
So, you set the target path to export the buffer to. Next, you set the audio codec properties, like "codec='aac'". The next 2 parameters (_dblBufferTimeSec and _dblDurationSec ) are tricky. Here is how they work:
_dblBufferTimeSec = X - a position from buffer start, it means how many seconds from the start point (returned by the DelayAvailable method) has passed.
_dblBufferTimeSec < 0 - a position from the end of the buffer, i.e. "how many seconds prior to the current moment should I start the export?"
_dblDurationSec = X - duration of the exported file. If X is greater then it is available in the buffer, the MDelay waits for the buffer is of proper duration.
_dblDurationSec = 0 - till the end of the buffer
_dblDurationSec = -1 * X < 0 - wait X seconds after end then export the X.
So, the above code exports the last 10 seconds of the buffer.
The method returns an IMFAsyncOperation with which you can control the export operation asynchronously.
To check, how many export operations related to the same MDelay object are running at the same time you should call the DelayExportGetCount method. To check the state of each of the exports, you should iterate through them with the DelayExportGetByIndex.
Asynchronous control
With IMFAsyncOperation object, you can check a state of the current export operation. For this, you should use the OperationGetState method. The method returns you a progress state of the operation.
You can control the export operation by using "pause" and "continue" commands with the OperationControl method. And you can cancel the export with the OperationCancel.
A sample to test
In the attachment, you can find a sample that illustrates the export functionality of the MDelay object. To make it work on any machine, it is "libopenh264" video codec specified:
- Start a live source with the "Init Device" button.
- Enable the buffering with the "Enable" checkbox in the "Delay" section.
- Set the target path with "..." button at the right to the "Export to" textbox.
- Set the buffer position with either a trackbar in the "Delay" section or with the "Delayed" field. Note that the position should be greater than the specified "Export duration".
- Set the target file duration with the "Export duration" field.
- Click the "Export" buffer.
You'll have a message box with either a result or with an error description.