Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
Windos
win32.3rdparty
win32.directx.audio
win32.directx.ddk
win32.directx.graphics
win32.directx.input
win32.directx.managed
win32.directx.misc
win32.directx.networking
win32.directx.sdk
win32.directx.video
win32.dirx.grap.shaders
win32.gdi
win32.international
win32.kernel
win32.messaging
win32.mmedia
win32.networks
win32.ole
win32.rtc
win32.tapi
win32.tapi.beta
win32.tools
win32.ui
win32.wince
win32.wmi
windows.mediacenter
winfx.aero
winfx.announcements
winfx.avalon
winfx.collaboration
winfx.fundamentals
winfx.general
winfx.indigo
winfx.sdk
winfx.winfs
  
 
date: Sat, 28 Jun 2008 12:38:14 +0800,    group: microsoft.public.win32.programmer.directx.video        back       


using WM9 encoder to capture video cannot work with custom transform filter   
Although this is for DirectShow mobile, I decided to post it here as there 
have been no replies when I post on microsoft.public.pocketpc.developer.

I am using on the CameraCaptureSample to capture a video. Although the 
sample on its own works well, I want to improved it to grab the raw camera 
data and work on it. I have successfully written and added my null transform 
filter (CTransInPlaceFilter) to the graph by using the following code:

....
// prepare the preview graph
hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, 
&MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, NULL);

//find the default renderer
hr = pFilterGraph->FindFilterByName(L"Video Renderer", &pVidRenderer);

//get input pin of the default renderer
IPin* ipin = GetPin(pVidRenderer, PINDIR_INPUT);

//find out who the renderer is connected to and disconnect from them
IPin* opin;
hr = ipin->ConnectedTo(&opin);
hr = ipin->Disconnect(); //disconnect default renderer output pin
hr = opin->Disconnect(); //disconnect video source output pin

//create our null transform filter
hr = pNullTransform.CoCreateInstance(CLSID_NullNull);
hr = pFilterGraph->AddFilter(pNullTransform, L"NullNull");

//find the input pin of the null transform filter and connect it to the 
output of the video source
IPin* nullRendIn = GetPin(pNullTransform, PINDIR_INPUT);
hr = pFilterGraph->Connect(opin, nullRendIn);

//connect the output of the null transform filter to the default renderer
IPin* nullRendOut = GetPin(pNullTransform, PINDIR_OUTPUT);
hr = pFilterGraph->Connect(nullRendOut, ipin);

//media control object
hr = pFilterGraph->QueryInterface(IID_IMediaControl, (void 
**)&pMediaControl);

//run the graph
hr = pMediaControl->Run();
........

After this I can see that my null transform filter can receive the media 
sample in its function HRESULT Transform(IMediaSample *pSample) and I can 
successfully convert the buffer into the a bitmap file. This means, the null 
transform filter is working well.

However, with the presence of the null transform filter in the graph, I can 
no longer capture video into ASF file by using the sample code. I initialize 
the WM9 encoder as followed (copied from the sample code):

 // Create the video encoder
CHK( pVideoEncoder.CoCreateInstance( CLSID_DMOWrapperFilter ));
CHK( pVideoEncoder.QueryInterface( &pWrapperFilter ));

// Load the WMV9 DMO
CHK( pWrapperFilter->Init( CLSID_CWMV9EncMediaObject, 
DMOCATEGORY_VIDEO_ENCODER ));

// Everything succeeded, let's add the encoder to the graph
CHK( pFilterGraph->AddFilter( pVideoEncoder, L"WMV9 DMO Encoder" ));

// file to save video to
CHK( m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Asf, 
L\\test.asf, &pASFMultiplexer, &pFileSinkFilter ));

// Connect the video capture filter, the encoder and the multiplexer 
together
CHK( m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, 
&MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer));

This code is put just before pMediaControl->Run() and there is no error.

To start capturing:

LONGLONG dwStart = 0, dwEnd = 0;
WORD  wStartCookie = 1, wEndCookie = 2;
CaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, 
NULL, &dwStart, &dwEnd, wStartCookie, wEndCookie );

To stop capturing:

dwStart = 0;
CHK( pFilterGraph->QueryInterface( &pMediaSeeking ));
CHK( pMediaSeeking->GetCurrentPosition( &dwEnd ));
CHK( m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, 
&MEDIATYPE_Video, NULL, &dwStart, &dwEnd, wStartCookie, wEndCookie ));
There are no errors, all HRESULTs return S_OK, but the video file is not 
created! If, however, I removed my custom filter from the graph then the 
video is captured properly.

Any ideas what the problem is? Thanks a lot!
date: Sat, 28 Jun 2008 12:38:14 +0800   author:   minhdanh

Re: using WM9 encoder to capture video cannot work with custom transform filter   
From: "minhdanh"

[...]
> all HRESULTs return S_OK, but the video file is not
> created! If, however, I removed my custom filter from the
> graph then the video is captured properly.

I had almost exactly the same problem and I think the issue 
was on the way the sample handles messages and events. I 
rewrote it from scratch (without the GUI) and everything 
worked as expected at first try.


-- 
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
date: Sat, 28 Jun 2008 01:34:50 -0400   author:   Alessandro Angeli

Re: using WM9 encoder to capture video cannot work with custom transform filter   
I figured it out. The problem has nothing to do with the custom transform 
filter or with the WM9 encoder. The problem is because my main message loop 
takes too much CPU time. Therefore without the custom transform filter, the 
WM9 encoder would still have enough time to encode the video (although many 
frames are dropped). With the transform filter in place, there is no CPU 
time for the WM9 encoder, and no files are created!

Old code:

 // Main message loop:
 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
 while(msg.message!=WM_QUIT)
 {
  if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }

New code:

 // Main message loop:
 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
 while(msg.message!=WM_QUIT)
 {
  if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
  else
  {
    //this solves the problem!!!
    Sleep(100);
  }
 }

Most of the time, PeekMessage return immediately without getting any 
meaningful messages, causing the WHILE loop to keep on repeating and consume 
too much CPU time. I fix the problem by adding a delay between the 
iterations of the while loop, giving other threads in the program enough CPU 
time.
date: Mon, 7 Jul 2008 23:11:50 +0800   author:   minhdanh

Re: using WM9 encoder to capture video cannot work with custom transform filter   
From: "minhdanh"

[...]
> Most of the time, PeekMessage return immediately without
> getting any meaningful messages, causing the WHILE loop
> to keep on repeating and consume too much CPU time. I fix
> the problem by adding a delay between the iterations of
> the while loop, giving other threads in the program
> enough CPU time.

That is how PeekMessage() is supposed to work and that is 
*not* how you create a message loop:

http://msdn.microsoft.com/en-us/library/ms644928(VS.85).aspx

You either use GetMessage() or 
MsgWaitForMultipleObjects[Ex]() + PeekMessage(), so that you 
will be blocked when there are no messages instead of 
needlessly polling the message queue. The lazy polling using 
PeekMessage() + Sleep() will not dispatch messages during 
Sleep(), delaying the processing.


-- 
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
date: Tue, 8 Jul 2008 14:12:19 -0400   author:   Alessandro Angeli

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us