尽管分辨率发生变化,视频捕捉输出始终为 320x240
好的,我已经这样做了 2 天,需要有关最后一部分的帮助。
我有一台 Microsoft LifeCam Cinema 摄像机,并使用 .NET DirectShowLib 捕获视频流。好吧,实际上我使用 WPFMediaKit,但我现在在直接处理直接显示库的源代码中。
我的工作内容是: - 查看摄像机的视频输出 - 以 ASF 或 AVI 格式记录相机的视频输出(ICaptureGraphBuilder2 支持的唯一 2 种 MediaType)
问题是:我可以将其另存为 .avi。这在 1280x720 分辨率下工作正常,但它以 RAW 输出保存文件。这意味着每秒大约 50-60MB。太高了。
或者我可以将其切换为 .asf 并输出 WMV,但当我这样做时,捕获和输出的分辨率都变为 320x240。
在 WPFMediaKit 中,我更改了一个函数,因为显然使用 Microsoft 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,我最终就可以以 1280x720 的分辨率查看捕获的视频。
如果我将其设置为 MediaType.Asf,它将变为 320x240 并且输出是相同的。
或者 AVI 以正确的格式工作和输出,但在 RAW 视频中这样做,因此文件大小非常大。我尝试在图表中添加压缩器,但没有成功,这远远超出了我的经验。
我正在寻找 2 个答案中的 1 个。
- 以 1280x720 录制 ASF
- 向图表中添加压缩器,以便输出的 AVI 文件大小较小。
Ok I have been at this for 2 days and need help with this last part.
I have a Microsoft LifeCam Cinema camera and I use the .NET DirectShowLib to capture the video stream. Well actually I use WPFMediaKit, but I am in the source code of that dealing directly with the direct show library now.
What I have working is:
- View the video output of the camera
- Record the video output of the camera in ASF or AVI (the only 2 MediaType's supported with ICaptureGraphBuilder2)
The problem is: I can save it as a .avi. This works fine and at a resolution of 1280x720 but it saves the file in RAW output. Meaning it is about 50-60MB per second. Way too high.
Or I can switch it to .asf and it outputs a WMV, but when I do this the capture and the output both go to resolution 320x240.
In WPFMediaKit there is a function I changed because apparently with Microsoft LifeCam Cinema cameras a lot of people have this problem. So instead of creating or changing the AMMediaType you iterate through and then use that to call 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;
When that was implemented I could finally view the captured video as 1280x720 as long as I set the SetOutputFilename to a MediaType.Avi.
If I set it to a MediaType.Asf it goes to 320x240 and the output is the same.
Or the AVI works and outputs in the correct format but does so in RAW video, hence a very large file size. I have attempted to add a compressor to the graph but with no luck, this is far out of my experience.
I am looking for 1 of 2 answers.
- Recording the ASF at 1280x720
- Adding a compressor to the graph so that the filesize of my outputted AVI is small.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想通了。因此,我将其发布在这里,供其他路过的可怜人想知道为什么它不起作用。
下载 WPFMediaKit 的源代码,您将需要更改一些代码。
转到文件夹 DirectShow > MediaPlayers 并打开 VideoCapturePlayer.cs
找到函数 SetVideoCaptureParameters 并将其替换为:
现在,只要您的相机支持,它就会以您想要的分辨率排序您的屏幕显示。
接下来,您很快就会发现,在将视频写入磁盘时,您没有应用这个新的正确捕获。
由于 ICaptureBuilder2 方法仅支持 Avi 和 Asf(即 wmv),因此您需要将媒体类型设置为其中之一。
您将在 SetupGraph 函数中找到该行。
Asf 只能以 320x240 输出,而 Avi 将以所需的分辨率输出,但未压缩(意味着 1280x720 视频源每秒 50-60MB),这太高了。
因此,您有 2 个选择
了解如何将编码器(压缩过滤器)添加到 Avi 输出
了解如何更改 WMV 配置文件
我尝试过 1,但没有成功。主要是因为这是我第一次使用DirectShow,仅仅掌握了图形的含义。
但我在#2 上取得了成功,这就是我是如何做到的。
特别感谢(http://www.codeproject.com/KB/audio-video/videosav.aspx)我从这里提取了所需的代码。
从 http 下载演示项目://www.codeproject.com/KB/audio-video/videosav.aspx 并将 WMLib.cs 复制并粘贴到您的项目中(根据需要更改命名空间)
在 VideoCapturePlayer 中创建一个函数。 CS类
在SetupGraph函数中找到SetOutputFileName并在其下方放置
ConfigProfileFromFile(mux, "c:\wmv.prx");
现在在您的 c: 驱动器上创建一个名为 wmv.prx 的文件,并将相关信息放入其中。
您可以在此处查看演示项目中的 PRX 文件示例:http://www.codeproject.com /KB/audio-video/videosav.aspx (Pal90.prx)
现在享受以正确大小输出的 .wmv 文件。
是的,我知道我放入的代码相当杂乱,但我将让您来完善它。
I figured this out. So I am posting it here for any other poor soul who passes by wondering why it doesn't work.
Download the source of the WPFMediaKit, you are going to need to change some code.
Go to Folder DirectShow > MediaPlayers and open up VideoCapturePlayer.cs
Find the function SetVideoCaptureParameters and replace it with this:
Now that will sort out your screen display at what ever desired resolution you want, provided that your camera supports it.
Next you will soon figure out that this new correct capture you have isnt applied when writing the video to disk.
Since the ICaptureBuilder2 method only supports Avi and Asf (which is wmv) you need to set your mediatype to one of them.
You will find that line in the SetupGraph function.
Asf will only output in 320x240, yet the Avi will output in the desired resolution, but uncompressed (meaning 50-60MB per second for a 1280x720 video feed), which is too high.
So that leaves you with 2 options
Figure out how to add a encoder (compression filter) to the Avi output
Figure out how to change the WMV profile
I tried 1, with no success. Mainly due to the fact this is my first time working with DirectShow and only just grasp the meaning of graphs.
But I was successful with #2 and here is how I did it.
Special thanks to (http://www.codeproject.com/KB/audio-video/videosav.aspx) I pulled out the needed code from here.
Download the demo project from http://www.codeproject.com/KB/audio-video/videosav.aspx and copy and paste the WMLib.cs into your project (change the namespace as necessary)
Create a function in the VideoCapturePlayer.cs class
In the SetupGraph function find the SetOutputFileName and below it put
ConfigProfileFromFile(mux, "c:\wmv.prx");
Now create a file called wmv.prx on your c: drive and place the relevant information in it.
You can see a sample of a PRX file from the demo project here: http://www.codeproject.com/KB/audio-video/videosav.aspx (Pal90.prx)
And now enjoy your .wmv file outputted at the right size.
Yes I know the code I placed in was rather scrappy but I will leave it up to you to polish it up.
Lifecam 因设置捕获格式(更具体地说,回退到其他格式)时的不明显行为而闻名。请参阅之前的讨论,这些讨论可能会建议您解决方案:
Lifecam is known for unobvious behavior with setting capture format (more specifically, falling back to other formats). See prevoius discussions which are likely to suggest you a solution: