|
|
|
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
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
|
|