青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 74, 文章 - 0, 評論 - 26, 引用 - 0
數(shù)據(jù)加載中……

在Windows Mobile 5中使用DirectShow控制攝像頭-轉(zhuǎn)

By Amit Ranjan
July 21, 2006

A number of Windows Mobile 5.0 APIs (for example, SHCameraCapture) make it trivial for a mobile application developer to access a camera, but their ease of use comes at a price—flexibility. Most of the time, using the API directly would offer a solution, but sometimes you need more control and flexibility. That's where Microsoft's DirectShow framework comes in. This article shows how to use DirectShow to access a camera. It demonstrates how to build a filter graph manually and how to handle graph events in the application message handler. Having some prior knowledge of DirectShow and COM will be helpful, but it's not necessary.

Figure 1 depicts the components in the filter graph you will use to capture video.

Figure 1: Filter Graph for Video Capture

The camera is the hardware component. For an application to interact with the camera, it would need to talk to its drivers. Next, the video capture filter enables an application to capture video. After capture, you encode the data using WMV9EncMediaObject, a DirectX Media Object (DMO). You can use a DMO inside a filter graph with the help of a DMO Wrapper filter. Next, the encoded video data needs to be multiplexed. You use a Windows Media ASF writer filter for this task. The ASF writer multiplexes the video data and writes it to an .asf file. With that, your filter graph is ready. Now, it's just a matter of running it. As you will see, building the graph is pretty easy too.

Set the Build Environment

First, you need to set the build environment. Add the following libraries in the linker setting of a Visual Studio 2005 Smart Device project:

  • dmoguids.lib
  • strmiids.lib
  • strmbase.lib
  • uuid.lib

Also include the following header files in your project:

  • atlbase.h
  • dmodshow.h
  • dmoreg.h
  • wmcodecids.h

 

Note: For the sake of clarity, this example doesn't show error handling. However, a real world application would require error handling.

Building the Graph

A filter graph that performs audio or video capture is known as a Capture graph. DirectShow provides a Capture Graph Builder object that exposes an interface called ICaptureGraphBuilder2; it exposes methods to help build and control a capture graph.

First, create instances of IGraphBuilder and ICaptureGraphBuilder2 by using the COM function CoCreateInstance:

HRESULT hResult = S_OK;

IGraphBuilder *pFilterGraph;

ICaptureGraphBuilder2 *pCaptureGraphBuilder;

hResult=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,

                         IID_IGraphBuilder,(void**)&pFilterGraph);

hResult=CoCreateInstance(CLSID_CaptureGraphBuilder, NULL,

                         CLSCTX_INPROC, IID_ICaptureGraphBuilder2,

                         (void**)& pCaptureGraphBuilder);

CoCreateInstance takes five parameters:

  1. The first is a class ID.
  2. The second decides whether the object created is part of an aggregator.
  3. The third specifies the context in which the newly created object would run.
  4. The fourth parameter is a reference to the identifier of the interface you will use to communicate with the object.
  5. The last parameter is the address of the variable that receives the interface pointer requested.

Once you have created the IGraphBuilder and ICaptureGraphBulder2 instances, you need to call the SetFilterGraph method of the ICaptureGraphBuilder2 interface:

hResult = m_pCaptureGraphBuilder->SetFiltergraph( pFilterGraph );

The SetFilterGraph method takes a pointer to the IGraphBuilder interface. This specifies which filter graph the capture graph builder will use. If you don't call the SetFilterGraph method, the Capture graph builder automatically creates a graph when it needs it.

Now, you're ready to create an instance of the video capture filter. The following code initializes a Video capture filter, the pointer of which is returned by the CoCreateInstance:

IBaseFilter *pVideoCaptureFilter;

hResult=CoCreateInstance(CLSID_VideoCapture, NULL, CLSCTX_INPROC,

                         IID_IBaseFilter, (void**)&pVideoCaptureFilter);

You then need to get a pointer to IPersistPropertyBag from the video capture filter. You use this pointer to set the capture device (in other words, the camera) that the capture filter will use, as follows:

IPersistPropertyBag *pPropertyBag;

