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).
15 #include "AtmoExternalCaptureInput.h"
16 #include "AtmoTools.h"
19 #if defined(_ATMO_VLC_PLUGIN_)
23 #define INT64_C(c) c ## LL
26 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
27 CAtmoInput(pAtmoDynData)
29 vlc_cond_init( &m_WakeupCond );
30 vlc_mutex_init( &m_WakeupLock );
31 m_pCurrentFramePixels = NULL;
32 m_pLog = pAtmoDynData->getAtmoFilter();
37 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
38 CAtmoInput(pAtmoDynData)
40 m_hWakeupEvent = CreateEvent(NULL,0,0,NULL);
41 InitializeCriticalSection( &m_BufferLock );
42 m_pCurrentFramePixels = NULL;
47 CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
49 /* if there is still an unprocessed bufferpicture do kill it */
50 #if defined(_ATMO_VLC_PLUGIN_)
51 vlc_mutex_lock( &m_WakeupLock );
52 free( m_pCurrentFramePixels );
53 vlc_mutex_unlock( &m_WakeupLock );
55 vlc_cond_destroy( &m_WakeupCond );
56 vlc_mutex_destroy( &m_WakeupLock );
58 EnterCriticalSection( &m_BufferLock );
59 free( m_pCurrentFramePixels );
60 LeaveCriticalSection( &m_BufferLock );
61 CloseHandle(m_hWakeupEvent);
62 DeleteCriticalSection( &m_BufferLock );
66 ATMO_BOOL CAtmoExternalCaptureInput::Open()
72 // Closes the input-device.
73 // Returns true if the input-device was closed successfully.
74 ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
82 this method will be called from another thread or possible the COM Server to feed
83 new pixeldata into the calculation process it doest just the following:
84 1: check if last buffer was allready processed (!m_pCurrentFramePixels)
85 2. copy the bitmap info structure into the threads own one
86 3. alloc memory for frame
87 4. copy sourcepixeldata into own buffer...
88 5. let the thread wake up and return imediately to the caller
89 so that the real videoout wouldn't be stop for a too long time
91 void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
94 normaly we should protect this area of code by critical_section or a mutex,
95 but I think we can omit this here because the timing this method is called
96 is really slow (in terms of the speed of a modern computer?)
97 so it's nearly impossible that two frames are delivert in the same time
98 the test needs and malloc needs...
100 #if defined(_ATMO_VLC_PLUGIN_)
101 // msg_Dbg( m_pLog, "DeliverNewSourceDataPaket start...");
102 vlc_mutex_lock( &m_WakeupLock );
104 EnterCriticalSection( &m_BufferLock );
106 if( !m_pCurrentFramePixels )
108 // Last Frame was processed... take this one...
109 memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
110 int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
111 switch(m_CurrentFrameHeader.biBitCount) {
112 case 8: /* PixelDataSize = PixelDataSize; */ break;
113 case 16: PixelDataSize = PixelDataSize * 2; break;
114 case 24: PixelDataSize = PixelDataSize * 3; break;
115 case 32: PixelDataSize = PixelDataSize * 4; break;
117 m_pCurrentFramePixels = malloc(PixelDataSize);
118 memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
120 #if defined(_ATMO_VLC_PLUGIN_)
121 vlc_cond_signal( &m_WakeupCond );
122 vlc_mutex_unlock( &m_WakeupLock );
123 // msg_Dbg( m_pLog, "DeliverNewSourceDataPaket done.");
125 SetEvent(m_hWakeupEvent);
126 LeaveCriticalSection( &m_BufferLock );
133 the real thread Method which is processing the pixeldata into the hardware channel
134 values - which are used by the thread AtmoLiveView...
136 #if defined (_ATMO_VLC_PLUGIN_)
138 DWORD CAtmoExternalCaptureInput::Execute(void)
140 while ((this->m_bTerminated == ATMO_FALSE)) {
141 vlc_mutex_lock( &m_WakeupLock );
142 vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + 75000 );
144 /* DeliverNewSourceDataPaket delivered new work for me... get it! */
145 if(m_pCurrentFramePixels)
146 CalcColors(); // read picture and calculate colors
147 vlc_mutex_unlock( &m_WakeupLock );
150 msg_Dbg( m_pLog, "DWORD CAtmoExternalCaptureInput::Execute(void) bailed out?");
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[0], 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 EnterCriticalSection( &m_BufferLock );
170 if(m_pCurrentFramePixels)
171 CalcColors(); // read picture and calculate colors
172 LeaveCriticalSection( &m_BufferLock );
181 void CAtmoExternalCaptureInput::CalcColors()
183 // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
184 tHSVColor HSV_Img[IMAGE_SIZE];
185 tRGBColor pixelColor;
186 int srcIndex,index = 0;
187 memset(&HSV_Img,0,sizeof(HSV_Img));
189 // msg_Dbg( m_pLog, "CalcColors start...");
191 if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
194 // HSVI = HSV Image allready in right format just copy the easiest task
195 // und weiterverarbeiten lassen
196 #ifdef _ATMO_VLC_PLUGIN_
197 if(m_CurrentFrameHeader.biCompression == VLC_FOURCC('H','S','V','I'))
199 if(m_CurrentFrameHeader.biCompression == MakeDword('H','S','V','I'))
202 memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
204 else if(m_CurrentFrameHeader.biCompression == BI_RGB)
206 if(m_CurrentFrameHeader.biBitCount == 16)
208 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
210 for(int y=0;y<CAP_HEIGHT;y++)
212 srcIndex = y * CAP_WIDTH;
213 for(int x=0;x<CAP_WIDTH;x++)
215 pixelColor.b = (buffer[srcIndex] & 31) << 3;
216 pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
217 pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
219 HSV_Img[index++] = RGB2HSV(pixelColor);
223 else if(m_CurrentFrameHeader.biBitCount == 24)
225 for(int y=0;y<CAP_HEIGHT;y++)
227 srcIndex = y * (CAP_WIDTH*3);
228 for(int x=0;x<CAP_WIDTH;x++)
230 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
231 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
232 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
233 HSV_Img[index++] = RGB2HSV(pixelColor);
237 else if(m_CurrentFrameHeader.biBitCount == 32)
239 for(int y=0;y<CAP_HEIGHT;y++)
241 srcIndex = y * (CAP_WIDTH*4);
242 for(int x=0;x<CAP_WIDTH;x++)
244 pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
245 pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
246 pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
248 HSV_Img[index++] = RGB2HSV(pixelColor);
256 if the image color format wasn't recognized - the output
257 will be black (memset)
261 /* remove the source buffer */
262 free( m_pCurrentFramePixels );
263 m_pCurrentFramePixels = NULL;
266 now convert the pixeldata into one RGB trippel for each channel,
267 this is done by some very sophisticated methods and statistics ...
269 the only thing I know - the pixel priority is controled by some
270 gradients for each edge of the picture
272 (sorry I don't know how it exactly works because the formulas
273 are done by some one else...)
275 //msg_Dbg( m_pLog, "CalcColors ende AddPacket...");
276 m_pAtmoDynData->getLivePacketQueue()->AddPacket( m_pAtmoColorCalculator->AnalyzeHSV( HSV_Img ) );
277 //msg_Dbg( m_pLog, "CalcColors ende AddPacket...done.");