大概测试了一下,如果直接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; } }