|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| DirectShow hell :( |
|
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| Please help me handle the DirectShow. I'm trying to render a video file without sound to a IDirect3DTexture9 object with the help of DirectShow. I have experience with Direct3D9 but I'm new to DirectShow, therefore my starting point was the following thread on gamedev: LINK While rendering the 1024x512x24 bpp AVI file encoded with Indeo5 codec to my texture I obtain the following results: The white rectangle is the 1024x512 texture that I clear every frame to white before copying the video frame over it. What you can notice is some noise in the top part of the image. This is what gets copied from the video, and it is animated, meaning that this noise changes every frame during the length of the video. Here's the initialization code: //globals IGraphBuilder *m_pGraph; IMediaControl *m_pMediaControl; IMediaPosition *m_pMediaPosition; IMediaEvent *m_pMediaEvent; IBaseFilter *m_pNULLRenderer; IBaseFilter *m_pGrabberBase; ISampleGrabber *m_pVideoGrabber; AM_MEDIA_TYPE mt; //create graph manager CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGraph); //create null renderer CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&m_pNULLRenderer); //add null renderer to graph m_pGraph->AddFilter(m_pNULLRenderer, L"Null Renderer"); //create sample grabber CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&m_pGrabberBase); m_pGrabberBase->QueryInterface(IID_ISampleGrabber, (void**)&m_pVideoGrabber); //set media type of sample grabber ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = GUID_NULL;//MEDIASUBTYPE_RGB32; mt.formattype = FORMAT_VideoInfo; m_pVideoGrabber->SetMediaType(&mt); m_pVideoGrabber->SetBufferSamples(TRUE); m_pVideoGrabber->SetOneShot(FALSE); //add grabber to graph m_pGraph->AddFilter(m_pGrabberBase, L"Sample Grabber"); //automatically build graph based on filename if(FAILED(m_pGraph->RenderFile(L"c:\\intro.avi",L"")))assert(0); //get media interfaces m_pGraph->QueryInterface(IID_IMediaControl, (void**)&m_pMediaControl); m_pGraph->QueryInterface(IID_IMediaEvent, (void**)&m_pMediaEvent); m_pGraph->QueryInterface(IID_IMediaPosition, (void**)&m_pMediaPosition); //create the render texture D3DXCreateTexture(_dx9.GetDevice(),1024,512,1,0,D3DFMT_R8G8B8, D3DPOOL_MANAGED,media.GetTextureByPath(L"cutscene0").GetTexturePointerToPointer()); //start the movie m_pMediaControl->Run(); now, every frame, do long video_buffer_size = 0; unsigned char* video_buffer = NULL; D3DLOCKED_RECT d3dlr; //clear the texture to white media.GetTextureByPath(L"cutscene0").FillWithConstantColor(1,1,1); IDirect3DTexture9 *g_pTexture=media.GetTextureByPath(L"cutscene0").GetTexture(); m_pVideoGrabber->GetCurrentBuffer(&video_buffer_size,NULL); if(video_buffer_size==0) { assert(0); } video_buffer = new unsigned char[video_buffer_size]; if(!video_buffer) { assert(0); } m_pVideoGrabber->GetCurrentBuffer(&video_buffer_size, (long*)video_buffer); if (!FAILED(g_pTexture->LockRect(0,&d3dlr,NULL,0))) { memcpy ((BYTE*)(d3dlr.pBits), (BYTE*)video_buffer, video_buffer_size); g_pTexture->UnlockRect(0); } delete [] video_buffer; I'm a novice to directshow, but for general purpose here's how the GraphEdit shows my graph and it's own graph when playing the same movie file: Circled with red: my graph in the game Circled with blue: the graph create by GraphEdit when selecting "Render Media File" option over the same video file. PLEASE HELP ME PLAY THE VIDEO FILE IN MY GAME! |
||||
|
||||
![]() daviangel Member since: 6/13/2000 From: Marina, CA, United States |
||||
|
|
||||
| Well this may or may not be the cause of your grief but is Indeo codec a supported compression format for DirectShow? Well if anything I know they cause problems on Vista and Win7 so I would try modifying your avi file to use a different format. Indeo Codecs are not supported on any version of the upcoming OS known as “Windows 7″ |
||||
|
||||
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| Indeo5 isn't the problem. Indeo5 codec is installed on my OS. I have also tried Cinepak, MS RLE and other codecs. All behave the same.. |
||||
|
||||
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| OK, One more hint. Tried the same code on Vista Ultimate which resulted in an error on line: m_pVideoGrabber->GetCurrentBuffer(&video_buffer_size,NULL); "video_buffer_size" was set to zero and the function returned a value of -2147220953 which translates to VFW_E_WRONG_STATE. Any ideas? I double checked the rest of methods and they all return S_OK. |
||||
|
||||
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| Anyone experienced this? |
||||
|
||||
![]() feal87 Member since: 3/19/2009 |
||||
|
|
||||
| I experienced the same while making a video player for my engine, you have to use an actual video renderer. Using null renderer will not make anything work. Personal DirectX Related Blog |
||||
|
||||
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| feal87, Could you help with some source code? I am absolutely new to DirectShow. |
||||
|
||||
![]() Maddi Member since: 3/29/2005 From: Germany |
||||
|
|
||||
| My first guess would be that the decoder is missing from your games graph because the sample grabber does not request a specific format. I saw in your code that you commented out the subtype of RGB32 ( mt.subtype = GUID_NULL;//MEDIASUBTYPE_RGB32; ). Didn't that work ? I guess GUID_NULL is too much freedom, maybe you need some other format. check the input pin of the renderer in the blue graph to see what kind of Media Type arrives there and try to use that in your own code. Cheers, Maddi |
||||
|
||||
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| The media type that is shown in the graph editor is MEDIASUBTYPE_Avi, I tried to put this value in the code, but anything that I change results in an error on line: _pVideoGrabber->GetCurrentBuffer(&video_buffer_size,NULL); video_buffer_size is 0. |
||||
|
||||
![]() Maddi Member since: 3/29/2005 From: Germany |
||||
|
|
||||
| MEDIASUBTYPE_Avi does not make much sense I guess, you need RGB or something alike. You could try the following: Instead of using a NULL_Renderer put a real one into it. ( Leave the grabber out for now ). Then remove the real renderer and replace it with the grabber and add a null_renderer at the end. You could also try not to use "RenderFile()" but create the connections yourself. I start to remember how I came to hate DirectShow :) As far as I know there is another API from Microsoft that does not have all the GraphBuilding stuff. Maybe that could make it easier. Cheers, Maddi |
||||
|
||||
![]() vladic2000x Member since: 9/19/2005 From: Chisinau, Moldova, Republic of |
||||
|
|
||||
| By some sort of magic :) I managed to render the video in the game with Null renderer. I tested the program on multiple PCs. It runs everywhere except that on a low performance PC the video slows down. Instead of running 20 seconds as supposed to, it runs 30 seconds. But the most strange to me is when I call the GetCurrentPosition() method of IMediaSeeking interface it returns me the correct time. For instance the slow video is at the second 10 but the GetCurrentPosition() method returns 15. Just wondering maybe the frames are queued somewhere? Any ideas why the slowdown happens? The low performance PC should handle very well the playback, it's not that slow: 1.8Ghz, 128 MB GeForce5 |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|