hResult=pVideoCaptureFilter->QueryInterface( &pPropertyBag );

Now, you need to get a handle on the camera you will use to capture video. You can enumerate the available camera devices by using the FindFirstDevice and FindNextDevice functions. You can have multiple cameras present on a device. (HTC Universal is one example.) To keep the code simple for this example, use FindFirstDevice to get the first available camera on the device as follows:

DEVMGR_DEVICE_INFORMATION devInfo;

CComVariant  CamName;

CPropertyBag PropBag;

GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93,

                    0x3E, 0x4D, 0x7E, 0x3C, 0x86 };

devInfo.dwSize = sizeof(devInfo);

FindFirstDevice( DeviceSearchByGuid, &guidCamera, & devInfo);

CamName=devInfo.szLegacyName

PropBag.Write( _T("VCapName"), &CamName );

pPropertyBag->Load( &PropBag, NULL );

hResult =pFilterGraph->AddFilter( pVideoCaptureFilter,

                                  _T("Video Capture Filter") );

pPropertyBag.Release();

Note the first parameter in the FindFirstDevice, DeviceSearchByGuid. It specifies the search type. Other options are DeviceSearchByLegacyName, DeviceSearchByDeviceName, and so forth. DeviceSearchByGuid is the most reliable way to find a capture device. The information regarding the device is returned in the DEVMGR_DEVICE_INFORMATION structure. You store the szLegacyName value in the CComVariant variable, and you need an object that has implemented IPropertyBag interface.

In the code sample, CPropertyBag is a custom class that has implemented IPropertyBag. This object is needed to pass the capture device name to the filter. The string VCapName identifies the filter property for the name of the video capture device. Once you have set the capture device, you can add the Video capture filter to the filter graph. You use the AddFilter method of the graph manager for this. This method takes two parameters: the first is the pointer to the filter that is to be added, and the second is the name of the filter. The second parameter can be NULL; in this case, the filter graph manager generates a unique name for the filter. If you have provided a name that conflicts with some other filter, the manager will modify the name to make it unique.

You then need to instantiate the WMV9 encoder:

IBaseFilter *pVideoEncoder;

IDMOWrapperFilter *pWrapperFilter;

hResult=CoCreateInstance(CLSID_DMOWrapperFilter, NULL,CLSCTX_INPROC,

                         IID_IBaseFilter, (void**)&pVideoEncoder);

hResult =pVideoEncoder->QueryInterface( &pWrapperFilter );

hResult =pWrapperFilter->Init( CLSID_CWMV9EncMediaObject,

                               DMOCATEGORY_VIDEO_ENCODER );

hResult=pFilterGraph->AddFilter( pVideoEncoder, L"WMV9DMO Encoder");

Because the WMV9 encoder is a DMO, you can't add/use it like other filters. But DirectShow provides a wrapper filter that enables you to use a DMO like any other filter. You first create an instance of the DMO wrapper filter and then initialize the WMV9 encoder DMO with it. After initializing the DMO, you add it into the filter graph as follows:

IBaseFilter *pASFMultiplexer;

IFileSinkFilter *pFileSinkFilter;

hResult = pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Asf, T("\\test.asf"), &pASFMultiplexer, &pFileSinkFilter );

You have added the source and the transform filter in the filter graph, so the last thing remaining is adding a sink filter in the graph. For this, you call the SetOutputFileName method of ICaptureGraphBuilder2. The first parameter is a media subtype; the second parameter is the name of the file in which you want to save the video; the third parameter is the address of a pointer that receives the multiplexer's interface; and the fourth parameter receives the file writers' interface.

With that, your filter graph is ready. All you need to do is connect the source filter, encoder, and multiplexer. You can achieve this by using the RenderStream method of the graph builder, as follows:

hResult = pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE,

                                         &MEDIATYPE_Video,

                                         m_pVideoCaptureFilter,

                                         pVideoEncoder,

                                         pASFMultiplexer );

 

The first parameter is the pin category, which can be NULL to match any category.The second parameter specifies the media type. The third, fourth, and fifth parameters specify a starting filter, an intermediate filter, and a sink filter, respectively. The method connects the source filter to the transform filter and then the transform filter to the sink filter.

