Directshow中使用IAMStreamConfig接口改变摄像头分辨率
【转自】http://blog.youkuaiyun.com/yanqiao1986/archive/2010/04/02/5445486.aspx
实验室的江同学在一个有关摄像头的小项目中用到Directshow在.net平台上的封装DshowNet,该项目运行时在显示视频之前都会弹出一个视频属性配置窗口要求手动配置如分辨率等视频属性。江同学要求能够去除这个弹出窗口而在代码中设置分辨率等属性。
于是定位到源码当中的ShowCapPinDialog函数
- public static bool ShowCapPinDialog( ICaptureGraphBuilder2 bld, IBaseFilter flt, IntPtr hwnd )
- {
- int hr;
- object comObj = null;
- ISpecifyPropertyPages spec = null;
- DsCAUUID cauuid = new DsCAUUID();
- try
- {
- Guid cat = PinCategory.Capture;
- Guid type = MediaType.Interleaved;
- Guid iid = typeof(IAMStreamConfig).GUID;
- hr = bld.FindInterface(ref cat, ref type, flt, ref iid, out comObj);
- if (hr != 0)
- {
- type = MediaType.Video;
- hr = bld.FindInterface(ref cat, ref type, flt, ref iid, out comObj);
- if (hr != 0)
- return false;
- }
- spec = comObj as ISpecifyPropertyPages;
- if (spec == null)
- return false;
- hr = spec.GetPages(out cauuid);
- hr = OleCreatePropertyFrame(hwnd, 30, 30, null, 1,
- ref comObj, cauuid.cElems, cauuid.pElems, 0, 0, IntPtr.Zero);
- return true;
- }
- catch (Exception ee)
- {
- Trace.WriteLine("!Ds.NET: ShowCapPinDialog " + ee.Message);
- return false;
- }
- finally
- {
- if (cauuid.pElems != IntPtr.Zero)
- Marshal.FreeCoTaskMem(cauuid.pElems);
- spec = null;
- if (comObj != null)
- Marshal.ReleaseComObject(comObj); comObj = null;
- }
- }
在改源码中弹出的窗口是IAMStreamConfig的属性页。
于是想想使用IAMStreamConfig接口即能设定视频的分辨率。
搜了下发现http://topic.youkuaiyun.com/u/20080827/17/8b2dcced-316f-4b9d-80f6-e4776931ec73.html这个帖子中涉及到这个问题。12楼大虾的回帖很有参考价值。
因为摄像头只能支持固定的几种分辨率,所以必须枚举该摄像头支持的几种分辨率再判断该设置成哪种。
修改后的代码如下。
- public static bool ShowCapPinDialog( ICaptureGraphBuilder2 bld, IBaseFilter flt, IntPtr hwnd )
- {
- int hr;
- object comObj = null;
- IAMStreamConfig pamsc = null;
- try
- {
- Guid cat = PinCategory.Capture;
- Guid type = MediaType.Interleaved;
- Guid iid = typeof(IAMStreamConfig).GUID;
- hr = bld.FindInterface(ref cat, ref type, flt, ref iid, out comObj);
- if (hr != 0)
- {
- type = MediaType.Video;
- hr = bld.FindInterface(ref cat, ref type, flt, ref iid, out comObj);
- if (hr != 0)
- return false;
- }
- pamsc = comObj as IAMStreamConfig;
- if (pamsc == null)
- return false;
- int count;
- int size;
- hr = pamsc.GetNumberOfCapabilities(out count, out size);
- IntPtr pt = Marshal.AllocHGlobal(128);
- for (int iFormat = 0; iFormat < count; iFormat++)
- {
- AMMediaType ammtp = new AMMediaType();
- hr = pamsc.GetStreamCaps(iFormat, out ammtp, pt);
- if (hr == 0)
- {
- VideoInfoHeader pvihdr = new VideoInfoHeader();
- Marshal.PtrToStructure(ammtp.formatPtr, pvihdr);
- if (pvihdr.BmiHeader.Width == 176)
- {
- pvihdr.AvgTimePerFrame = 10000000 / 15;
- hr = pamsc.SetFormat(ammtp);
- break;
- }
- }
- }
- return true;
- }
- catch (Exception ee)
- {
- Trace.WriteLine("!Ds.NET: ShowCapPinDialog " + ee.Message);
- return false;
- }
- finally
- {
- pamsc = null;
- if (comObj != null)
- Marshal.ReleaseComObject(comObj);
- comObj = null;
- }
- }
上面代码简单描述了IAMStreamConfig接口的用法,最后将摄像头属性设置为分辨率176*144的模式。
发表于 @ 2010年04月02日