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