Update the changelog
[opencv] / apps / Hawk / AviSource.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 #include "stdafx.h"
42 #include "Hawk.h"
43 #include <mmsystem.h>
44 #include <cvstreams.h>
45 #include <HighGUI.h>
46 #include "convert.h"
47 #include <iProxyTrans.h>
48 #include <ProxyTransuids.h>
49
50 #define SafeRelease(p) { if( (p) != 0 ) { (p)->Release(); (p)= 0; } }
51 #define WM_GRAPHNOTIFY  WM_USER+13
52
53 IPin* get_pin( IBaseFilter* pFilter, PIN_DIRECTION dir );
54
55 template<> void AFXAPI DestructElements<IUnknown*> (IUnknown** pElements, int nCount);
56
57 void AFXAPI DestructElements(IUnknown** elements, int count)
58 {
59     for(int i = 0; i < count; i++)
60     {
61         SafeRelease(elements[i]);
62     }
63 };
64
65 int play_avi(char* filename, char* windowname, void (*callback)(IplImage*))
66 {
67     if(!filename || !windowname)
68     {
69         return -1;
70     }
71
72     // get the full file path
73     char drive[_MAX_DRIVE];
74     char path[_MAX_DIR];
75     char fpath[_MAX_PATH];
76     char fname[_MAX_FNAME];
77     char fext[_MAX_EXT];
78     char fullname[_MAX_PATH];
79     LPSTR f;
80     CHawkApp* app = (CHawkApp*)AfxGetApp();
81     const CStringArray& search_path = app->GetVideoPath();
82
83     _splitpath(filename, drive, path, fname, fext);
84     strcpy(fpath, drive);
85     strcat(fpath, path);
86     DWORD found = SearchPath(fpath, fname, fext, _MAX_PATH, fullname, &f);
87     if(!found)
88     {
89         found = SearchPath(NULL, fname, fext, _MAX_PATH, fullname, &f);
90         if(!found)
91         {
92             for(int i = 0; i < search_path.GetSize(); i++)
93             {
94                 if(found = SearchPath(search_path[i], fname, fext, _MAX_PATH, fullname, &f))
95                 {
96                     break;
97                 }
98             }
99
100             if(!found)
101             {
102                 return -1;
103             }
104         }
105     }
106
107     HWND hwnd;
108     HRESULT hres;
109     IGraphBuilder *pigb  = NULL;
110     IMediaControl *pimc  = NULL;
111     IMediaEventEx *pimex = NULL;
112     IVideoWindow  *pivw  = NULL;
113     IProxyTransform* pipt = NULL;
114     IBaseFilter* pias = NULL;
115     CArray<IUnknown*, IUnknown*> interfaces;
116
117     // Initialize COM
118     if(FAILED(CoInitialize(0)))
119     {
120         return -1;
121     };
122
123
124     if(FAILED(CoCreateInstance(CLSID_FilterGraph,
125     NULL,
126     CLSCTX_INPROC_SERVER,
127     IID_IGraphBuilder,
128     (void **)&pigb)))
129     {
130         return -1;
131     }
132     
133     pigb->QueryInterface(IID_IMediaControl, (void **)&pimc);
134     pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex);
135     pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw);
136     ASSERT(pimc);
137     ASSERT(pimex);
138     ASSERT(pivw);
139
140     interfaces.Add(pigb);
141     interfaces.Add(pimc);
142     interfaces.Add(pimex);
143     interfaces.Add(pivw);
144
145     BSTR wstr = CString(fullname).AllocSysString();
146     hres = pigb->RenderFile(wstr, 0);
147     ::SysFreeString(wstr);
148     if(FAILED(hres))
149     {
150         return -1;
151     }
152
153     // Find the last filter:
154     IEnumFilters* pief = NULL;
155     hres = pigb->EnumFilters(&pief);
156     ASSERT(SUCCEEDED(hres) && pief);
157     interfaces.Add(pief);
158     // Find the last filter
159     IBaseFilter* pRenderer = NULL;
160     IBaseFilter* pRenderSource = NULL;
161     IBaseFilter* pibf = NULL;
162     IPin* pSourceOut = NULL;
163     IPin* pRenderIn = NULL;
164
165     ULONG cf = 1;
166     // The filter without the output pin should be a renderer, 
167     // and the filter before the renderer - the source of images...
168     while(cf)
169     {
170         pief->Next(1, &pibf, &cf);
171         IPin* pOut = get_pin(pibf, PINDIR_OUTPUT);
172         if(!pOut)
173         {
174             // This is the renderer...
175             pRenderIn = get_pin(pibf, PINDIR_INPUT);
176             pRenderIn->ConnectedTo(&pSourceOut);
177             ASSERT(pSourceOut);
178
179             SafeRelease(pibf);
180             interfaces.Add(pRenderIn);
181             interfaces.Add(pSourceOut);
182             break;
183         }
184
185         SafeRelease(pibf);
186     }
187
188     if(!pSourceOut || !pRenderIn)
189     {
190         return -1;
191     }
192
193     // Create a proxy transform filter
194     if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER, 
195                 IID_IProxyTransform, (void**)&pipt)) || !pipt)
196     {
197         return -1;
198     }
199
200     interfaces.Add(pipt);
201
202     IBaseFilter* pProxyFilter = NULL;
203     pipt->QueryInterface(IID_IBaseFilter, (void**)&pProxyFilter);
204     ASSERT(pProxyFilter);
205     IPin* pProxyOut = get_pin(pProxyFilter, PINDIR_OUTPUT);
206     IPin* pProxyIn = get_pin(pProxyFilter, PINDIR_INPUT);
207     ASSERT(pProxyOut && pProxyIn);
208
209     interfaces.Add(pProxyFilter);
210     interfaces.Add(pProxyOut);
211     interfaces.Add(pProxyIn);
212
213     // Set the proxy callback
214     pipt->set_transform((void(*)(void*))callback, 0);
215
216     // Add the proxy transform filter to the graph...
217     hres = pigb->AddFilter(pProxyFilter, L"Proxy Transform");
218     ASSERT(SUCCEEDED(hres));
219
220     // Insert the proxy transfor filter...
221     hres = pigb->Disconnect(pSourceOut);
222     ASSERT(SUCCEEDED(hres));
223     hres = pigb->Disconnect(pRenderIn);
224     ASSERT(SUCCEEDED(hres));
225
226     hres = pigb->Connect(pSourceOut, pProxyIn);
227     ASSERT(SUCCEEDED(hres));
228     hres = pigb->Connect(pProxyOut, pRenderIn);
229     ASSERT(SUCCEEDED(hres));
230     hres = pigb->Connect(pSourceOut, pProxyIn);
231     ASSERT(SUCCEEDED(hres));
232
233     BOOL needDestroy = FALSE;
234     if(windowname)
235     {
236         // Find/create and attach the HighGUI window to the DS renderer
237         hwnd = (HWND)cvGetWindowHandle(windowname);
238         if(!hwnd)
239         {
240             int error = cvNamedWindow((char*)windowname, 0);
241             if(error == 0/*HG_INITFAILED*/)
242             {
243 #ifdef _DEBUG
244                 CString str = "Can't initialize graphic library. \nPossible can't find cvlgrfmtsd.dll";
245 #else
246                 CString str = "Can't initialize graphic library. \nPossible can't find cvlgrfmts.dll";
247 #endif // _DEBUG
248                 AfxMessageBox(LPCTSTR(str));
249                 return -1;
250             }
251             hwnd = (HWND)cvGetWindowHandle(windowname);
252             needDestroy = TRUE;
253         }
254
255         pimex->SetNotifyWindow((OAHWND)hwnd, WM_GRAPHNOTIFY, 0);
256         pimex->SetNotifyFlags(0x00);
257         pimex->CancelDefaultHandling(EC_COMPLETE);
258
259         pivw->put_Owner((OAHWND)hwnd);
260         long flags;
261         pivw->get_WindowStyle(&flags);
262         pivw->put_WindowStyle( flags &(~WS_CAPTION) | WS_CHILD/*|WS_CLIPSIBLINGS|WS_CLIPCHILDREN*/);
263         pivw->put_MessageDrain((OAHWND)hwnd);
264         CRect rc;
265         ::GetClientRect(hwnd, &rc);
266         pivw->SetWindowPosition( rc.left, rc.top, rc.right, rc.bottom );
267     }
268     else
269     {
270         pivw->put_WindowState(SW_HIDE);
271         pivw->put_AutoShow(OAFALSE);
272     }
273
274     pimc->Run();
275
276     // Wait for operation completion...
277     while(1)
278     {
279         long evCode;
280         MSG message;
281         GetMessage(&message, NULL, 0, 0);
282         if(message.message == WM_GRAPHNOTIFY)
283         {
284             long param1, param2;
285             // Check for completion:
286             hres = pimex->GetEvent(&evCode, &param1, &param2, 0);
287             pimex->FreeEventParams(evCode, param1, param2);
288             if(evCode == EC_COMPLETE)
289             {
290                 break;
291             }
292             evCode = 0;
293             hres = pimex->WaitForCompletion(0, &evCode);
294 //            if(hres == S_OK)
295 //            {
296 //                break;
297 //            }
298 //            OAFilterState state;
299 //            hres = pimc->GetState(INFINITE, &state);
300             
301         }
302
303         TranslateMessage(&message);
304         DispatchMessage(&message);
305
306         if(!cvGetWindowHandle(windowname))
307         {
308             // The avi window has been destroyed...
309             OAFilterState state;
310             hres = pimc->GetState(INFINITE, &state);
311             hres = pimc->Pause();
312             hres = pimc->GetState(INFINITE, &state);
313             hres = pimc->Stop();
314             hres = pimc->GetState(INFINITE, &state);
315             ASSERT(state == State_Stopped);
316             break;
317         }
318     }
319
320     if(needDestroy)
321     {
322         cvDestroyWindow(windowname);
323     }
324
325     return 0;
326 }