我正在尝试为基于GMFBridge和DirectShow的视频播放器制作时间码计数器。
我使用Timer每200ms调用一次GetCurrentPosition(),但我认为它不准确。我想至少在视频运行时获取当前帧的帧号(从开始)。
这可以实际完成吗?
我正在使用DirectShowLib .NET库。
答案 0 :(得分:1)
据我所知,这很难实现,在我处理的解决方案中,我做了以下操作以获得'帧号':
public int NumberOfFrames
{
get
{
return (int)(Duration / AverageTimePerFrame);
}
}
public double AverageTimePerFrame
{
get
{
return videoInfoHeader.AvgTimePerFrame / 10000000.0;
}
}
public int GetCurrentFrame(double currentTime)
{
int noOfFrames = (int)(Duration / AverageTimePerFrame);
return Convert.ToInt32(Math.Min(noOfFrames - 1, Math.Floor(currentTime / AverageTimePerFrame)));
}
我通过以下方式获得了videoInfoHeader:
// Get the media type from the SampleGrabber
AMMediaType media = new AMMediaType();
hr = sampGrabber.GetConnectedMediaType(media);
DsError.ThrowExceptionForHR(hr);
if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
{
throw new NotSupportedException("Unknown Grabber Media Format");
}
// Grab the size info
videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
DsUtils.FreeAMMediaType(media);
然而,这显然是根据我自己的用例量身定制的,希望它能帮助你一点点。祝你好运!
<强>更新强> 添加了CurrentTime代码(储物柜是我自己使用的,你最有可能删除它):
public double CurrentTime
{
set
{
lock (locker)
{
IMediaPosition mediaPos = fFilterGraph as IMediaPosition;
int hr;
if (value >= 0 && value <= Duration)
{
hr = mediaPos.put_CurrentPosition(value);
DsError.ThrowExceptionForHR(hr);
}
}
}
get
{
lock (locker)
{
IMediaPosition mediaPos = fFilterGraph as IMediaPosition;
int hr;
double currentTime;
hr = mediaPos.get_CurrentPosition(out currentTime);
DsError.ThrowExceptionForHR(hr);
return currentTime;
}
}
}