视频捕获输出始终在320x240,尽管改变分辨率



好的,我已经做了2天了,最后一部分需要帮助。

我有一个微软LifeCam电影摄像机,我使用。net DirectShowLib来捕获视频流。好吧,实际上我使用WPFMediaKit,但我在源代码直接处理直接显示库现在。

我的工作是:—查看摄像机的视频输出-将摄像机的视频输出记录为ASF或AVI格式(ICaptureGraphBuilder2唯一支持的两种MediaType)

问题是:我可以保存为。avi格式。这在1280x720的分辨率下工作得很好,但它将文件保存为RAW输出。这意味着它大约是每秒50-60MB。太高了

或者我可以切换到。asf,它输出一个WMV,但是当我这样做时,捕获和输出都是320x240的分辨率。

在WPFMediaKit中,我改变了一个功能,因为显然微软LifeCam电影相机很多人都有这个问题。而不是创建或改变AMMediaType你迭代然后用那个去调用SetFormat。

        ///* Make the VIDEOINFOHEADER 'readable' */
        var videoInfo = new VideoInfoHeader();
        int iCount = 0, iSize = 0;
        videoStreamConfig.GetNumberOfCapabilities(out iCount, out iSize);
        IntPtr TaskMemPointer = Marshal.AllocCoTaskMem(iSize);

        AMMediaType pmtConfig = null;
        for (int iFormat = 0; iFormat < iCount; iFormat++)
        {
            IntPtr ptr = IntPtr.Zero;
            videoStreamConfig.GetStreamCaps(iFormat, out pmtConfig, TaskMemPointer);
            videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(pmtConfig.formatPtr, typeof(VideoInfoHeader));
            if (videoInfo.BmiHeader.Width == DesiredWidth && videoInfo.BmiHeader.Height == DesiredHeight)
            {
                ///* Setup the VIDEOINFOHEADER with the parameters we want */
                videoInfo.AvgTimePerFrame = DSHOW_ONE_SECOND_UNIT / FPS;
                if (mediaSubType != Guid.Empty)
                {
                    int fourCC = 0;
                    byte[] b = mediaSubType.ToByteArray();
                    fourCC = b[0];
                    fourCC |= b[1] << 8;
                    fourCC |= b[2] << 16;
                    fourCC |= b[3] << 24;
                    videoInfo.BmiHeader.Compression = fourCC;
                   // pmtConfig.subType = mediaSubType;
                }
                /* Copy the data back to unmanaged memory */
                Marshal.StructureToPtr(videoInfo, pmtConfig.formatPtr, true);
                hr = videoStreamConfig.SetFormat(pmtConfig);
                break;
            }
        }
        /* Free memory */
        Marshal.FreeCoTaskMem(TaskMemPointer);
        DsUtils.FreeAMMediaType(pmtConfig);
        if (hr < 0)
            return false;
        return true;

当这实现时,我终于可以查看捕获的视频为1280x720,只要我将SetOutputFilename设置为MediaType.Avi。

如果我将它设置为MediaType。当它转到320x240时,输出是相同的。

或者AVI以正确的格式工作和输出,但在RAW视频中这样做,因此文件大小非常大。我曾尝试在图中添加一个压缩器,但运气不好,这远远超出了我的经验。

我正在寻找2个答案中的1个。

  1. 以1280x720记录ASF
  2. 在图形中添加压缩器,以便我输出的AVI文件大小较小。

我明白了。所以我把它贴在这里,为那些路过想知道为什么它不起作用的可怜的灵魂。

  1. 下载WPFMediaKit的源代码,你需要修改一些代码。

  2. 进入文件夹DirectShow> MediaPlayers,打开VideoCapturePlayer.cs

  3. 找到SetVideoCaptureParameters函数并将其替换为:

    /// <summary>
    /// Sets the capture parameters for the video capture device
    /// </summary>
    private bool SetVideoCaptureParameters(ICaptureGraphBuilder2 capGraph, IBaseFilter captureFilter, Guid mediaSubType)
    {
        /* The stream config interface */
        object streamConfig;
        /* Get the stream's configuration interface */
        int hr = capGraph.FindInterface(PinCategory.Capture,
                                        MediaType.Video,
                                        captureFilter,
                                        typeof(IAMStreamConfig).GUID,
                                        out streamConfig);
        DsError.ThrowExceptionForHR(hr);
        var videoStreamConfig = streamConfig as IAMStreamConfig;
        /* If QueryInterface fails... */
        if (videoStreamConfig == null)
        {
            throw new Exception("Failed to get IAMStreamConfig");
        }
        ///* Make the VIDEOINFOHEADER 'readable' */
        var videoInfo = new VideoInfoHeader();
        int iCount = 0, iSize = 0;
        videoStreamConfig.GetNumberOfCapabilities(out iCount, out iSize);
        IntPtr TaskMemPointer = Marshal.AllocCoTaskMem(iSize);
    
        AMMediaType pmtConfig = null;
        for (int iFormat = 0; iFormat < iCount; iFormat++)
        {
            IntPtr ptr = IntPtr.Zero;
            videoStreamConfig.GetStreamCaps(iFormat, out pmtConfig, TaskMemPointer);
            videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(pmtConfig.formatPtr, typeof(VideoInfoHeader));
            if (videoInfo.BmiHeader.Width == DesiredWidth && videoInfo.BmiHeader.Height == DesiredHeight)
            {
                ///* Setup the VIDEOINFOHEADER with the parameters we want */
                videoInfo.AvgTimePerFrame = DSHOW_ONE_SECOND_UNIT / FPS;
                if (mediaSubType != Guid.Empty)
                {
                    int fourCC = 0;
                    byte[] b = mediaSubType.ToByteArray();
                    fourCC = b[0];
                    fourCC |= b[1] << 8;
                    fourCC |= b[2] << 16;
                    fourCC |= b[3] << 24;
                    videoInfo.BmiHeader.Compression = fourCC;
                   // pmtConfig.subType = mediaSubType;
                }
                /* Copy the data back to unmanaged memory */
                Marshal.StructureToPtr(videoInfo, pmtConfig.formatPtr, true);
                hr = videoStreamConfig.SetFormat(pmtConfig);
                break;
            }
        }
        /* Free memory */
        Marshal.FreeCoTaskMem(TaskMemPointer);
        DsUtils.FreeAMMediaType(pmtConfig);
        if (hr < 0)
            return false;
        return true;
    }
    

