大概测试了一下,如果直接RenderFile播放的话,视频之间从上一个视频Stop到下一个视频Run之间 所需的时间为下面方法的至少3倍时间,
对于采用同一种视频编码的多个视频,可以采用只改变SourceFilter,而其他Filter不用改变的方式来切换视频。
实现方式如下,注意需要
DirectShowLibNET
DirectShowLibNET - A library to allow .NET applications to use DirectShow functions
public void ChangeFileSource(string newfilename)
{
// 先加入 新加入的文件名代表的SourceFilter
IPin nextOutPin = null;
int hr = 0;
IBaseFilter sourceFilter = null;
hr = m_FilterGraph.AddSourceFilter(newfilename, newfilename, out sourceFilter);
DsError.ThrowExceptionForHR(hr);
hr = sourceFilter.FindPin("Output", out nextOutPin);
DsError.ThrowExceptionForHR(hr);
//然后停止 当前FilterGraph的播放,
hr = m_mediaCtrl.Stop();
DsError.ThrowExceptionForHR(hr);
//然后枚举所有Filter
IEnumFilters enumFilters = null;
hr = m_FilterGraph.EnumFilters(out enumFilters);
int iFiltCount = 0;
while (0 == enumFilters.Skip(1))
{
iFiltCount++;
}
enumFilters.Reset();
int iPos = 0;
IBaseFilter[] filters = new IBaseFilter[iFiltCount];
while (iPos < iFiltCount)
{
int numFiltersToGet = 1;
IBaseFilter[] filter = new IBaseFilter[numFiltersToGet];
IntPtr fetched = IntPtr.Zero;
hr = enumFilters.Next(1, filter, fetched);
DsError.ThrowExceptionForHR(hr);
filters[iPos] = filter[0];
iPos++;
}
//此循环将新加入的SourceFilter加入到FilterGraph中,并将原SourceFilter移除并释放掉
for (iPos = 0; iPos < iFiltCount; iPos++)
{
m_FilterGraph.RemoveFilter(filters[iPos]);
if (filters[iPos] != m_currentSource)
{
m_FilterGraph.AddFilter(filters[iPos], null);
}
else
{
Marshal.ReleaseComObject(filters[iPos]);
}
}
hr = m_FilterGraph.Render(nextOutPin);
DsError.ThrowExceptionForHR(hr);
m_currentSource = sourceFilter;
sourceFilter = null;
m_mediaCtrl.Run();
if (enumFilters != null)
{
Marshal.ReleaseComObject(enumFilters);
enumFilters = null;
}
}