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 #error This makes no sense!
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;
145 vlc_mutex_unlock( &m_WakeupLock );
152 DWORD CAtmoExternalCaptureInput::Execute(void) {
154 handles[0] = this->m_hTerminateEvent;
155 handles[1] = m_hWakeupEvent;
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...!
163 if(event == (WAIT_OBJECT_0+1)) {
164 CalcColors(); // read picture and calculate colors
165 this->m_FrameArrived = ATMO_TRUE;
174 void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
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.
186 if(this->m_pAtmoDynData)
188 CAtmoConfig *cfg = this->m_pAtmoDynData->getAtmoConfig();
191 int delay = cfg->getLiveView_FrameDelay();
194 #if defined (_ATMO_VLC_PLUGIN_)
195 msleep(delay * 1000);
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));
211 // Convert Data to HSV values.. bla bla....
212 if(m_pCurrentFramePixels!=NULL)
214 if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
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'))
222 if(m_CurrentFrameHeader.biCompression == MakeDword('H','S','V','I'))
225 memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
227 else if(m_CurrentFrameHeader.biCompression == BI_RGB)
229 if(m_CurrentFrameHeader.biBitCount == 16)
231 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
233 for(int y=0;y<CAP_HEIGHT;y++)
235 srcIndex = y * CAP_WIDTH;
236 for(int x=0;x<CAP_WIDTH;x++)
238 pixelColor.b = (buffer[srcIndex] & 31) << 3;
239 pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
240 pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
242 HSV_Img[index++] = RGB2HSV(pixelColor);
246 else if(m_CurrentFrameHeader.biBitCount == 24)
248 for(int y=0;y<CAP_HEIGHT;y++)
250 srcIndex = y * (CAP_WIDTH*3);
251 for(int x=0;x<CAP_WIDTH;x++)
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);
260 else if(m_CurrentFrameHeader.biBitCount == 32)
262 for(int y=0;y<CAP_HEIGHT;y++)
264 srcIndex = y * (CAP_WIDTH*4);
265 for(int x=0;x<CAP_WIDTH;x++)
267 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
268 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
269 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
271 HSV_Img[index++] = RGB2HSV(pixelColor);
279 if the image color format wasn't recognized - the output
280 will be black (memset)
284 now convert the pixeldata into one RGB trippel for each channel,
285 this is done by some very sophisticated methods and statistics ...
287 the only thing I know - the pixel priority is controled by some
288 gradients for each edge of the picture
290 (sorry I don't know how it exactly works because the formulars
291 are done by some one else...)
293 m_ColorPacket = CalcColorsAnalyzeHSV(this->m_pAtmoDynData->getAtmoConfig(), HSV_Img);
295 /* remove the source buffe */
296 free(m_pCurrentFramePixels);
298 the buffer zereo so that deliver new data paket will wakeup the
299 thread on the next frame again
301 m_pCurrentFramePixels = NULL;