现在,这将排序你的屏幕显示在任何你想要的分辨率,只要你的相机支持它。

接下来,您很快就会发现,在将视频写入磁盘时,您没有应用这个新的正确捕获。

由于ICaptureBuilder2方法只支持Avi和Asf(即wmv),您需要将您的媒体类型设置为其中之一。

hr = graphBuilder.SetOutputFileName(MediaSubType.Asf, this.m_fileName, out mux, out sink);

你可以在SetupGraph函数中找到这一行。

Asf将只输出320x240的分辨率,而Avi将输出所需的分辨率,但未压缩(意味着每秒50-60MB的1280x720视频馈送),这太高了。

那么剩下两个选项

  1. 找出如何添加编码器(压缩过滤器)到Avi输出

  2. 了解如何更改WMV配置文件

我试过了,但没有成功。主要是由于这是我第一次使用DirectShow,对图表的含义只是掌握。

但是我成功地做到了#2,下面是我是如何做到的。

特别感谢(http://www.codeproject.com/KB/audio-video/videosav.aspx)我从这里取出了所需的代码。

  1. 在同一个文件夹中创建一个名为WMLib.cs的新类,并将以下内容放入其中

从http://www.codeproject.com/KB/audio-video/videosav.aspx下载演示项目,将WMLib.cs复制并粘贴到您的项目中(根据需要更改名称空间)

  1. 在VideoCapturePlayer.cs类中创建一个函数

    /// <summary>
    /// Configure profile from file to Asf file writer
    /// </summary>
    /// <param name="asfWriter"></param>
    /// <param name="filename"></param>
    /// <returns></returns>
    public bool ConfigProfileFromFile(IBaseFilter asfWriter, string filename)
    {
        int hr;
        //string profilePath = "test.prx";
        // Set the profile to be used for conversion
        if ((filename != null) && (File.Exists(filename)))
        {
            // Load the profile XML contents
            string profileData;
            using (StreamReader reader = new StreamReader(File.OpenRead(filename)))
            {
                profileData = reader.ReadToEnd();
            }
            // Create an appropriate IWMProfile from the data
            // Open the profile manager
            IWMProfileManager profileManager;
            IWMProfile wmProfile = null;
            hr = WMLib.WMCreateProfileManager(out profileManager);
            if (hr >= 0)
            {
                // error message: The profile is invalid (0xC00D0BC6)
                // E.g. no <prx> tags
                hr = profileManager.LoadProfileByData(profileData, out wmProfile);
            }
            if (profileManager != null)
            {
                Marshal.ReleaseComObject(profileManager);
                profileManager = null;
            }
            // Config only if there is a profile retrieved
            if (hr >= 0)
            {
                // Set the profile on the writer
                IConfigAsfWriter configWriter = (IConfigAsfWriter)asfWriter;
                hr = configWriter.ConfigureFilterUsingProfile(wmProfile);
                if (hr >= 0)
                {
                    return true;
                }
            }
        }
        return false;
    }
    
  2. 在SetupGraph函数中找到SetOutputFileName并在其下方放置

    ConfigProfileFromFile (mux,"c: wmv.prx");

  3. 现在创建名为wmv的文件。把PRX文件放到你的c: drive上,并把相关信息放进去。

您可以在这里看到演示项目中的一个PRX文件示例:http://www.codeproject.com/KB/audio-video/videosav.aspx (Pal90.prx)

现在享受你的。wmv文件以正确的大小输出。是的,我知道我所放置的代码是相当混乱的,但我将把它留给你来完善它。

Lifecam以设置捕获格式的不明显行为而闻名(更具体地说,是退回到其他格式)。请参阅前面的讨论,这些讨论可能会给您提供解决方案:

  • 不能使IAMStreamConfig.SetFormat()与LifeCam Studio一起工作
  • IAMStreamConfig设置被流忽略-微软LifeCam影院记录仅在640x480
  • 微软LifeCam能以低于30fps的帧率记录吗?

最新更新