Now your graph is ready, and you can start capturing the video.

Controlling the Graph

Before capturing video, you need two more things: the ImediaEventEx and IMediaControl pointers. IMediaEventEx derives from IMediaEvent, which supports event notification from the filter graph and individual filters to the application.ImediaEventEx provides a method to the register window that receives a message when any event occurs.

IMediaControl is an interface exposed by the filter graph that allows an application to control the streaming media through the graph. The application can use this to start, stop, or pause the running graph.The following code sample first queries the filter graph for its IMediaEventEx interface. Once it gets the pointer to the IMediaEventEx interface, it then calls its method SetNotifyWindow, passing it the handle to the window that handles the message. The second parameter is the message that will be passed as notification to the Windows message handler. The third parameter is the instance data (this can be 0):

IMediaEventEx *pMediaEvent;

IMediaControl *pMediaControl;

#define WM_GRAPHNOTIFY WM_APP+1

hResult =pFilterGraph->QueryInterface( IID_IMediaEventEx, (void**)&pMediaEvent );

hResult =pMediaEvent->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY,0);

hResult=pFilterGraph->QueryInterface(&pMediaControl);

hResult =pMediaControl->Run();

When an event occurs, DirectShow will send WM_GRAPHNOTIFY to the specified windows.

Note: WM_GRAPHNOTIFY is used here as an example. This can be any application-defined message.

Next, you get the pointer to the IMediaControl interface. You'll use this interface to control the graph. Call its Run method to put the entire graph into a running state. The following code shows how to start and stop capture by throwing the

ControlStream method of CaptureGraphBuilder:

LONGLONG dwStart  = 0, dwEnd = 0;

WORD wStartCookie = 1, wEndCookie = 2;

dwEnd=MAXLONGLONG;

 

//start capturing

hResult=pCaptureGraphBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pVideoCaptureFilter, &dwStart, &dwEnd,wStartCookie, wEndCookie);

 

//Stop capturing

dwStart=0;

hResult=pFilterGraph->QueryInterface(&pMediaSeeking );

hResult=pMediaSeeking->GetCurrentPosition( &dwEnd );

hResult= pCaptureGraphBuilder->ControlStream(

   &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVideoCaptureFilter,

   &dwStart, &dwEnd, wStartCookie, wEndCookie );

The code uses the search criteria supplied in the method call to locate an output pin on the capture filter. ControlStream enables an application to control streams without it needing to enumerate filters and pins in the graph.Start and End specify the start and stop times (MAX_LONGLONG is the largest possible reference time value). When you start, the End is set to MAXLONLONG. When you want to stop, you first get the current position of the stream by using the GetCurrentPosition method of the IMediaSeeking interface. You then call the ControlStream method with Start set at 0 and End set at the current position.You now have the graph ready and running. You can start using it to capture and save in an .asf file.

Handling the Graph Events

Because an application will control the graph, you need to write the code to facilitate that. You already have registered the window and message with the filter graph, so the only thing remaining is to handle the message in the window's message handler as follows:

BOOL CALLBACK VidCapDlgProc(HWND hDlg,UINT Msg,WPARAM wParam, LPARAM lParam)

{

   ... ... ... ...

   case WM_GRAPHNOTIFY:

      {

         ProcessGraphMessage();

      }

   ... ... ... ...

}

ProcessGraphMessage()

{

   HRESULT hResult=S_OK;

   long leventCode, param1, param2;

   while(hResult=pEvent->GetEvent(&leventCode, &param1, &param2, 0),

   SUCCEEDED(hResult))

   {

      hResult = pEvent->FreeEventParams(leventCode, param1, param2);

      if (EC_STREAM_CONTROL_STOPPED == leventCode)

      {

         pMediaControl->Stop();

         break;

      }

      else if(EC_CAP_FILE_COMPLETED== leventCode)

      {

         //Handle the file capture completed event

      }

      else if(EC_CAP_FILE_WRITE_ERROR== leventCode)

      {

         //Handle the file write error event

      }

   }

}

