尽管改变了分辨率,但video捕获输出始终为320×240

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

我有一台Microsoft LifeCam Cinema相机,我使用.NET DirectShowLib来捕获video流。 实际上我使用WPFMediaKit,但我现在直接处理直接显示库的源代码。

我的工作是: – 查看摄像机的video输出 – 以ASF或AVI记录摄像机的video输出(ICaptureGraphBuilder2支持的唯一2个MediaType)

问题是:我可以将其保存为.avi。 这工作正常,分辨率为1280×720,但它将文件保存在RAW输出中。 这意味着它大约是每秒50-60MB。 方式太高了。

或者我可以将其切换为.asf并输出WMV,但是当我这样做时,捕获和输出都转到分辨率320×240。

在WPFMediaKit中有一个我改变的function,因为很明显有微软LifeCam Cinema相机很多人都有这个问题。 因此,不是创建或更改您迭代的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; 

实现后,只要我将SetOutputFilename设置为MediaType.Avi,我就可以最终将捕获的video视为1280×720。

如果我将它设置为MediaType。如果它转到320×240并且输出相同。

或者AVI以正确的格式工作和输出,但在RAWvideo中这样做,因此文件非常大。 我试图在图表中添加一个压缩器,但没有运气,这远远超出了我的经验。

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

  1. 以1280×720录制ASF
  2. 在图表中添加压缩器,以便输出的AVI的文件大小。

我想出来了。 因此,我在这里张贴任何其他可怜的灵魂,他们想知道为什么它不起作用。

  1. 下载WPFMediaKit的源代码,您将需要更改一些代码。

  2. 转到Folder DirectShow> MediaPlayers并打开VideoCapturePlayer.cs

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

     ///  /// Sets the capture parameters for the video capture device ///  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; } 

现在,只要您的相机支持,您就可以按照您想要的分辨率对屏幕显示进行整理。

接下来,您很快就会发现,在将video写入磁盘时,您所应用的这种新的正确捕获function并未应用。

由于ICaptureBuilder2方法仅支持Avi和Asf(即wmv),因此您需要将mediatype设置为其中一个。

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

您将在SetupGraph函数中找到该行。

Asf仅输出320x240,但Avi将以所需的分辨率输出,但未压缩(意味着1280x720video输入每秒50-60MB),这太高了。

所以这给你留下了两个选择

  1. 了解如何将编码器(压缩filter)添加到Avi输出

  2. 弄清楚如何更改WMV配置文件

我试过1,没有成功。 主要是因为这是我第一次使用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类中创建一个函数

     ///  /// Configure profile from file to Asf file writer ///  ///  ///  ///  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) // Eg no  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. 现在在c:驱动器上创建一个名为wmv.prx的文件,并在其中放置相关信息。

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

现在享受以正确尺寸输出的.wmv文件。 是的,我知道我放入的代码相当杂乱,但我会留给你去修饰它。

Lifecam以设置捕获格式(更具体地说,回归到其他格式)的不明显行为而闻名。 请参阅可能建议您解决方案的prevoius讨论:

  • 无法使IAMStreamConfig.SetFormat()与LifeCam Studio一起使用
  • 流忽略IAMStreamConfig设置 – Microsoft LifeCam Cinema仅在640×480上记录
  • Microsoft LifeCam能否以低于30 fps的帧速率录制?