2 * AtmoExternalCaptureInput.cpp: Datasource which gets its data via a COM object call
3 * or some other external method.
6 * See the README.txt file for copyright information and how to reach the author(s).
11 #include "AtmoExternalCaptureInput.h"
12 #include "AtmoTools.h"
15 #define INT64_C(c) c ## LL
18 #if defined(_ATMO_VLC_PLUGIN_)
20 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
21 CAtmoInput(pAtmoDynData),
22 CThread(pAtmoDynData->getAtmoFilter())
24 m_pCurrentFramePixels = NULL;
25 vlc_cond_init( &m_WakeupCond );
26 vlc_mutex_init( &m_WakeupLock );
27 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput created.");
33 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
34 CAtmoInput(pAtmoDynData)
36 m_hWakeupEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
37 m_pCurrentFramePixels = NULL;
42 CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
44 /* if there is still an unprocessed bufferpicture do kill it */
45 if(m_pCurrentFramePixels != NULL)
46 free(m_pCurrentFramePixels);
48 #if defined(_ATMO_VLC_PLUGIN_)
49 vlc_cond_destroy( &m_WakeupCond );
50 vlc_mutex_destroy(&m_WakeupLock);
51 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput destroyed.");
53 CloseHandle(m_hWakeupEvent);
57 ATMO_BOOL CAtmoExternalCaptureInput::Open()
63 // Closes the input-device.
64 // Returns true if the input-device was closed successfully.
65 ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
71 tColorPacket CAtmoExternalCaptureInput::GetColorPacket(void)
73 return this->m_ColorPacket;
77 this method will be called from another thread or possible the COM Server to feed
78 new pixeldata into the calculation process it doest just the following:
79 1: check if last buffer was allready processed (!m_pCurrentFramePixels)
80 2. copy the bitmap info structure into the threads own one
81 3. alloc memory for frame
82 4. copy sourcepixeldata into own buffer...
83 5. let the thread wake up and return imediately to the caller
84 so that the real videoout wouldn't be stop for a too long time
86 void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
89 normaly we should protect this area of code by critical_section or a mutex,
90 but I think we can omit this here because the timing this method is called
91 is really slow (in terms of the speed of a modern computer?)
92 so it's nearly impossible that two frames are delivert in the same time
93 the test needs and malloc needs...
95 if( !m_pCurrentFramePixels )
97 // Last Frame was processed... take this one...
98 memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
99 int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
100 switch(m_CurrentFrameHeader.biBitCount) {
101 case 8: /* PixelDataSize = PixelDataSize; */ break;
102 case 16: PixelDataSize = PixelDataSize * 2; break;
103 case 24: PixelDataSize = PixelDataSize * 3; break;
104 case 32: PixelDataSize = PixelDataSize * 4; break;
106 m_pCurrentFramePixels = malloc(PixelDataSize);
107 memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
109 #if defined(_ATMO_VLC_PLUGIN_)
110 vlc_mutex_lock( &m_WakeupLock );
111 vlc_cond_signal( &m_WakeupCond );
112 vlc_mutex_unlock( &m_WakeupLock );
114 SetEvent(m_hWakeupEvent);
121 the real thread Method which is processing the pixeldata into the hardware channel
122 values - which are used by the thread AtmoLiveView...
124 #if defined (_ATMO_VLC_PLUGIN_)
126 DWORD CAtmoExternalCaptureInput::Execute(void)
128 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput::Execute(void)");
131 vlc_mutex_lock( &m_WakeupLock );
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));
136 /* DeliverNewSourceDataPaket delivered new work for me... get it! */
137 CalcColors(); // read picture and calculate colors
138 this->m_FrameArrived = ATMO_TRUE;
144 /* kludge for pthreads? using the same condition variable too often results in hanging the pthread
145 call inside vlc_cond_timedwait...
148 vlc_cond_destroy( &m_WakeupCond );
149 vlc_cond_init( &m_WakeupCond );
154 vlc_mutex_unlock( &m_WakeupLock );
161 DWORD CAtmoExternalCaptureInput::Execute(void) {
163 handles[0] = this->m_hTerminateEvent;
164 handles[1] = m_hWakeupEvent;
166 while (this->m_bTerminated == ATMO_FALSE) {
167 DWORD event = WaitForMultipleObjects(2,handles,ATMO_FALSE,INFINITE);
168 if(event == WAIT_OBJECT_0) {
169 // Terminate Thread Event was set... say good bye...!
172 if(event == (WAIT_OBJECT_0+1)) {
173 CalcColors(); // read picture and calculate colors
174 this->m_FrameArrived = ATMO_TRUE;
183 void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
185 this->m_FrameArrived = ATMO_FALSE;
186 for(DWORD i=0;(i<timeout) && !m_FrameArrived;i++)
187 #if defined (_ATMO_VLC_PLUGIN_)
193 if(this->m_pAtmoDynData)
195 CAtmoConfig *cfg = this->m_pAtmoDynData->getAtmoConfig();
198 int delay = cfg->getLiveView_FrameDelay();
201 #if defined (_ATMO_VLC_PLUGIN_)
202 msleep(delay * 1000);
211 void CAtmoExternalCaptureInput::CalcColors() {
212 // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
213 tHSVColor HSV_Img[IMAGE_SIZE];
214 tRGBColor pixelColor;
215 int srcIndex,index = 0;
216 memset(&HSV_Img,0,sizeof(HSV_Img));
218 // Convert Data to HSV values.. bla bla....
219 if(m_pCurrentFramePixels!=NULL)
221 if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
224 // HSVI = HSV Image allready in right format just copy the easiest task
225 // und weiterverarbeiten lassen
226 #ifdef _ATMO_VLC_PLUGIN_
227 if(m_CurrentFrameHeader.biCompression == VLC_FOURCC('H','S','V','I'))
229 if(m_CurrentFrameHeader.biCompression == MakeDword('H','S','V','I'))
232 memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
234 else if(m_CurrentFrameHeader.biCompression == BI_RGB)
236 if(m_CurrentFrameHeader.biBitCount == 16)
238 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
240 for(int y=0;y<CAP_HEIGHT;y++)
242 srcIndex = y * CAP_WIDTH;
243 for(int x=0;x<CAP_WIDTH;x++)
245 pixelColor.b = (buffer[srcIndex] & 31) << 3;
246 pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
247 pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
249 HSV_Img[index++] = RGB2HSV(pixelColor);
253 else if(m_CurrentFrameHeader.biBitCount == 24)
255 for(int y=0;y<CAP_HEIGHT;y++)
257 srcIndex = y * (CAP_WIDTH*3);
258 for(int x=0;x<CAP_WIDTH;x++)
260 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
261 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
262 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
263 HSV_Img[index++] = RGB2HSV(pixelColor);
267 else if(m_CurrentFrameHeader.biBitCount == 32)
269 for(int y=0;y<CAP_HEIGHT;y++)
271 srcIndex = y * (CAP_WIDTH*4);
272 for(int x=0;x<CAP_WIDTH;x++)
274 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
275 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
276 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
278 HSV_Img[index++] = RGB2HSV(pixelColor);
286 if the image color format wasn't recognized - the output
287 will be black (memset)
291 now convert the pixeldata into one RGB trippel for each channel,
292 this is done by some very sophisticated methods and statistics ...
294 the only thing I know - the pixel priority is controled by some
295 gradients for each edge of the picture
297 (sorry I don't know how it exactly works because the formulars
298 are done by some one else...)
300 m_ColorPacket = CalcColorsAnalyzeHSV(this->m_pAtmoDynData->getAtmoConfig(), HSV_Img);
302 /* remove the source buffe */
303 free(m_pCurrentFramePixels);
305 the buffer zereo so that deliver new data paket will wakeup the
306 thread on the next frame again
308 m_pCurrentFramePixels = NULL;