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 free( m_pCurrentFramePixels );
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.");
52 CloseHandle(m_hWakeupEvent);
56 ATMO_BOOL CAtmoExternalCaptureInput::Open()
62 // Closes the input-device.
63 // Returns true if the input-device was closed successfully.
64 ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
70 tColorPacket CAtmoExternalCaptureInput::GetColorPacket(void)
72 return this->m_ColorPacket;
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
85 void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
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...
94 if( !m_pCurrentFramePixels )
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;
105 m_pCurrentFramePixels = malloc(PixelDataSize);
106 memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
108 #if defined(_ATMO_VLC_PLUGIN_)
109 vlc_mutex_lock( &m_WakeupLock );
110 vlc_cond_signal( &m_WakeupCond );
111 vlc_mutex_unlock( &m_WakeupLock );
113 SetEvent(m_hWakeupEvent);
120 the real thread Method which is processing the pixeldata into the hardware channel
121 values - which are used by the thread AtmoLiveView...
123 #if defined (_ATMO_VLC_PLUGIN_)
125 DWORD CAtmoExternalCaptureInput::Execute(void)
127 msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput::Execute(void)");
130 vlc_mutex_lock( &m_WakeupLock );
132 while ((this->m_bTerminated == ATMO_FALSE) && (!vlc_object_alive (this->m_pAtmoThread) == false)) {
133 int value = vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + INT64_C(75000));
135 /* DeliverNewSourceDataPaket delivered new work for me... get it! */
136 CalcColors(); // read picture and calculate colors
137 this->m_FrameArrived = ATMO_TRUE;
143 /* kludge for pthreads? using the same condition variable too often results in hanging the pthread
144 call inside vlc_cond_timedwait...
147 vlc_cond_destroy( &m_WakeupCond );
148 vlc_cond_init( &m_WakeupCond );
153 vlc_mutex_unlock( &m_WakeupLock );
160 DWORD CAtmoExternalCaptureInput::Execute(void) {
162 handles[0] = this->m_hTerminateEvent;
163 handles[1] = m_hWakeupEvent;
165 while (this->m_bTerminated == ATMO_FALSE) {
166 DWORD event = WaitForMultipleObjects(2,handles,ATMO_FALSE,INFINITE);
167 if(event == WAIT_OBJECT_0) {
168 // Terminate Thread Event was set... say good bye...!
171 if(event == (WAIT_OBJECT_0+1)) {
172 CalcColors(); // read picture and calculate colors
173 this->m_FrameArrived = ATMO_TRUE;
182 void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
184 this->m_FrameArrived = ATMO_FALSE;
185 for(DWORD i=0;(i<timeout) && !m_FrameArrived;i++)
186 #if defined (_ATMO_VLC_PLUGIN_)
192 if(this->m_pAtmoDynData)
194 CAtmoConfig *cfg = this->m_pAtmoDynData->getAtmoConfig();
197 int delay = cfg->getLiveView_FrameDelay();
200 #if defined (_ATMO_VLC_PLUGIN_)
201 msleep(delay * 1000);
210 void CAtmoExternalCaptureInput::CalcColors() {
211 // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
212 tHSVColor HSV_Img[IMAGE_SIZE];
213 tRGBColor pixelColor;
214 int srcIndex,index = 0;
215 memset(&HSV_Img,0,sizeof(HSV_Img));
217 // Convert Data to HSV values.. bla bla....
218 if(m_pCurrentFramePixels!=NULL)
220 if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
223 // HSVI = HSV Image allready in right format just copy the easiest task
224 // und weiterverarbeiten lassen
225 #ifdef _ATMO_VLC_PLUGIN_
226 if(m_CurrentFrameHeader.biCompression == VLC_FOURCC('H','S','V','I'))
228 if(m_CurrentFrameHeader.biCompression == MakeDword('H','S','V','I'))
231 memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
233 else if(m_CurrentFrameHeader.biCompression == BI_RGB)
235 if(m_CurrentFrameHeader.biBitCount == 16)
237 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
239 for(int y=0;y<CAP_HEIGHT;y++)
241 srcIndex = y * CAP_WIDTH;
242 for(int x=0;x<CAP_WIDTH;x++)
244 pixelColor.b = (buffer[srcIndex] & 31) << 3;
245 pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
246 pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
248 HSV_Img[index++] = RGB2HSV(pixelColor);
252 else if(m_CurrentFrameHeader.biBitCount == 24)
254 for(int y=0;y<CAP_HEIGHT;y++)
256 srcIndex = y * (CAP_WIDTH*3);
257 for(int x=0;x<CAP_WIDTH;x++)
259 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
260 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
261 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
262 HSV_Img[index++] = RGB2HSV(pixelColor);
266 else if(m_CurrentFrameHeader.biBitCount == 32)
268 for(int y=0;y<CAP_HEIGHT;y++)
270 srcIndex = y * (CAP_WIDTH*4);
271 for(int x=0;x<CAP_WIDTH;x++)
273 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
274 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
275 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
277 HSV_Img[index++] = RGB2HSV(pixelColor);
285 if the image color format wasn't recognized - the output
286 will be black (memset)
290 now convert the pixeldata into one RGB trippel for each channel,
291 this is done by some very sophisticated methods and statistics ...
293 the only thing I know - the pixel priority is controled by some
294 gradients for each edge of the picture
296 (sorry I don't know how it exactly works because the formulars
297 are done by some one else...)
299 m_ColorPacket = CalcColorsAnalyzeHSV(this->m_pAtmoDynData->getAtmoConfig(), HSV_Img);
301 /* remove the source buffe */
302 free(m_pCurrentFramePixels);
304 the buffer zereo so that deliver new data paket will wakeup the
305 thread on the next frame again
307 m_pCurrentFramePixels = NULL;