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"
14 #if defined(_ATMO_VLC_PLUGIN_)
16 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
17 CAtmoInput(pAtmoDynData),
18 CThread(pAtmoDynData->getAtmoFilter())
20 m_pCurrentFramePixels = NULL;
21 vlc_cond_init( this->m_pAtmoThread, &m_WakeupCond );
22 vlc_mutex_init( &m_WakeupLock );
23 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput created.");
29 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
30 CAtmoInput(pAtmoDynData)
32 m_hWakeupEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
33 m_pCurrentFramePixels = NULL;
38 CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
40 /* if there is still an unprocessed bufferpicture do kill it */
41 if(m_pCurrentFramePixels != NULL)
42 free(m_pCurrentFramePixels);
44 #if defined(_ATMO_VLC_PLUGIN_)
45 vlc_cond_destroy( &m_WakeupCond );
46 vlc_mutex_destroy(&m_WakeupLock);
47 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput destroyed.");
49 CloseHandle(m_hWakeupEvent);
53 ATMO_BOOL CAtmoExternalCaptureInput::Open()
59 // Closes the input-device.
60 // Returns true if the input-device was closed successfully.
61 ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
67 tColorPacket CAtmoExternalCaptureInput::GetColorPacket(void)
69 return this->m_ColorPacket;
73 this method will be called from another thread or possible the COM Server to feed
74 new pixeldata into the calculation process it doest just the following:
75 1: check if last buffer was allready processed (!m_pCurrentFramePixels)
76 2. copy the bitmap info structure into the threads own one
77 3. alloc memory for frame
78 4. copy sourcepixeldata into own buffer...
79 5. let the thread wake up and return imediately to the caller
80 so that the real videoout wouldn't be stop for a too long time
82 void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
85 normaly we should protect this area of code by critical_section or a mutex,
86 but I think we can omit this here because the timing this method is called
87 is really slow (in terms of the speed of a modern computer?)
88 so it's nearly impossible that two frames are delivert in the same time
89 the test needs and malloc needs...
91 if( !m_pCurrentFramePixels )
93 // Last Frame was processed... take this one...
94 memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
95 int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
96 switch(m_CurrentFrameHeader.biBitCount) {
97 case 8: /* PixelDataSize = PixelDataSize; */ break;
98 case 16: PixelDataSize = PixelDataSize * 2; break;
99 case 24: PixelDataSize = PixelDataSize * 3; break;
100 case 32: PixelDataSize = PixelDataSize * 4; break;
102 m_pCurrentFramePixels = malloc(PixelDataSize);
103 memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
105 #if defined(_ATMO_VLC_PLUGIN_)
106 vlc_mutex_lock( &m_WakeupLock );
107 vlc_cond_signal( &m_WakeupCond );
108 vlc_mutex_unlock( &m_WakeupLock );
110 SetEvent(m_hWakeupEvent);
117 the real thread Method which is processing the pixeldata into the hardware channel
118 values - which are used by the thread AtmoLiveView...
120 #if defined (_ATMO_VLC_PLUGIN_)
122 DWORD CAtmoExternalCaptureInput::Execute(void)
124 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput::Execute(void)");
127 vlc_mutex_lock( &m_WakeupLock );
129 while ((this->m_bTerminated == ATMO_FALSE) && (this->m_pAtmoThread->b_die == false)) {
130 int value = vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + INT64_C(75000));
132 /* DeliverNewSourceDataPaket delivered new work for me... get it! */
133 CalcColors(); // read picture and calculate colors
134 this->m_FrameArrived = ATMO_TRUE;
140 /* kludge for pthreads? using the same condition variable too often results in hanging the pthread
141 call inside vlc_cond_timedwait...
144 vlc_cond_destroy( &m_WakeupCond );
145 vlc_cond_init( m_pAtmoThread, &m_WakeupCond );
150 vlc_mutex_unlock( &m_WakeupLock );
157 DWORD CAtmoExternalCaptureInput::Execute(void) {
159 handles[0] = this->m_hTerminateEvent;
160 handles[1] = m_hWakeupEvent;
162 while (this->m_bTerminated == ATMO_FALSE) {
163 DWORD event = WaitForMultipleObjects(2,handles,ATMO_FALSE,INFINITE);
164 if(event == WAIT_OBJECT_0) {
165 // Terminate Thread Event was set... say good bye...!
168 if(event == (WAIT_OBJECT_0+1)) {
169 CalcColors(); // read picture and calculate colors
170 this->m_FrameArrived = ATMO_TRUE;
179 void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
181 this->m_FrameArrived = ATMO_FALSE;
182 for(DWORD i=0;(i<timeout) && !m_FrameArrived;i++)
183 #if defined (_ATMO_VLC_PLUGIN_)
189 if(this->m_pAtmoDynData)
191 CAtmoConfig *cfg = this->m_pAtmoDynData->getAtmoConfig();
194 int delay = cfg->getLiveView_FrameDelay();
197 #if defined (_ATMO_VLC_PLUGIN_)
198 msleep(delay * 1000);
207 void CAtmoExternalCaptureInput::CalcColors() {
208 // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
209 tHSVColor HSV_Img[IMAGE_SIZE];
210 tRGBColor pixelColor;
211 int srcIndex,index = 0;
212 memset(&HSV_Img,0,sizeof(HSV_Img));
214 // Convert Data to HSV values.. bla bla....
215 if(m_pCurrentFramePixels!=NULL)
217 if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
220 // HSVI = HSV Image allready in right format just copy the easiest task
221 // und weiterverarbeiten lassen
222 #ifdef _ATMO_VLC_PLUGIN_
223 if(m_CurrentFrameHeader.biCompression == VLC_FOURCC('H','S','V','I'))
225 if(m_CurrentFrameHeader.biCompression == MakeDword('H','S','V','I'))
228 memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
230 else if(m_CurrentFrameHeader.biCompression == BI_RGB)
232 if(m_CurrentFrameHeader.biBitCount == 16)
234 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
236 for(int y=0;y<CAP_HEIGHT;y++)
238 srcIndex = y * CAP_WIDTH;
239 for(int x=0;x<CAP_WIDTH;x++)
241 pixelColor.b = (buffer[srcIndex] & 31) << 3;
242 pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
243 pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
245 HSV_Img[index++] = RGB2HSV(pixelColor);
249 else if(m_CurrentFrameHeader.biBitCount == 24)
251 for(int y=0;y<CAP_HEIGHT;y++)
253 srcIndex = y * (CAP_WIDTH*3);
254 for(int x=0;x<CAP_WIDTH;x++)
256 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
257 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
258 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
259 HSV_Img[index++] = RGB2HSV(pixelColor);
263 else if(m_CurrentFrameHeader.biBitCount == 32)
265 for(int y=0;y<CAP_HEIGHT;y++)
267 srcIndex = y * (CAP_WIDTH*4);
268 for(int x=0;x<CAP_WIDTH;x++)
270 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
271 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
272 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
274 HSV_Img[index++] = RGB2HSV(pixelColor);
282 if the image color format wasn't recognized - the output
283 will be black (memset)
287 now convert the pixeldata into one RGB trippel for each channel,
288 this is done by some very sophisticated methods and statistics ...
290 the only thing I know - the pixel priority is controled by some
291 gradients for each edge of the picture
293 (sorry I don't know how it exactly works because the formulars
294 are done by some one else...)
296 m_ColorPacket = CalcColorsAnalyzeHSV(this->m_pAtmoDynData->getAtmoConfig(), HSV_Img);
298 /* remove the source buffe */
299 free(m_pCurrentFramePixels);
301 the buffer zereo so that deliver new data paket will wakeup the
302 thread on the next frame again
304 m_pCurrentFramePixels = NULL;