]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/AtmoExternalCaptureInput.cpp
TS: prioritize normal audio tracks over special ones
[vlc] / modules / video_filter / atmo / AtmoExternalCaptureInput.cpp
1 /*
2  * AtmoExternalCaptureInput.cpp: Datasource which gets its data via a COM object call
3  * or some other external method.
4  *
5  *
6  * See the README.txt file for copyright information and how to reach the author(s).
7  *
8  * $Id$
9 */
10
11 #include "AtmoExternalCaptureInput.h"
12 #include "AtmoTools.h"
13
14
15 #if defined(_ATMO_VLC_PLUGIN_)
16
17
18 #ifndef INT64_C
19 #define INT64_C(c)  c ## LL
20 #endif
21
22 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
23                            CAtmoInput(pAtmoDynData)
24 {
25     vlc_cond_init( &m_WakeupCond );
26     vlc_mutex_init( &m_WakeupLock );
27     m_pCurrentFramePixels = NULL;
28 }
29
30 #else
31
32 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
33                            CAtmoInput(pAtmoDynData)
34 {
35     m_hWakeupEvent = CreateEvent(NULL,0,0,NULL);
36     InitializeCriticalSection( &m_BufferLock );
37     m_pCurrentFramePixels = NULL;
38 }
39
40 #endif
41
42 CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
43 {
44    /* if there is still an unprocessed bufferpicture do kill it */
45 #if defined(_ATMO_VLC_PLUGIN_)
46    vlc_mutex_lock( &m_WakeupLock );
47    free( m_pCurrentFramePixels );
48    vlc_mutex_unlock( &m_WakeupLock );
49
50    vlc_cond_destroy( &m_WakeupCond );
51    vlc_mutex_destroy( &m_WakeupLock );
52 #else
53    EnterCriticalSection( &m_BufferLock );
54    free( m_pCurrentFramePixels );
55    LeaveCriticalSection( &m_BufferLock );
56    CloseHandle(m_hWakeupEvent);
57    DeleteCriticalSection( &m_BufferLock );
58 #endif
59 }
60
61 ATMO_BOOL CAtmoExternalCaptureInput::Open()
62 {
63     this->Run();
64     return ATMO_TRUE;
65 }
66
67 // Closes the input-device.
68 // Returns true if the input-device was closed successfully.
69 ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
70 {
71     this->Terminate();
72     return ATMO_TRUE;
73 }
74
75
76 /*
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
85 */
86 void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
87 {
88     /*
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...
94     */
95 #if defined(_ATMO_VLC_PLUGIN_)
96 //    msg_Dbg( m_pAtmoThread, "DeliverNewSourceDataPaket start...");
97     vlc_mutex_lock( &m_WakeupLock );
98 #else
99     EnterCriticalSection( &m_BufferLock );
100 #endif
101     if( !m_pCurrentFramePixels )
102     {
103         // Last Frame was processed... take this one...
104         memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
105         int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
106         switch(m_CurrentFrameHeader.biBitCount) {
107             case 8:  /* PixelDataSize = PixelDataSize; */ break;
108             case 16: PixelDataSize = PixelDataSize * 2; break;
109             case 24: PixelDataSize = PixelDataSize * 3; break;
110             case 32: PixelDataSize = PixelDataSize * 4; break;
111         }
112         m_pCurrentFramePixels = malloc(PixelDataSize);
113         memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
114     }
115 #if defined(_ATMO_VLC_PLUGIN_)
116     vlc_cond_signal( &m_WakeupCond );
117     vlc_mutex_unlock( &m_WakeupLock );
118     // msg_Dbg( m_pAtmoThread, "DeliverNewSourceDataPaket done.");
119 #else
120     SetEvent(m_hWakeupEvent);
121     LeaveCriticalSection( &m_BufferLock );
122 #endif
123 }
124
125
126
127 /*
128  the real thread Method which is processing the pixeldata into the hardware channel
129  values - which are used by the thread AtmoLiveView...
130 */
131 #if defined (_ATMO_VLC_PLUGIN_)
132
133 DWORD CAtmoExternalCaptureInput::Execute(void)
134 {
135     while ((this->m_bTerminated == ATMO_FALSE) && (this->m_pAtmoThread->b_die == false)) {
136           vlc_mutex_lock( &m_WakeupLock );
137           vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + 75000 );
138
139           /* DeliverNewSourceDataPaket delivered new work for me... get it! */
140           if(m_pCurrentFramePixels)
141              CalcColors(); // read picture and calculate colors
142           vlc_mutex_unlock( &m_WakeupLock );
143     }
144
145     msg_Dbg( m_pAtmoThread, "DWORD CAtmoExternalCaptureInput::Execute(void) bailed out?");
146
147     return 0;
148 }
149
150 #else
151
152 DWORD CAtmoExternalCaptureInput::Execute(void) {
153     HANDLE handles[2];
154     handles[0] = this->m_hTerminateEvent;
155     handles[1] = m_hWakeupEvent;
156
157     while (this->m_bTerminated == ATMO_FALSE) {
158            DWORD event = WaitForMultipleObjects(2, &handles[0], FALSE, INFINITE);
159            if(event == WAIT_OBJECT_0) {
160               // Terminate Thread Event was set... say good bye...!
161               break;
162            }
163            if(event == (WAIT_OBJECT_0+1)) {
164               EnterCriticalSection( &m_BufferLock );
165               if(m_pCurrentFramePixels)
166                  CalcColors(); // read picture and calculate colors
167               LeaveCriticalSection( &m_BufferLock );
168            }
169     }
170     return 0;
171 }
172
173 #endif
174
175
176 void CAtmoExternalCaptureInput::CalcColors()
177 {
178      // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
179     tHSVColor HSV_Img[IMAGE_SIZE];
180     tRGBColor pixelColor;
181     int srcIndex,index = 0;
182     memset(&HSV_Img,0,sizeof(HSV_Img));
183
184     // msg_Dbg( m_pAtmoThread, "CalcColors start...");
185
186     if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
187     {
188
189         // HSVI = HSV Image allready in right format just copy the easiest task
190         // und weiterverarbeiten lassen
191 #ifdef _ATMO_VLC_PLUGIN_
192         if(m_CurrentFrameHeader.biCompression ==  VLC_FOURCC('H','S','V','I'))
193 #else
194         if(m_CurrentFrameHeader.biCompression ==  MakeDword('H','S','V','I'))
195 #endif
196         {
197             memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
198         }
199         else if(m_CurrentFrameHeader.biCompression == BI_RGB)
200         {
201             if(m_CurrentFrameHeader.biBitCount == 16)
202             {
203                 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
204
205                 for(int y=0;y<CAP_HEIGHT;y++)
206                 {
207                     srcIndex = y * CAP_WIDTH;
208                     for(int x=0;x<CAP_WIDTH;x++)
209                     {
210                         pixelColor.b = (buffer[srcIndex] & 31) << 3;
211                         pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
212                         pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
213                         srcIndex++;
214                         HSV_Img[index++] = RGB2HSV(pixelColor);
215                     }
216                 }
217             }
218             else if(m_CurrentFrameHeader.biBitCount == 24)
219             {
220                 for(int y=0;y<CAP_HEIGHT;y++)
221                 {
222                     srcIndex = y * (CAP_WIDTH*3);
223                     for(int x=0;x<CAP_WIDTH;x++)
224                     {
225                         pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
226                         pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
227                         pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
228                         HSV_Img[index++] = RGB2HSV(pixelColor);
229                     }
230                 }
231             }
232             else if(m_CurrentFrameHeader.biBitCount == 32)
233             {
234                 for(int y=0;y<CAP_HEIGHT;y++)
235                 {
236                     srcIndex = y * (CAP_WIDTH*4);
237                     for(int x=0;x<CAP_WIDTH;x++)
238                     {
239                         pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
240                         pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
241                         pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
242                         srcIndex++;
243                         HSV_Img[index++] = RGB2HSV(pixelColor);
244                     }
245                 }
246             }
247         }
248     }
249     /*
250       else {
251         if the image color format wasn't recognized - the output
252         will be black (memset)
253         }
254     */
255
256     /* remove the source buffer */
257     free( m_pCurrentFramePixels );
258     m_pCurrentFramePixels = NULL;
259
260     /*
261         now convert the pixeldata into one RGB trippel for each channel,
262         this is done by some very sophisticated methods and statistics ...
263
264         the only thing I know - the pixel priority is controled by some
265         gradients for each edge of the picture
266
267         (sorry I don't know how it exactly works because the formulas
268         are done by some one else...)
269     */
270     //msg_Dbg( m_pAtmoThread, "CalcColors ende AddPacket...");
271     m_pAtmoDynData->getLivePacketQueue()->AddPacket( m_pAtmoColorCalculator->AnalyzeHSV( HSV_Img ) );
272     //msg_Dbg( m_pAtmoThread, "CalcColors ende AddPacket...done.");
273 }
274