avi_mapDecode.cpp

Go to the documentation of this file.
00001 // File avi_mapDecode.cpp
00002 
00003 
00004 // This form of decoding might be useful for formats that cant be decoded by VFW
00005 // but it hasn't been tested or finised yet. At the moment all it might do is
00006 // write bitmaps from the data stream. 
00007 // Might be abue to get frames by using the media position interface.
00008 
00009 #pragma warning( disable : 4311 4312 4133)
00010 
00011 #define _WIN32_DCOM 
00012 
00013 #include <windows.h>
00014 #include <atlbase.h>
00015 #include <stdio.h>
00016 #include <dshow.h>
00017 #include "streams.h"   // for CMedia
00018 #include "qedit.h"     // for ISample
00019 
00020 struct __declspec(uuid("{1125E600-3F8F-4856-9491-34B1443B0E60}")) CLSID_TransSmpte;
00021 
00022 class CTransSmpte : public CTransInPlaceFilter {
00023 public:
00024     HRESULT Transform(IMediaSample *pSample);
00025     HRESULT CheckInputType(const CMediaType *mtIn);
00026     HRESULT SetMediaType( PIN_DIRECTION pindir, const CMediaType *pMediaType);
00027     // Constructor
00028     CTransSmpte( LPUNKNOWN punk, HRESULT *phr );
00029     ~CTransSmpte( );
00030 private:
00031     int         m_nWidth;
00032     int         m_nHeight;
00033     HBITMAP     m_DibSection;
00034     HDC         m_DC;
00035     void *      m_pDibBits;
00036     HGDIOBJ     m_OldObject;
00037     double      m_dFPS;
00038 };
00039 
00040 HRESULT GetInterfaces(void);
00041 HRESULT CaptureVideo();
00042 HRESULT SetupVideoWindow(void);
00043 HRESULT HandleGraphEvent(void);
00044 
00045 void Msg(TCHAR *szFormat, ...);
00046 void CloseInterfaces(void);
00047 void ResizeVideoWindow(void);
00048 
00049 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
00050 
00051 #define JIF(x) if (FAILED(hr=(x))) \
00052     {Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n\0"), hr); return hr;}
00053 
00054 #define DEFAULT_VIDEO_WIDTH     320
00055 #define DEFAULT_VIDEO_HEIGHT    240
00056 
00057 #define APPLICATIONNAME TEXT("AVI GET FRAME \0")
00058 #define CLASSNAME       TEXT("OFX:AVI_READER\0")
00059 
00060 // Application-defined message to notify app of filtergraph events
00061 #define WM_GRAPHNOTIFY  WM_APP+1
00062 
00063 char bmproot[255]="c:\\rsfz";
00064 HWND ghApp=0;
00065 BOOL bDir=TRUE;
00066 long framecount=0;
00067 BOOL b32=FALSE;
00068 char MediaFile[255];
00069 
00070 IVideoWindow  * g_pVW = NULL;
00071 IMediaControl * g_pMC = NULL;
00072 IMediaEventEx * g_pME = NULL;
00073 IMediaFilter  * g_pMF = NULL;
00074 IGraphBuilder * g_pGraph = NULL;
00075 ICaptureGraphBuilder2 * g_pCapture = NULL;
00076 IBaseFilter * g_pMux=NULL;
00077 IBaseFilter * g_pTee=NULL;
00078 IBaseFilter * pSmpte=NULL;
00079 
00080 HRESULT CaptureVideo(){
00081     HRESULT hr;
00082     IBaseFilter *pSrcFilter=NULL;
00083     hr = GetInterfaces();
00084     if (FAILED(hr))    {
00085         Msg(TEXT("Failed to get video interfaces!  hr=0x%x"), hr);
00086         return hr;
00087     }
00088     hr = g_pCapture->SetFiltergraph(g_pGraph);
00089     if (FAILED(hr)){
00090         Msg(TEXT("Failed to set capture filter graph!  hr=0x%x"), hr);
00091         return hr;
00092     }
00093     CA2W pszWW( MediaFile );
00094     hr=g_pGraph->AddSourceFilter(pszWW,L"Source File",&pSrcFilter);
00095     if (FAILED(hr))    {
00096         Msg(TEXT("Failed to set Input Filename!%s,  hr=0x%x"), MediaFile,hr);
00097         return hr;
00098     }
00099     hr=g_pGraph->AddFilter(g_pTee,L"Inf TEE");
00100     if (FAILED(hr))    {
00101         Msg(TEXT("Failed to add the InfTEE filter: hr=0x%x"), hr);
00102         return hr;
00103     }
00104     pSmpte = new CTransSmpte(NULL, &hr);
00105     hr=g_pGraph->AddFilter(pSmpte,L"TransSmpte");
00106     if (FAILED(hr))    {
00107         Msg(TEXT("Failed to add the smpte filter: hr=0x%x"), hr);
00108         return hr;
00109     }
00110     CComPtr< IBaseFilter > pVideoFilter;  // insert instance of Grabber filer
00111     if(!b32){
00112     pVideoFilter.CoCreateInstance(CLSID_SampleGrabber);
00113     if(!pVideoFilter)    {
00114         Msg(TEXT("Could not create SampleGrabber from Qedit.dll"));
00115         return hr;
00116     }
00117     CComQIPtr< ISampleGrabber, &IID_ISampleGrabber > pVideoGrab(pVideoFilter);
00118     CMediaType VideoType;
00119     VideoType.SetType(&MEDIATYPE_Video);
00120     VideoType.SetSubtype(&MEDIASUBTYPE_RGB24);
00121     hr = pVideoGrab->SetMediaType(&VideoType);
00122     if(FAILED(hr))    {
00123         Msg(TEXT("Could not set sample grabber's media type"));
00124         return hr;
00125     }
00126     hr = g_pGraph->AddFilter(pVideoFilter, L"VideoGrabber");
00127     if(FAILED(hr))    {
00128         Msg(TEXT("Could not add VideoGrabber to the graph"));
00129         return hr; 
00130     }
00131     CComPtr<IPin> pSourcePin;//     = GetOutPin(pSrcFilter,   0);
00132     hr = g_pCapture->FindPin(pSrcFilter,PINDIR_OUTPUT,0,0,TRUE,0,&pSourcePin); 
00133     if (FAILED(hr)){Msg("Fail find pin Source"); return hr;}
00134     CComPtr<IPin> pVideoIn;//       = GetInPin (pVideoFilter,  0);
00135     hr = g_pCapture->FindPin(pVideoFilter,PINDIR_INPUT,0,0,TRUE,0,&pVideoIn); 
00136     if (FAILED(hr)){Msg("Fail find pin GrabIn"); return hr;}
00137     hr=g_pGraph->Connect( pSourcePin, pVideoIn );
00138     if(FAILED(hr))    {
00139         Msg(TEXT("Bad Connect Vout-> Grab IN : hr=0x%x"), hr);
00140         return hr;
00141     }
00142     }  // b32
00143     hr = g_pCapture->RenderStream(
00144                       NULL, // Pin category.
00145                       NULL,      // Media type.
00146                       (b32 ? pSrcFilter:pVideoFilter),                  // Capture filter.
00147                       pSmpte,                  // Intermediate filter (optional).
00148                       NULL);                 // Mux or file sink filter.
00149     if (FAILED(hr))    {
00150         Msg(TEXT("Couldn't render the video file capture stream.  hr=0x%x\r\n"), hr);
00151     }
00152     SetupVideoWindow();  // only needed if not rendering to Mux
00153     pSrcFilter->Release();
00154     // Disable the reference clock so that ALL frames are converted
00155     hr = g_pMF->SetSyncSource(NULL);
00156     if (FAILED(hr)){
00157         Msg(TEXT("Couldn't set the reference clock:  hr=0x%x"), hr);
00158         return hr;
00159     }
00160     hr = g_pMC->Run();
00161     if (FAILED(hr)){
00162         Msg(TEXT("Couldn't run the graph!  hr=0x%x"), hr);
00163         return hr;
00164     }
00165     return S_OK;
00166 }
00167 
00168 HRESULT GetInterfaces(void){
00169     HRESULT hr;
00170     hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
00171                            IID_IGraphBuilder, (void **) &g_pGraph);
00172     if (FAILED(hr))        return hr;
00173     hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
00174                            IID_ICaptureGraphBuilder2, (void **) &g_pCapture);
00175     if (FAILED(hr))return hr;
00176     hr = CoCreateInstance (CLSID_InfTee, NULL, CLSCTX_INPROC,
00177                            IID_IBaseFilter, (void **) &g_pTee);
00178     if (FAILED(hr))return hr;
00179     hr = g_pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &g_pMC);
00180     if (FAILED(hr))        return hr;
00181     hr = g_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &g_pVW);
00182     if (FAILED(hr))return hr;
00183     hr = g_pGraph->QueryInterface(IID_IMediaFilter, (LPVOID *) &g_pMF);
00184     if (FAILED(hr))return hr;
00185     hr = g_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) &g_pME);
00186     if (FAILED(hr))return hr;
00187     // Set the window handle used to process graph events
00188     hr = g_pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0);
00189     return hr;
00190 }
00191 
00192 void CloseInterfaces(void){
00193     if (g_pMC)        g_pMC->StopWhenReady();
00194     if (g_pME)        g_pME->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0);
00195     if(g_pVW)    {
00196         g_pVW->put_Visible(OAFALSE);
00197         g_pVW->put_Owner(NULL);
00198     }
00199     SAFE_RELEASE(g_pMC);
00200     SAFE_RELEASE(g_pME);
00201     SAFE_RELEASE(g_pMF);
00202     SAFE_RELEASE(g_pVW);
00203     SAFE_RELEASE(g_pMux);
00204     SAFE_RELEASE(g_pTee);
00205     if(pSmpte)delete pSmpte;
00206     SAFE_RELEASE(g_pGraph);
00207     SAFE_RELEASE(g_pCapture);
00208 }
00209 
00210 
00211 HRESULT SetupVideoWindow(void){
00212     HRESULT hr;
00213     hr = g_pVW->put_Owner((OAHWND)ghApp);
00214     if (FAILED(hr))        return hr;
00215     hr = g_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
00216     if (FAILED(hr))        return hr;
00217     ResizeVideoWindow();
00218     hr = g_pVW->put_Visible(OATRUE);
00219     if (FAILED(hr))        return hr;
00220     return hr;
00221 }
00222 
00223 void ResizeVideoWindow(void){
00224     if (g_pVW){
00225         RECT rc;
00226         GetClientRect(ghApp, &rc);
00227         g_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
00228     }
00229 }
00230 
00231 void Msg(TCHAR *szFormat, ...){
00232     TCHAR szBuffer[1024];  // Large buffer for long filenames or URLs
00233     const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
00234     const int LASTCHAR = NUMCHARS - 1;
00235     va_list pArgs;
00236     va_start(pArgs, szFormat);
00237     _vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
00238     va_end(pArgs);
00239     szBuffer[LASTCHAR] = TEXT('\0');
00240     MessageBox(NULL, szBuffer, TEXT("PlayCap Message"), MB_OK | MB_ICONERROR);
00241 }
00242 
00243 HRESULT HandleGraphEvent(void){
00244     LONG evCode, evParam1, evParam2;
00245     HRESULT hr=S_OK;
00246     if (!g_pME)
00247         return E_POINTER;
00248     while(SUCCEEDED(g_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1, 
00249                    (LONG_PTR *) &evParam2, 0)))    {
00250         switch (evCode){
00251           case EC_COMPLETE:
00252             MessageBox(NULL,"Complete","Output",MB_OK);
00253             PostMessage(ghApp,WM_CLOSE,0,0); 
00254             break;
00255         }
00256         hr = g_pME->FreeEventParams(evCode, evParam1, evParam2);
00257     }
00258     return hr;
00259 }
00260 
00261 LRESULT CALLBACK WndMainProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
00262     switch (message){
00263         case WM_GRAPHNOTIFY:
00264             HandleGraphEvent();
00265             break;
00266         case WM_SIZE:
00267             ResizeVideoWindow();
00268             break;
00269         case WM_CLOSE:            
00270             ShowWindow(ghApp, SW_HIDE);
00271             CloseInterfaces();  // Stop capturing and release interfaces
00272             break;
00273         case WM_DESTROY:
00274             PostQuitMessage(0);
00275             return 0;
00276     }
00277     if (g_pVW)
00278         g_pVW->NotifyOwnerMessage((LONG_PTR) hwnd, message, wParam, lParam);
00279     return DefWindowProc (hwnd , message, wParam, lParam);
00280 }
00281 
00282 extern "C"  int AviDecoderEntry(HINSTANCE hInstance, char *movie_name, long frame){
00283     MSG msg={0};
00284     WNDCLASS wc;
00285     if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))){
00286         Msg(TEXT("CoInitialize Failed!\r\n"));   
00287         return 0;
00288     } 
00289     ZeroMemory(&wc, sizeof wc);
00290     wc.lpfnWndProc   = WndMainProc;
00291     wc.hInstance     = hInstance;
00292     wc.lpszClassName = CLASSNAME;
00293     wc.lpszMenuName  = NULL;
00294     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
00295     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
00296     wc.hIcon         = NULL; //LoadIcon(hInstance, MAKEINTRESOURCE(IDI_VIDPREVIEW));
00297     if(!RegisterClass(&wc)){
00298         Msg(TEXT("RegisterClass Failed! Error=0x%x\r\n"), GetLastError());
00299         CoUninitialize();
00300         return 0;
00301     }
00302     strcpy(MediaFile,movie_name);
00303     // Create the main window.  The WS_CLIPCHILDREN style is required.
00304     ghApp = CreateWindow(CLASSNAME, APPLICATIONNAME,
00305                          WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_CLIPCHILDREN,
00306                          CW_USEDEFAULT, CW_USEDEFAULT,
00307                          DEFAULT_VIDEO_WIDTH, DEFAULT_VIDEO_HEIGHT,
00308                          0, 0, hInstance, 0);
00309     if(ghApp){
00310         HRESULT hr;
00311         hr = CaptureVideo();
00312         if (FAILED (hr)){
00313             CloseInterfaces();
00314             DestroyWindow(ghApp);
00315         }
00316         else{
00317             ShowWindow(ghApp,SW_SHOW);
00318         }       
00319         while(GetMessage(&msg,NULL,0,0)){
00320             TranslateMessage(&msg);
00321             DispatchMessage(&msg);
00322         }
00323     }
00324     if(UnregisterClass(CLASSNAME,hInstance) == 0){
00325       MessageBox(NULL,"Unregister Class Failed",NULL,MB_OK);
00326     }
00327     CoUninitialize();
00328     return 1;
00329 }
00330 
00331 void WriteBitmap(long nx, long ny, unsigned char *S, long f);
00332 
00333 CTransSmpte::CTransSmpte(LPUNKNOWN punk,HRESULT *phr) 
00334     : CTransInPlaceFilter(TEXT("TransSmpte"), punk, __uuidof(CLSID_TransSmpte), phr)
00335     , m_nWidth(0)
00336     , m_nHeight(0)
00337     , m_pDibBits(NULL)
00338     , m_DibSection(NULL)
00339     , m_DC(NULL)
00340     , m_OldObject(NULL)
00341     , m_dFPS( 0.0 )
00342 {
00343 }
00344 
00345 CTransSmpte::~CTransSmpte( ){
00346     if( m_OldObject ){
00347         SelectObject( m_DC, m_OldObject );
00348         m_OldObject = NULL;
00349     }
00350     if( m_DC )    {
00351         DeleteDC( m_DC );
00352         m_DC = NULL;
00353     }
00354     if( m_DibSection )    {
00355         DeleteObject( m_DibSection );
00356         m_DibSection = NULL;
00357     }
00358 }
00359 
00360 
00361 HRESULT CTransSmpte::SetMediaType( PIN_DIRECTION pindir, const CMediaType *pMediaType){
00362     CheckPointer(pMediaType,E_POINTER);
00363     VIDEOINFO* pVI = (VIDEOINFO*) pMediaType->Format();
00364     CheckPointer(pVI,E_UNEXPECTED);
00365 
00366     m_nWidth  = pVI->bmiHeader.biWidth;
00367     m_nHeight = pVI->bmiHeader.biHeight;
00368     double tpf = double(pVI->AvgTimePerFrame) / UNITS;
00369     m_dFPS = tpf;
00370     return CTransInPlaceFilter::SetMediaType( pindir, pMediaType );
00371 }
00372 
00373 
00374 HRESULT CTransSmpte::CheckInputType(const CMediaType *mtIn){
00375     CheckPointer(mtIn,E_POINTER);
00376     if (*mtIn->FormatType() != FORMAT_VideoInfo) {
00377         return E_INVALIDARG;
00378     }
00379     if( *mtIn->Type( ) != MEDIATYPE_Video ){
00380         return E_INVALIDARG;
00381     }
00382     if( *mtIn->Subtype( ) == MEDIASUBTYPE_RGB24 )b32=FALSE;
00383     if(( *mtIn->Subtype( ) != MEDIASUBTYPE_RGB32 ) &&
00384     ( *mtIn->Subtype( ) != MEDIASUBTYPE_RGB24 ))  {
00385         return E_INVALIDARG;
00386     }
00387     VIDEOINFO *pVI = (VIDEOINFO *) mtIn->Format();
00388     CheckPointer(pVI,E_UNEXPECTED);
00389     if( pVI->bmiHeader.biBitCount == 24 )b32=FALSE;
00390     if(( pVI->bmiHeader.biBitCount != 32 ) &&
00391     ( pVI->bmiHeader.biBitCount != 24 ))    {
00392         return E_INVALIDARG;
00393     }
00394     if( pVI->bmiHeader.biHeight < 0 )    {
00395         return E_INVALIDARG;
00396     }
00397     return NOERROR;
00398 }
00399 
00400 HRESULT CTransSmpte::Transform(IMediaSample *pSample){
00401     CheckPointer(pSample,E_POINTER);
00402     if(bDir)framecount++; else framecount--;
00403     char *pBuffer = 0;
00404     pSample->GetPointer( (LPBYTE*) &pBuffer );
00405     WriteBitmap(m_nWidth, m_nHeight, (unsigned char*)pBuffer,framecount);
00406     return NOERROR;
00407 }
00408 
00409 static  char szOutFileName[255];
00410 
00411 #define BFT_BITMAP 0x4d42
00412 
00413 void WriteBitmap(long nx, long ny, unsigned char *S, long f){
00414  HANDLE hfbm;
00415  DWORD dwRead;
00416  BITMAPFILEHEADER hdr,*lphdr;
00417  BITMAPINFOHEADER bfi,*lpbi;
00418  long imagesize,mx;
00419  if(b32) mx=((nx*32+31)/32) * 4;
00420  else    mx=((nx*24+31)/32) * 4;
00421  sprintf(szOutFileName,"%s%0.4ld.bmp",bmproot,f);
00422 //MessageBox(NULL,szOutFileName,bmproot,MB_OK);
00423  if((hfbm=CreateFile(szOutFileName,GENERIC_WRITE,FILE_SHARE_WRITE,
00424    NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,
00425    (HANDLE)NULL)) == INVALID_HANDLE_VALUE){
00426    MessageBox(NULL,szOutFileName,"File Open Fail",MB_OK);
00427    MessageBeep(MB_OK);
00428    return;
00429  }
00430  lpbi=&bfi;
00431  lpbi->biSize=sizeof(BITMAPINFOHEADER);
00432  lpbi->biWidth=(DWORD)nx;
00433  lpbi->biHeight=(DWORD)ny;
00434  lpbi->biPlanes=1;
00435  if(b32)lpbi->biBitCount=32;
00436  else   lpbi->biBitCount=24;
00437  lpbi->biCompression=BI_RGB;
00438  lpbi->biSizeImage = imagesize = (DWORD)(mx*ny);
00439  lpbi->biXPelsPerMeter=0;
00440  lpbi->biYPelsPerMeter=0;
00441  lpbi->biClrUsed=0;
00442  lpbi->biClrImportant=0;
00443  lphdr=&hdr;
00444 //{char ttt[256]; sprintf(ttt,"imagesize=%ld BitCcunt=%ld -  mx %ld ny %ld", imagesize,lpbi->biBitCount,mx,ny);
00445 //MessageBox(NULL,ttt,"Test",MB_OK); }
00446  hdr.bfType          = BFT_BITMAP;
00447  hdr.bfSize          = (sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
00448                         + imagesize);
00449  hdr.bfReserved1     = 0;
00450  hdr.bfReserved2     = 0;
00451  hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize;
00452  WriteFile(hfbm,lphdr,sizeof(BITMAPFILEHEADER),&dwRead,(LPOVERLAPPED)NULL);
00453  WriteFile(hfbm,lpbi,sizeof(BITMAPINFOHEADER),&dwRead,(LPOVERLAPPED)NULL);
00454  WriteFile(hfbm,S,imagesize,&dwRead,(LPOVERLAPPED)NULL);
00455  if(dwRead != imagesize){
00456    MessageBeep(MB_OK);
00457    MessageBox(NULL,"Bad write",NULL,MB_OK);
00458  }
00459  if(!CloseHandle(hfbm)){
00460    MessageBeep(MB_OK);
00461    MessageBox(NULL,"Bad close",NULL,MB_OK);
00462  }
00463  return;
00464 }
00465 
00466 

Generated on Sun Apr 27 14:20:13 2014 for OpenFX by  doxygen 1.5.6