You handle the WM_GRAPHNOTIFY message in the windows handler. DirectShow sends this message to the application when any event arises. The application calls a user-defined method to process the events. The GetEvent method of the IMediaEvent interface retrieves the event code and two event parameters from the queue.Because the message loop and event notification are asynchronous, the queue might hold more then one event. Hence, the GetEvent code is called in a loop until it returns a failure code. Also, whenever you call GetEvent, it's important to call FreeEvent to free the resource associated with the event parameter. And, being the good programmer that you are, you won't forget to release the resources afterwards, will you? Call Release on every object that you have created, as follows:

PVideoCaptureFilter->Release ();

pVideoEncoder->Release ();

pMediaEvent ->Release();

pMediaSeeking ->Release();

pASFMultiplexer->Release();

pFileSinkFilter->Release();

pWrapperFilter ->Release();

pFilterGraph->Release();

pCaptureGraphBuilder->Release();

 

What Have You Learned?

You now understand how to create, run, and control a filter graph manually. By using the DirectShow framework to capture from a camera, you gain good control with ease.

posted on 2008-11-28 14:06 井泉 閱讀(7853) 評論(10)  編輯 收藏 引用

評論

# re: 在Windows Mobile 5中使用DirectShow控制攝像頭-轉(zhuǎn)  回復(fù)  更多評論   

LZ對我?guī)椭艽?。:?

《編程使用手機攝像頭》
http://whbell.spaces.live.com/blog/cns!5EE1383181C65478!194.entry

2009-01-24 13:41 | bell.wang

# re: 在Windows Mobile 5中使用DirectShow控制攝像頭-轉(zhuǎn)  回復(fù)  更多評論   

頂一下,還不錯
2010-03-09 16:06 | nfl 2010

# re: 在Windows Mobile 5中使用DirectShow控制攝像頭-轉(zhuǎn)  回復(fù)  更多評論   

