Ada*_*ley 10 c# directshow directshow.net
好的,我已经在这2天了,需要最后一部分的帮助.
我有一台Microsoft LifeCam Cinema相机,我使用.NET DirectShowLib来捕获视频流.实际上我使用WPFMediaKit,但我现在直接处理直接显示库的源代码.
我的工作是: - 查看摄像机的视频输出 - 以ASF或AVI记录摄像机的视频输出(ICaptureGraphBuilder2支持的唯一2个MediaType)
问题是:我可以将其保存为.avi.这工作正常,分辨率为1280x720,但它将文件保存在RAW输出中.这意味着它大约是每秒50-60MB.方式太高了.
或者我可以将其切换为.asf并输出WMV,但是当我这样做时,捕获和输出都转到分辨率320x240.
在WPFMediaKit中有一个我改变的功能,因为很明显有微软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;
Run Code Online (Sandbox Code Playgroud)
实现后,只要我将SetOutputFilename设置为MediaType.Avi,我就可以最终将捕获的视频视为1280x720.
如果我将它设置为MediaType.如果它转到320x240并且输出相同.
或者AVI以正确的格式工作和输出,但在RAW视频中这样做,因此文件非常大.我试图在图表中添加压缩器,但没有运气,这远远超出了我的经验.
我正在寻找2个答案中的1个.
Ada*_*ley 13
我想通了.因此,我在这里发布任何其他可怜的灵魂,并想知道为什么它不起作用.
下载WPFMediaKit的源代码,您将需要更改一些代码.
转到Folder DirectShow> MediaPlayers并打开VideoCapturePlayer.cs
找到函数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;
}
Run Code Online (Sandbox Code Playgroud)现在,只要您的相机支持,您就可以按照您想要的分辨率对屏幕显示进行分类.
接下来,您很快就会发现,在将视频写入磁盘时,您所应用的这种新的正确捕获功能并未应用.
由于ICaptureBuilder2方法仅支持Avi和Asf(即wmv),因此您需要将mediatype设置为其中一个.
hr = graphBuilder.SetOutputFileName(MediaSubType.Asf, this.m_fileName, out mux, out sink);
Run Code Online (Sandbox Code Playgroud)
您将在SetupGraph函数中找到该行.
ASF将只在320×240的输出,然而阿维将在期望的分辨率输出,但是未压缩的(意思是每秒50-60MB为1280×720的视频馈送),这是太高了.
所以这给你留下了两个选择
了解如何将编码器(压缩过滤器)添加到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类中创建一个函数
/// <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;
}
Run Code Online (Sandbox Code Playgroud)在SetupGraph函数中找到SetOutputFileName并在其下面放置
ConfigProfileFromFile(mux,"c:\ wmv.prx");
现在在c:驱动器上创建一个名为wmv.prx的文件,并在其中放置相关信息.
你可以看到从演示项目这里PRX文件的样本:http://www.codeproject.com/KB/audio-video/videosav.aspx(Pal90.prx)
现在享受以正确尺寸输出的.wmv文件.是的,我知道我放入的代码非常糟糕但是我会留给你去修饰它.
| 归档时间: |
|
| 查看次数: |
11069 次 |
| 最近记录: |