]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/AtmoExternalCaptureInput.cpp
Converted atmo filter to vlc_clone().
[vlc] / modules / video_filter / atmo / AtmoExternalCaptureInput.cpp
1 /*
2  * AtmoExternalCaptureInput.cpp: Datasource which gets its data via a COM object call
3  * or some other external method.
4  *
5  *
6  * See the README.txt file for copyright information and how to reach the author(s).
7  *
8  * $Id$
9  */
10
11 #ifdef HAVE_CONFIG_H
12 # include "config.h"
13 #endif
14
15 #include "AtmoExternalCaptureInput.h"
16 #include "AtmoTools.h"
17
18
19 #if defined(_ATMO_VLC_PLUGIN_)
20
21
22 #ifndef INT64_C
23 #define INT64_C(c)  c ## LL
24 #endif
25
26 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
27                            CAtmoInput(pAtmoDynData)
28 {
29     vlc_cond_init( &m_WakeupCond );
30     vlc_mutex_init( &m_WakeupLock );
31     m_pCurrentFramePixels = NULL;
32     m_pLog = pAtmoDynData->getAtmoFilter();
33 }
34
35 #else
36
37 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
38                            CAtmoInput(pAtmoDynData)
39 {
40     m_hWakeupEvent = CreateEvent(NULL,0,0,NULL);
41     InitializeCriticalSection( &m_BufferLock );
42     m_pCurrentFramePixels = NULL;
43 }
44
45 #endif
46
47 CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
48 {
49    /* if there is still an unprocessed bufferpicture do kill it */
50 #if defined(_ATMO_VLC_PLUGIN_)
51    vlc_mutex_lock( &m_WakeupLock );
52    free( m_pCurrentFramePixels );
53    vlc_mutex_unlock( &m_WakeupLock );
54
55    vlc_cond_destroy( &m_WakeupCond );
56    vlc_mutex_destroy( &m_WakeupLock );
57 #else
58    EnterCriticalSection( &m_BufferLock );
59    free( m_pCurrentFramePixels );
60    LeaveCriticalSection( &m_BufferLock );
61    CloseHandle(m_hWakeupEvent);
62    DeleteCriticalSection( &m_BufferLock );
63 #endif
64 }
65
66 ATMO_BOOL CAtmoExternalCaptureInput::Open()
67 {
68     this->Run();
69     return ATMO_TRUE;
70 }
71
72 // Closes the input-device.
73 // Returns true if the input-device was closed successfully.
74 ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
75 {
76     this->Terminate();
77     return ATMO_TRUE;
78 }
79
80
81 /*
82   this method will be called from another thread or possible the COM Server to feed
83   new pixeldata into the calculation process it doest just the following:
84   1: check if last buffer was allready processed (!m_pCurrentFramePixels)
85   2. copy the bitmap info structure into the threads own one
86   3. alloc memory for frame
87   4. copy sourcepixeldata into own buffer...
88   5. let the thread wake up and return imediately to the caller
89   so that the real videoout wouldn't be stop for a too long time
90 */
91 void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
92 {
93     /*
94        normaly we should protect this area of code by critical_section or a mutex,
95        but I think we can omit this here because the timing this method is called
96        is really slow (in terms of the speed of a modern computer?)
97        so it's nearly impossible that two frames are delivert in the same time
98        the test needs and malloc needs...
99     */
100 #if defined(_ATMO_VLC_PLUGIN_)
101 //    msg_Dbg( m_pLog, "DeliverNewSourceDataPaket start...");
102     vlc_mutex_lock( &m_WakeupLock );
103 #else
104     EnterCriticalSection( &m_BufferLock );
105 #endif
106     if( !m_pCurrentFramePixels )
107     {
108         // Last Frame was processed... take this one...
109         memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
110         int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
111         switch(m_CurrentFrameHeader.biBitCount) {
112             case 8:  /* PixelDataSize = PixelDataSize; */ break;
113             case 16: PixelDataSize = PixelDataSize * 2; break;
114             case 24: PixelDataSize = PixelDataSize * 3; break;
115             case 32: PixelDataSize = PixelDataSize * 4; break;
116         }
117         m_pCurrentFramePixels = malloc(PixelDataSize);
118         memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
119     }
120 #if defined(_ATMO_VLC_PLUGIN_)
121     vlc_cond_signal( &m_WakeupCond );
122     vlc_mutex_unlock( &m_WakeupLock );
123     // msg_Dbg( m_pLog, "DeliverNewSourceDataPaket done.");
124 #else
125     SetEvent(m_hWakeupEvent);
126     LeaveCriticalSection( &m_BufferLock );
127 #endif
128 }
129
130
131
132 /*
133  the real thread Method which is processing the pixeldata into the hardware channel
134  values - which are used by the thread AtmoLiveView...
135 */
136 #if defined (_ATMO_VLC_PLUGIN_)
137
138 DWORD CAtmoExternalCaptureInput::Execute(void)
139 {
140     while ((this->m_bTerminated == ATMO_FALSE)) {
141           vlc_mutex_lock( &m_WakeupLock );
142           vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + 75000 );
143
144           /* DeliverNewSourceDataPaket delivered new work for me... get it! */
145           if(m_pCurrentFramePixels)
146              CalcColors(); // read picture and calculate colors
147           vlc_mutex_unlock( &m_WakeupLock );
148     }
149
150     msg_Dbg( m_pLog, "DWORD CAtmoExternalCaptureInput::Execute(void) bailed out?");
151
152     return 0;
153 }
154
155 #else
156
157 DWORD CAtmoExternalCaptureInput::Execute(void) {
158     HANDLE handles[2];
159     handles[0] = this->m_hTerminateEvent;
160     handles[1] = m_hWakeupEvent;
161
162     while (this->m_bTerminated == ATMO_FALSE) {
163            DWORD event = WaitForMultipleObjects(2, &handles[0], FALSE, INFINITE);
164            if(event == WAIT_OBJECT_0) {
165               // Terminate Thread Event was set... say good bye...!
166               break;
167            }
168            if(event == (WAIT_OBJECT_0+1)) {
169               EnterCriticalSection( &m_BufferLock );
170               if(m_pCurrentFramePixels)
171                  CalcColors(); // read picture and calculate colors
172               LeaveCriticalSection( &m_BufferLock );
173            }
174     }
175     return 0;
176 }
177
178 #endif
179
180
181 void CAtmoExternalCaptureInput::CalcColors()
182 {
183      // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
184     tHSVColor HSV_Img[IMAGE_SIZE];
185     tRGBColor pixelColor;
186     int srcIndex,index = 0;
187     memset(&HSV_Img,0,sizeof(HSV_Img));
188
189     // msg_Dbg( m_pLog, "CalcColors start...");
190
191     if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
192     {
193
194         // HSVI = HSV Image allready in right format just copy the easiest task
195         // und weiterverarbeiten lassen
196 #ifdef _ATMO_VLC_PLUGIN_
197         if(m_CurrentFrameHeader.biCompression ==  VLC_FOURCC('H','S','V','I'))
198 #else
199         if(m_CurrentFrameHeader.biCompression ==  MakeDword('H','S','V','I'))
200 #endif
201         {
202             memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
203         }
204         else if(m_CurrentFrameHeader.biCompression == BI_RGB)
205         {
206             if(m_CurrentFrameHeader.biBitCount == 16)
207             {
208                 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
209
210                 for(int y=0;y<CAP_HEIGHT;y++)
211                 {
212                     srcIndex = y * CAP_WIDTH;
213                     for(int x=0;x<CAP_WIDTH;x++)
214                     {
215                         pixelColor.b = (buffer[srcIndex] & 31) << 3;
216                         pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
217                         pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
218                         srcIndex++;
219                         HSV_Img[index++] = RGB2HSV(pixelColor);
220                     }
221                 }
222             }
223             else if(m_CurrentFrameHeader.biBitCount == 24)
224             {
225                 for(int y=0;y<CAP_HEIGHT;y++)
226                 {
227                     srcIndex = y * (CAP_WIDTH*3);
228                     for(int x=0;x<CAP_WIDTH;x++)
229                     {
230                         pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
231                         pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
232                         pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
233                         HSV_Img[index++] = RGB2HSV(pixelColor);
234                     }
235                 }
236             }
237             else if(m_CurrentFrameHeader.biBitCount == 32)
238             {
239                 for(int y=0;y<CAP_HEIGHT;y++)
240                 {
241                     srcIndex = y * (CAP_WIDTH*4);
242                     for(int x=0;x<CAP_WIDTH;x++)
243                     {
244                         pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
245                         pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
246                         pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
247                         srcIndex++;
248                         HSV_Img[index++] = RGB2HSV(pixelColor);
249                     }
250                 }
251             }
252         }
253     }
254     /*
255       else {
256         if the image color format wasn't recognized - the output
257         will be black (memset)
258         }
259     */
260
261     /* remove the source buffer */
262     free( m_pCurrentFramePixels );
263     m_pCurrentFramePixels = NULL;
264
265     /*
266         now convert the pixeldata into one RGB trippel for each channel,
267         this is done by some very sophisticated methods and statistics ...
268
269         the only thing I know - the pixel priority is controled by some
270         gradients for each edge of the picture
271
272         (sorry I don't know how it exactly works because the formulas
273         are done by some one else...)
274     */
275     //msg_Dbg( m_pLog, "CalcColors ende AddPacket...");
276     m_pAtmoDynData->getLivePacketQueue()->AddPacket( m_pAtmoColorCalculator->AnalyzeHSV( HSV_Img ) );
277     //msg_Dbg( m_pLog, "CalcColors ende AddPacket...done.");
278 }
279