頂一下,還不錯 頂一下,還不錯
2010-06-03 00:11 | baby loopstoel

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲高清精品中出| 亚洲精品国产精品国自产观看浪潮| 夜夜嗨av一区二区三区网站四季av | 国产亚洲精品v| 国产亚洲aⅴaaaaaa毛片| 欧美国产精品日韩| 欧美高清视频免费观看| 久久伊人一区二区| 免费不卡中文字幕视频| 欧美福利一区二区| 亚洲日本欧美日韩高观看| 亚洲人成绝费网站色www| 99热这里只有成人精品国产| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 美女亚洲精品| 欧美国产视频在线| 国产精品第一页第二页第三页| 国产精品久久久久毛片大屁完整版| 国产精品综合久久久| 狠狠色伊人亚洲综合网站色| 亚洲国产日韩精品| 亚洲欧美日韩区| 蜜桃av综合| 一区电影在线观看| 久久亚洲精品一区二区| 欧美伦理视频网站| 国内精品久久久久影院薰衣草| 亚洲乱码国产乱码精品精| 性欧美激情精品| 欧美激情一区| 午夜老司机精品| 欧美激情视频一区二区三区在线播放| 国产精品国产三级国产普通话三级 | 99视频精品| 亚洲欧美中文另类| 亚洲国产成人精品久久久国产成人一区 | 亚洲一区二区欧美日韩| 久久久亚洲国产美女国产盗摄| 最新日韩av| 久久久久亚洲综合| 国产热re99久久6国产精品| 99riav国产精品| 久久久综合香蕉尹人综合网| 一区二区三区色| 欧美黄色免费| 亚洲人成在线观看网站高清| 久久久久www| 亚洲欧美精品中文字幕在线| 欧美精品九九99久久| 亚洲大片在线| 久久亚洲精品视频| 欧美影院成年免费版| 国产精品网站在线| 国自产拍偷拍福利精品免费一| 国产精品一区二区久久精品| 久久男女视频| 免费在线视频一区| 国产精品毛片va一区二区三区 | 欧美14一18处毛片| 国产精品亚洲аv天堂网| 亚洲丰满在线| 美女诱惑一区| 久久精品国内一区二区三区| 国产热re99久久6国产精品| 亚洲视频一区在线观看| 亚洲欧洲日本国产| 亚洲综合电影| 欧美日韩日本网| 一区二区三区日韩欧美| 亚洲日产国产精品| 欧美三级在线| 亚洲一区在线观看免费观看电影高清| 亚洲国产精品成人| 欧美激情一区二区| 一本色道久久综合亚洲精品按摩| 亚洲黄色在线视频| 欧美韩日高清| 亚洲欧美国产精品桃花| 国产欧美一区二区精品秋霞影院| 欧美一区二区精品久久911| 亚洲一区二区在线视频| 国产区在线观看成人精品| 噜噜噜在线观看免费视频日韩 | 欧美午夜精品久久久久免费视 | 亚洲日产国产精品| 欧美日韩日本网| 亚洲欧美第一页| 久久国产精品高清| 亚洲国产视频一区| 一本色道久久综合亚洲精品高清| 国产精品毛片va一区二区三区| 久久福利精品| 你懂的亚洲视频| 亚洲一区二区在线免费观看视频 | 亚洲欧美国产视频| 午夜精品在线看| 在线日韩av| 亚洲作爱视频| 一区二区在线视频观看| 99精品福利视频| 激情久久久久久久| 亚洲免费观看在线观看| 国产丝袜美腿一区二区三区| 久久久蜜桃精品| 欧美大胆a视频| 在线亚洲高清视频| 国产在线欧美| 一区二区三欧美| 91久久精品一区二区别| 中文精品一区二区三区| 亚洲高清网站| 欧美在现视频| 亚洲欧美成人精品| 欧美激情视频在线免费观看 欧美视频免费一| 亚洲在线视频观看| 欧美韩日一区二区三区| 噜噜噜在线观看免费视频日韩| 国产精品一卡| 亚洲伦理久久| 亚洲日本成人女熟在线观看| 欧美一区二区啪啪| 午夜欧美不卡精品aaaaa| 欧美日本国产一区| 亚洲电影免费在线观看| 99视频日韩| 在线观看欧美视频| 欧美一二三区精品| 午夜久久资源| 国产精品免费在线| 一区二区av在线| 99re6热只有精品免费观看| 久久综合伊人77777麻豆| 久久婷婷麻豆| 激情文学一区| 久久久久一区二区三区四区| 久久精品国产免费看久久精品| 国产精品久久久一区麻豆最新章节| 亚洲激情一区二区三区| 日韩午夜在线观看视频| 欧美激情久久久| 韩国精品在线观看| 影音先锋中文字幕一区二区| 欧美中文日韩| 久久综合久久美利坚合众国| 国产亚洲一级| 久久成人精品无人区| 久久久精品五月天| 激情国产一区| 欧美成人国产| 亚洲美女中出| 久久九九精品99国产精品| 欧美另类在线播放| 日韩午夜电影| 亚洲免费一在线| 国产色综合久久| 久久综合伊人77777| 亚洲欧洲在线看| 亚洲午夜三级在线| 国产亚洲一区精品| 美女视频一区免费观看| 亚洲精品国产精品国产自| 亚洲影音先锋| 黄网动漫久久久| 欧美日韩国产不卡| 亚洲综合色视频| 美女91精品| 夜夜躁日日躁狠狠久久88av| 国产精品乱子久久久久| 久久婷婷激情| 亚洲深夜av| 免费成人av在线| 欧美一级视频一区二区| 国产偷自视频区视频一区二区| 久久高清福利视频| 亚洲国产老妈| 欧美一区不卡| 亚洲精品在线视频| 国产精品专区h在线观看| 另类图片综合电影| 亚洲一区二区免费视频| 欧美成人精精品一区二区频| 亚洲图片在线观看| 亚洲动漫精品| 国产精品毛片a∨一区二区三区|国| 久久综合久久综合久久综合| 亚洲色图自拍| 亚洲国产精品日韩| 久久久www| 亚洲自拍电影| 日韩亚洲精品在线| 在线免费高清一区二区三区| 国产精品久久久久毛片软件 | 久久久最新网址| 一本久久青青| 91久久精品国产91性色tv| 久久久久青草大香线综合精品| 亚洲性av在线| 亚洲天堂av高清| 一本久久精品一区二区| 亚洲黄色毛片|