我一直在使用最新版本的WPFMediaKit。我要做的是编写一个示例应用程序,它将使用Samplegrabber来捕获视频文件的视频帧,这样我就可以将它们作为单独的位图。
到目前为止,在构建和呈现我的图形时,我已经很幸运地使用了以下代码。但是,当我使用此代码播放.wmv视频文件时,如果附加了samplegrabber,它将播放跳跃或断断续续的视频。如果我注释掉我添加samplegrabber过滤器的那行,它工作得很好。同样,它可以正确地与AVI/MPEG等采样器一起工作。
protected virtual void OpenSource()
{
FrameCount = 0;
/* Make sure we clean up any remaining mess */
FreeResources();
if (m_sourceUri == null)
return;
string fileSource = m_sourceUri.OriginalString;
if (string.IsNullOrEmpty(fileSource))
return;
try
{
/* Creates the GraphBuilder COM object */
m_graph = new FilterGraphNoThread() as IGraphBuilder;
if (m_graph == null)
throw new Exception("Could not create a graph");
/* Add our prefered audio renderer */
InsertAudioRenderer(AudioRenderer);
var filterGraph = m_graph as IFilterGraph2;
if (filterGraph == null)
throw new Exception("Could not QueryInterface for the IFilterGraph2");
IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1);
IBaseFilter sourceFilter;
/* Have DirectShow find the correct source filter for the Uri */
var hr = filterGraph.AddSourceFilter(fileSource, fileSource, out sourceFilter);
DsError.ThrowExceptionForHR(hr);
/* We will want to enum all the pins on the source filter */
IEnumPins pinEnum;
hr = sourceFilter.EnumPins(out pinEnum);
DsError.ThrowExceptionForHR(hr);
IntPtr fetched = IntPtr.Zero;
IPin[] pins = { null };
/* Counter for how many pins successfully rendered */
int pinsRendered = 0;
m_sampleGrabber = (ISampleGrabber)new SampleGrabber();
SetupSampleGrabber(m_sampleGrabber);
hr = m_graph.AddFilter(m_sampleGrabber as IBaseFilter, "SampleGrabber");
DsError.ThrowExceptionForHR(hr);
/* Loop over each pin of the source filter */
while (pinEnum.Next(pins.Length, pins, fetched) == 0)
{
if (filterGraph.RenderEx(pins[0],
AMRenderExFlags.RenderToExistingRenderers,
IntPtr.Zero) >= 0)
pinsRendered++;
Marshal.ReleaseComObject(pins[0]);
}
Marshal.ReleaseComObject(pinEnum);
Marshal.ReleaseComObject(sourceFilter);
if (pinsRendered == 0)
throw new Exception("Could not render any streams from the source Uri");
/* Configure the graph in the base class */
SetupFilterGraph(m_graph);
HasVideo = true;
/* Sets the NaturalVideoWidth/Height */
//SetNativePixelSizes(renderer);
}
catch (Exception ex)
{
/* This exection will happen usually if the media does
* not exist or could not open due to not having the
* proper filters installed */
FreeResources();
/* Fire our failed event */
InvokeMediaFailed(new MediaFailedEventArgs(ex.Message, ex));
}
InvokeMediaOpened();
}和:
private void SetupSampleGrabber(ISampleGrabber sampleGrabber)
{
FrameCount = 0;
var mediaType = new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24,
formatType = FormatType.VideoInfo
};
int hr = sampleGrabber.SetMediaType(mediaType);
DsUtils.FreeAMMediaType(mediaType);
DsError.ThrowExceptionForHR(hr);
hr = sampleGrabber.SetCallback(this, 0);
DsError.ThrowExceptionForHR(hr);
}我读过一些关于.wmv或.asf格式是异步的之类的东西。我曾尝试插入一个WMAsfReader来解码,但一旦它转到VMR9,它就会给出同样的行为。此外,当我注释掉IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1);行并使用filterGraph.Render(pins[0]);时,我已经让它正常工作了--唯一的缺点是它现在呈现在自己的Activemovie窗口中,而不是我的控件中,但是samplegrabber功能正常,没有任何跳过。所以我认为bug存在于VMR9 / samplegrabbing中的某个地方。
有什么帮助吗?我对此还不熟悉。
发布于 2010-04-16 17:07:13
一些解码器将使用使用DXVA的硬件加速。这是通过协商部分解码的格式,并将该部分解码的数据传递给渲染器来完成解码和渲染来实现的。如果在解码器和渲染器之间插入配置为RGB24的采样器,将禁用硬件加速。
我相信,这就是问题的症结所在。我担心细节仍然有点含糊,比如为什么当你使用默认的VMR-7时它可以工作,但当你使用VMR-9时它失败了。我猜解码器正在尝试使用dxva,但在vmr-9的情况下失败了,但有一个合理的纯软件备份,在vmr-7中工作良好。
我不熟悉WPFMediaKit,但我认为最简单的解决方案是用显式的vmr-7创建替换显式的vmr-9创建。也就是说,如果解码器只能在vmr-7上使用软件,那么就使用它,并专注于修复窗口重新设置父问题。
发布于 2010-04-16 21:28:55
结果是,我发布的代码(这段代码本身是我从Jeremiah的WPFMediakit源代码中稍加修改的)实际上足以呈现.WMV文件并被样本抓取。
这种波动似乎与通过VS调试器或VS2008本身运行有关。在可视化编辑器中处理XAML一段时间后,然后运行应用程序,我将引入这种不稳定的行为。关闭VS2008似乎可以弥补这个问题。:P
所以没有太多的答案,但当它突然出现时,至少有一个(恼人的-重新启动VS2008)修复。
https://stackoverflow.com/questions/2649191
复制相似问题