我可以从directshow视频获取时间码吗?

时间:2011-03-08 05:31:50

标签: directshow.net

我正在尝试为基于GMFBridge和DirectShow的视频播放器制作时间码计数器。

我使用Timer每200ms调用一次GetCurrentPosition(),但我认为它不准确。我想至少在视频运行时获取当前帧的帧号(从开始)。

这可以实际完成吗?

我正在使用DirectShowLib .NET库。

1 个答案:

答案 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;
        }
    }
}