Basic logic
You should use 2 MFReader objects to emulate a playlist behavior.
- Create the 1st MFReader object and initialize it with the 1st file of your playlist with the ReaderOpen method.
- Create the 2nd MFReader object and open the 2nd file with the ReaderOpen method.
- Start playback of the 1st MFReader.
- Check frame flags received from the source object. When you get a frame with the "Last" flag you should switch to the next MFReader object to grab frames from it. You can check the last frame with this code:
M_TIME mTime; pFrame.MFTimeGet(out mTime); if ((mTime.eFFlags & eMFrameFlags.eMFF_Last) != 0) { // indicate to switch to the next reader }
- Continue playback of the 2nd MFReader and initialize the next file with the ReaderOpen method for the 1st MFReader object.
Repeat steps 3-5 to emulate a simple playlist behavior.
The above is a good approach to put the frames to an output device (MFRenderer object). If your scenario includes MFWriter for recording, there could be a tricky situation with the internal timing data of the processed frames. Different files have different times and, probably, formats.
So, if you need to put the playlist to MFWriter, you should do the following:
- Always use SourceFrameConvertedGet-based methods for grabbing frames from the files.
- Define all the M_AV_PROPS structure including audio properties (sample rate, channels number, bits) before you start grabbing the frames.
- For each processed frame, before putting it into the MFWriter object, update the frame time data (see below).
How to update the time data?
First, you should get the frame rate of the processing video. You can get it from the above M_AV_PROPS that you use for grabbing frames from the sources, or you can use the MFAVPropsGet method.
double dblRate = avProps.vidProps.dblRate;
The calculation of time starts with 0, and the duration of a single frame is calculated in reference units:
double dblFrameTime = 0;
double dblFrameDuration = 10000000 / dblRate;
Then, on each frame you do the following:
M_TIME mTime = new M_TIME();
mTime.rtStartTime = (long)dblFrameTime;
mTime.rtEndTime = (long)(dblFrameTime + dblFrameDuration);
mTime.eFFlags = dblFrameTime == 0 ? eMFrameFlags.eMFF_Break : eMFrameFlags.eMFF_Live;
dblFrameTime += dblFrameDuration;
pFrame.MFTimeSet(ref mTime);
That's it. Repeat these actions for each processing frame before you put the frame to the MFWriter object to prevent the most common errors during the encoding.