00001 #include "stdafx.h"
00002
00003
00004
00005 #include <atlbase.h>
00006 #include <windows.h>
00007 #include <dshow.h>
00008 #include <qedit.h>
00009 #include <objbase.h>
00010
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013
00014 #include "dshowfile.h"
00015
00016 #include "iniparser.h"
00017
00018 const LONGLONG MILLISECONDS = (1000);
00019 const LONGLONG NANOSECONDS = (1000000000);
00020 const LONGLONG UNITS = (NANOSECONDS / 100);
00021
00022 void DShowFileFactory::registerParameters(ParamSection *sec) {
00023 sec->addStringParam("aviFile", &filename, "default.avi");
00024 sec->addBoolParam("useDShowFile", &use, true);
00025 };
00026
00027 VideoSource *DShowFileFactory::construct() {
00028 if (use) {
00029 DShowFile *vs = new DShowFile(filename);
00030 if (vs->initialize()) return vs;
00031 delete vs;
00032 }
00033 return 0;
00034 }
00035
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00101
00102
00103
00104 int GrabBitmaps(TCHAR * szFile);
00105 HRESULT GetPin(IBaseFilter * pFilter, PIN_DIRECTION dirrequired, int iNum, IPin **ppPin);
00106 IPin * GetInPin ( IBaseFilter *pFilter, int Num );
00107 IPin * GetOutPin( IBaseFilter *pFilter, int Num );
00108
00109 DShowFile::DShowFile(const char *filename)
00110 {
00111 image =0;
00112 this->filename = filename;
00113 frameCnt=0;
00114 g_psCurrent = Stopped;
00115 }
00116
00117 DShowFile::~DShowFile()
00118 {
00119 if (image) cvReleaseImage(&image);
00120 }
00121
00122 bool DShowFile::initialize()
00123 {
00124 if (!filename) return false;
00125
00126 HRESULT hr;
00127
00128
00129 if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
00130 {
00131 fprintf(stderr, "CoInitialize Failed!\r\n");
00132
00133 }
00134
00135
00136
00137 pGrabber.CoCreateInstance( CLSID_SampleGrabber );
00138 if( !pGrabber )
00139 {
00140 fprintf(stderr, "Could not create CLSID_SampleGrabber\r\n");
00141 return false;
00142 }
00143 CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabberBase( pGrabber );
00144
00145
00146
00147 pSource.CoCreateInstance( CLSID_AsyncReader );
00148 if( !pSource )
00149 {
00150 fprintf(stderr, "Could not create source filter\r\n");
00151 return false;
00152 }
00153
00154
00155
00156 pGraph.CoCreateInstance( CLSID_FilterGraph );
00157 if( !pGraph )
00158 {
00159 fprintf(stderr, "Could not not create the graph\r\n");
00160 return false;
00161 }
00162
00163
00164
00165 hr = pGraph->AddFilter( pSource, L"Source" );
00166 hr = pGraph->AddFilter( pGrabberBase, L"Grabber" );
00167
00168
00169
00170 wchar_t wfn[256];
00171 mbstowcs(wfn, filename, 256);
00172 CComQIPtr< IFileSourceFilter, &IID_IFileSourceFilter > pLoad( pSource );
00173 hr = pLoad->Load( wfn, NULL );
00174 if( FAILED( hr ) )
00175 {
00176 fprintf(stderr, "Could not load the media file\r\n");
00177 return false;
00178 }
00179
00180
00181
00182
00183
00184 AM_MEDIA_TYPE mt;
00185 ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
00186 mt.majortype = MEDIATYPE_Video;
00187 mt.subtype = MEDIASUBTYPE_RGB24;
00188 hr = pGrabber->SetMediaType(&mt);
00189 if (FAILED(hr)) return false;
00190
00191
00192
00193
00194 CComPtr< IPin > pSourcePin;
00195 CComPtr< IPin > pGrabPin;
00196
00197 pSourcePin = GetOutPin( pSource, 0 );
00198 pGrabPin = GetInPin( pGrabberBase, 0 );
00199
00200
00201
00202 hr = pGraph->Connect( pSourcePin, pGrabPin );
00203 if( FAILED( hr ) )
00204 {
00205 fprintf(stderr, "Could not connect source filter to grabber\r\n");
00206 return false;
00207 }
00208
00209
00210
00211 hr = pGrabber->GetConnectedMediaType( &mt );
00212
00213 VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
00214 CB.Width = vih->bmiHeader.biWidth;
00215 CB.Height = vih->bmiHeader.biHeight;
00216
00217 if (CB.image==0) {
00218 CB.image = image = cvCreateImage(cvSize(CB.Width, CB.Height), IPL_DEPTH_8U, 3);
00219 } else {
00220 if (CB.Width != CB.image->width || CB.Height != CB.image->height) {
00221 std::cerr << "BUG! Fixme! dshowfile.cpp!!!\n";
00222 return false;
00223 }
00224 image = CB.image;
00225 }
00226
00227
00228
00229 CComPtr <IPin> pGrabOutPin = GetOutPin( pGrabberBase, 0 );
00230 hr = pGraph->Render( pGrabOutPin );
00231 if( FAILED( hr ) )
00232 {
00233 fprintf(stderr, "Could not render grabber output pin\r\n");
00234 return false;
00235 }
00236
00237
00238
00239 hr = pGrabber->SetBufferSamples( FALSE );
00240
00241
00242
00243
00244 hr = pGrabber->SetOneShot( TRUE );
00245
00246
00247
00248 hr = pGrabber->SetCallback( &CB, 1 );
00249
00250
00251
00252 hr = pGraph->QueryInterface(IID_IMediaSeeking, (LPVOID *) &pSeeking);
00253 if (FAILED(hr)) {
00254 fprintf(stderr, "cannot query media seeking interface !\n");
00255 return false;
00256 }
00257
00258 hr = pSeeking->SetTimeFormat(&TIME_FORMAT_FRAME);
00259 if (FAILED(hr)) {
00260 fprintf(stderr, "cannot change time format !\n");
00261 return false;
00262 }
00263
00264 hr = pSeeking->GetDuration(&duration);
00265 if (FAILED(hr)) {
00266 fprintf(stderr, "cannot get video duration !\n");
00267 return false;
00268 }
00269
00270 printf("%s: %dx%d, %d samples.\n", filename, CB.Width, CB.Height, int(duration));
00271
00272
00273
00274
00275 CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = pGraph;
00276 if (pWindow)
00277 {
00278 hr = pWindow->put_AutoShow(OAFALSE);
00279 }
00280 return true;
00281 }
00282
00283 bool DShowFile::getFrame(IplImage *dst) {
00284
00285 if (g_psCurrent != Paused) {
00286
00287 if (g_psCurrent == Stopped)
00288 g_psCurrent = Paused;
00289
00290
00291 lastFrame = frameCnt;
00292 HRESULT hr;
00293
00294
00295
00296 if (lastFrame >= duration) {
00297 frameCnt=0;
00298 stop();
00299 } else {
00300 frameCnt++;
00301 }
00302
00303
00304 CComQIPtr< IMediaControl, &IID_IMediaControl > pControl( pGraph );
00305 hr = pControl->Run( );
00306
00307
00308 CComQIPtr< IMediaEvent, &IID_IMediaEvent > pEvent( pGraph );
00309 long EvCode = 0;
00310
00311 hr = pEvent->WaitForCompletion( INFINITE, &EvCode );
00312
00313
00314
00315 CB.frameWanted = true;
00316 }
00317
00318 while (CB.frameWanted) {
00319 Sleep(2);
00320 };
00321
00322 cvCopy(image,dst);
00323
00324
00325 return true;
00326 }
00327
00328
00329 void DShowFile::getSize(int &width, int &height)
00330 {
00331 width = CB.Width;
00332 height = CB.Height;
00333 }
00334
00335 void DShowFile::start()
00336 {
00337 g_psCurrent = Playing;
00338 }
00339
00340 void DShowFile::stop()
00341 {
00342 g_psCurrent = Paused;
00343 }
00344
00345 HRESULT GetPin( IBaseFilter * pFilter, PIN_DIRECTION dirrequired, int iNum, IPin **ppPin)
00346 {
00347 CComPtr< IEnumPins > pEnum;
00348 *ppPin = NULL;
00349
00350 HRESULT hr = pFilter->EnumPins(&pEnum);
00351 if(FAILED(hr))
00352 return hr;
00353
00354 ULONG ulFound;
00355 IPin *pPin;
00356 hr = E_FAIL;
00357
00358 while(S_OK == pEnum->Next(1, &pPin, &ulFound))
00359 {
00360 PIN_DIRECTION pindir = (PIN_DIRECTION)3;
00361
00362 pPin->QueryDirection(&pindir);
00363 if(pindir == dirrequired)
00364 {
00365 if(iNum == 0)
00366 {
00367 *ppPin = pPin;
00368 hr = S_OK;
00369 break;
00370 }
00371 iNum--;
00372 }
00373
00374 pPin->Release();
00375 }
00376
00377 return hr;
00378 }
00379
00380
00381 IPin * GetInPin( IBaseFilter * pFilter, int nPin )
00382 {
00383 CComPtr<IPin> pComPin=0;
00384 GetPin(pFilter, PINDIR_INPUT, nPin, &pComPin);
00385 return pComPin;
00386 }
00387
00388
00389 IPin * GetOutPin( IBaseFilter * pFilter, int nPin )
00390 {
00391 CComPtr<IPin> pComPin=0;
00392 GetPin(pFilter, PINDIR_OUTPUT, nPin, &pComPin);
00393 return pComPin;
00394 }
00395
00396
00397 static void deinterlaceResizeHalf(const IplImage *src, IplImage *dst)
00398 {
00399 assert(src->depth == IPL_DEPTH_8U);
00400
00401
00402 for(int y = 0; y < dst->height; y++)
00403 {
00404 unsigned char *srcpix = ((unsigned char *)(src->imageData)) + 2*y*src->widthStep;
00405 unsigned char *dstpix = ((unsigned char *)(dst->imageData)) + y*dst->widthStep;
00406 for (int x=0; x < dst->width; ++x) {
00407 if ((src->nChannels == 1) && (dst->nChannels == 1)) {
00408 *dstpix++ = (unsigned char)((int(srcpix[0])+int(srcpix[1]))>>1);
00409 srcpix+=2;
00410 } else if (dst->nChannels==1 && src->nChannels==3) {
00411 *dstpix++ = (unsigned char)((((int(srcpix[0])+int(srcpix[3]))>>1) +
00412 ((int(srcpix[1])+int(srcpix[4]))>>1) +
00413 ((int(srcpix[2])+int(srcpix[5]))>>1) )/3);
00414 srcpix+=6;
00415 } else if (dst->nChannels==3 && src->nChannels==3) {
00416 *dstpix++ = (unsigned char)((int(srcpix[0])+int(srcpix[3]))>>1);
00417 *dstpix++ = (unsigned char)((int(srcpix[1])+int(srcpix[4]))>>1);
00418 *dstpix++ = (unsigned char)((int(srcpix[2])+int(srcpix[5]))>>1);
00419 srcpix+=6;
00420 }
00421 }
00422 }
00423 }
00424
00425 void deinterlaceAndResize(IplImage *src, IplImage *dst)
00426 {
00427 static IplImage *tmpIm = 0;
00428
00429 if ((src->width/2) == dst->width && (src->height/2 == dst->height)) {
00430 deinterlaceResizeHalf(src, dst);
00431 return;
00432 }
00433
00434 if (tmpIm==0)
00435 tmpIm = cvCreateImage(cvSize(src->width, src->height/2), IPL_DEPTH_8U, 3);
00436
00437
00438 for(int y = 0; y < tmpIm->height; y++)
00439 {
00440
00441 int srcY = y*2;
00442
00443
00444 memcpy(tmpIm->imageData + y*tmpIm->widthStep, src->imageData + srcY*src->widthStep,
00445 src->widthStep);
00446 }
00447
00448 cvResize(tmpIm, dst);
00449 }
00450
00451