00001
00002
00003
00004
00005
00006
00007
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"
00018 #include "qedit.h"
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