]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/AtmoPacketQueue.cpp
enhanced & corrected AtmoLight filter module
[vlc] / modules / video_filter / atmo / AtmoPacketQueue.cpp
1 /*
2  * AtmoPacketQueue.cpp:  works as connection between the framegrabber (color-preprocessor)
3  * and the live output thread. It works as a FIFO for the colorpackets - helps also
4  * to synchronize between grabber and liveview threads.
5  * especially if the grabber has another framerate as the liveview (25fps)
6  *
7  * See the README.txt file for copyright information and how to reach the author(s).
8  *
9  * $Id$
10  */
11
12 #include "AtmoDefs.h"
13 #include "AtmoPacketQueue.h"
14
15 #if defined(_ATMO_VLC_PLUGIN_)
16 # include <vlc/vlc.h>
17 #define MAX_PACKET_TOO_LATE  -30000
18 #define MAX_PACKET_TOO_EARLY  30000
19 #define MIN_SLEEP_TIME        15000
20 #else
21 #define MAX_PACKET_TOO_LATE  -30
22 #define MAX_PACKET_TOO_EARLY  30
23 #define MIN_SLEEP_TIME        15
24 #endif
25
26
27 #if defined(_ATMO_VLC_PLUGIN_)
28
29 CAtmoPacketQueue::CAtmoPacketQueue()
30 {
31   m_first = NULL;
32   m_last = NULL;
33   m_waitcounter   = 0;
34   m_skipcounter   = 0;
35   m_framecounter  = 0;
36   m_nullpackets   = 0;
37
38   m_avgWait  = 0;
39   m_avgDelay = 0;
40
41   vlc_cond_init( &m_PacketArrivedCond );
42   vlc_mutex_init( &m_PacketArrivedLock );
43   vlc_mutex_init( &m_Lock );
44   m_PacketArrived = ATMO_FALSE;
45 }
46
47 #else
48
49 CAtmoPacketQueue::CAtmoPacketQueue(CAtmoPacketQueueStatus *statusMonitor)
50 {
51   m_first = NULL;
52   m_last = NULL;
53   m_waitcounter   = 0;
54   m_skipcounter   = 0;
55   m_framecounter  = 0;
56   m_nullpackets   = 0;
57
58   m_avgWait  = 0;
59   m_avgDelay = 0;
60
61   m_StatusMonitor = statusMonitor;
62
63   InitializeCriticalSection(&m_lock);
64   m_hPacketArrivedEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
65 }
66
67 #endif
68
69
70 CAtmoPacketQueue::~CAtmoPacketQueue(void)
71 {
72   ClearQueue();
73
74 #if defined(_ATMO_VLC_PLUGIN_)
75
76   vlc_cond_destroy( &m_PacketArrivedCond );
77   vlc_mutex_destroy( &m_Lock );
78
79 #else
80
81   DeleteCriticalSection( &m_lock );
82   CloseHandle(m_hPacketArrivedEvent);
83   if(m_StatusMonitor)
84      m_StatusMonitor->destroyWindow();
85
86 #endif
87 }
88
89 void CAtmoPacketQueue::Lock()
90 {
91 #if defined(_ATMO_VLC_PLUGIN_)
92     vlc_mutex_lock( &m_Lock );
93 #else
94     EnterCriticalSection( &m_lock );
95 #endif
96 }
97
98 void CAtmoPacketQueue::Unlock()
99 {
100 #if defined(_ATMO_VLC_PLUGIN_)
101     vlc_mutex_unlock( &m_Lock );
102 #else
103     LeaveCriticalSection( &m_lock );
104 #endif
105 }
106
107 void CAtmoPacketQueue::SignalEvent()
108 {
109 #if defined(_ATMO_VLC_PLUGIN_)
110    vlc_mutex_lock( &m_PacketArrivedLock );
111    m_PacketArrived = ATMO_TRUE;
112    vlc_cond_signal( &m_PacketArrivedCond );
113    vlc_mutex_unlock( &m_PacketArrivedLock );
114 #else
115    SetEvent( m_hPacketArrivedEvent );
116 #endif
117 }
118
119 void CAtmoPacketQueue::UnSignalEvent()
120 {
121 #if defined(_ATMO_VLC_PLUGIN_)
122
123 #else
124    ResetEvent( m_hPacketArrivedEvent );
125 #endif
126 }
127
128 void CAtmoPacketQueue::AddPacket(pColorPacket newPacket)
129 {
130   pColorPacketItem temp = new ColorPacketItem;
131   temp->packet = newPacket;
132   temp->next = NULL;
133 #if defined(_ATMO_VLC_PLUGIN_)
134   temp->tickcount = mdate();
135 #else
136   temp->tickcount = GetTickCount();
137 #endif
138
139   Lock();
140   if(m_last) {
141      m_last->next = temp;
142      m_last = temp;
143   } else {
144      m_last = temp;
145      m_first = temp;
146   }
147   Unlock();
148   SignalEvent();
149 }
150
151 pColorPacketItem CAtmoPacketQueue::GetNextPacketContainer()
152 {
153   pColorPacketItem temp = NULL;
154
155   Lock();
156   if(m_first) {
157      temp      = m_first;
158      m_first   = m_first->next;
159      if(!m_first)
160         m_last = NULL;
161      temp->next = NULL;
162   }
163   Unlock();
164
165   return temp;
166 }
167
168 pColorPacket CAtmoPacketQueue::GetNextPacket()
169 {
170   pColorPacketItem item = GetNextPacketContainer();
171   if(item) {
172      pColorPacket temp = item->packet;
173      delete item;
174      return(temp);
175   } else
176      return(NULL);
177 }
178
179 #if defined(_ATMO_VLC_PLUGIN_)
180 void CAtmoPacketQueue::ShowQueueStatus(atmo_thread_t *p_this)
181 {
182     /*
183      show some statistics for the whole time...
184     */
185     msg_Dbg( p_this, "Skipped Packets: %d", m_skipcounter );
186     if( m_skipcounter > 0 )
187         msg_Dbg( p_this, "Average Delay: %d ms", (int)(m_avgDelay/m_skipcounter)/1000 );
188     msg_Dbg( p_this, "Waited Packets: %d", m_waitcounter );
189     if( m_waitcounter > 0 )
190         msg_Dbg( p_this, "Average Wait: %d ms", (int)(m_avgWait/m_waitcounter)/1000 );
191     msg_Dbg( p_this, "Used Packets: %d", m_framecounter );
192     msg_Dbg( p_this, "Null Packets: %d", m_nullpackets );
193 }
194 #endif
195
196 #if defined(_ATMO_VLC_PLUGIN_)
197 pColorPacket CAtmoPacketQueue::GetNextPacket(mtime_t timecode, ATMO_BOOL withWait, atmo_thread_t *p_this, mtime_t &packet_time)
198 #else
199 pColorPacket CAtmoPacketQueue::GetNextPacket(DWORD timecode, ATMO_BOOL withWait, DWORD &packet_time)
200 #endif
201 {
202 #if !defined(_ATMO_VLC_PLUGIN_)
203     if(timecode & 0x80000000) // GetTickCount - delay < 0 ;-)
204       return NULL;
205 #endif
206
207    int timeDiff;
208
209    while(1)
210    {
211      Lock();
212      if(!m_first) {
213         Unlock();
214         break;
215      }
216      timeDiff    = m_first->tickcount - timecode;
217      packet_time = m_first->tickcount;
218      Unlock();
219
220      if(timeDiff >= MAX_PACKET_TOO_EARLY) // packet should be process in 35ms or later (usually we are to early for it)
221      {
222        if( !withWait )
223             break;
224      }
225      else
226      {
227          if(timeDiff <= MAX_PACKET_TOO_LATE) {
228             // we are more than -35ms too late for this packet, skip it and throw it away!
229 #if defined(_ATMO_VLC_PLUGIN_)
230             msg_Dbg( p_this, "getNextPacket skip late %d ms", timeDiff / 1000 );
231 #endif
232             pColorPacket skip = GetNextPacket();
233             delete (char *)skip;
234
235             m_skipcounter++;
236             m_avgDelay += abs(timeDiff);
237
238             continue;
239          }
240      }
241
242      if(withWait && timeDiff > MIN_SLEEP_TIME)
243      {
244           // if this is a sync call, to get in sync with frame source again we wait untils its time!
245 #if defined(_ATMO_VLC_PLUGIN_)
246          msg_Dbg( p_this, "getNextPacket Sleep %d ms", timeDiff / 1000 );
247 #endif
248          do_sleep( timeDiff );
249
250          m_avgWait += timeDiff;
251          m_waitcounter++;
252      }
253
254      m_framecounter++;
255 #if !defined(_ATMO_VLC_PLUGIN_)
256      if(m_StatusMonitor)
257      {
258         if(withWait)
259            m_StatusMonitor->UpdateValues(m_waitcounter, m_skipcounter, m_framecounter, m_nullpackets, m_avgWait, m_avgDelay);
260      }
261 #endif
262
263      return GetNextPacket();
264    }
265
266    m_nullpackets++;
267 #if !defined(_ATMO_VLC_PLUGIN_)
268    if(m_StatusMonitor)
269    {
270       if(withWait)
271          m_StatusMonitor->UpdateValues(m_waitcounter, m_skipcounter, m_framecounter, m_nullpackets, m_avgWait, m_avgDelay);
272    }
273 #endif
274    return NULL;
275 }
276
277 ATMO_BOOL CAtmoPacketQueue::WaitForNextPacket(DWORD timeout)
278 {
279     UnSignalEvent();
280
281 #if !defined(_ATMO_VLC_PLUGIN_)
282
283     return ( WaitForSingleObject( m_hPacketArrivedEvent, timeout ) == WAIT_OBJECT_0 );
284
285 #else
286
287     mtime_t maxWait = mdate() + timeout * 1000;
288
289     vlc_mutex_lock( &m_PacketArrivedLock );
290     m_PacketArrived = ATMO_FALSE;
291     while(vlc_cond_timedwait( &m_PacketArrivedCond, &m_PacketArrivedLock, maxWait) == 0)
292     {
293       /*
294         condition was set -> but may be an old signal from previous AddPacket
295         which is still left - so if m_PacketArrived is still false, wait again
296       */
297       if(mdate() >= maxWait)
298          break;
299       if( m_PacketArrived )
300          break;
301     }
302     vlc_mutex_unlock( &m_PacketArrivedLock );
303     return m_PacketArrived;
304
305 #endif
306 }
307
308 void CAtmoPacketQueue::ClearQueue()
309 {
310   pColorPacketItem next;
311
312   Lock();
313
314   while(m_first)
315   {
316       next = m_first->next;
317       delete (char *)(m_first->packet);
318       delete m_first;
319       m_first = next;
320   }
321   m_last = NULL;
322
323   m_waitcounter   = 0;
324   m_skipcounter   = 0;
325   m_framecounter  = 0;
326
327   m_avgWait  = 0;
328   m_avgDelay = 0;
329   m_nullpackets = 0;
330
331   Unlock();
332 }