Diffstat (limited to 'core/multimedia/opieplayer/loopcontrol_threaded.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/loopcontrol_threaded.cpp | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/core/multimedia/opieplayer/loopcontrol_threaded.cpp b/core/multimedia/opieplayer/loopcontrol_threaded.cpp index 0a1fc17..9a162c2 100644 --- a/core/multimedia/opieplayer/loopcontrol_threaded.cpp +++ b/core/multimedia/opieplayer/loopcontrol_threaded.cpp | |||
@@ -1,91 +1,97 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qtopia Environment. | 4 | ** This file is part of Qtopia Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | #define _REENTRANT | 20 | #define _REENTRANT |
21 | 21 | ||
22 | #include "mediaplayerplugininterface.h" | ||
23 | #include "loopcontrol.h" | ||
24 | #include "audiodevice.h" | ||
25 | #include "videowidget.h" | ||
26 | #include "audiowidget.h" | ||
27 | #include "mediaplayerstate.h" | ||
28 | |||
29 | /* OPIE */ | ||
22 | #include <qpe/qpeapplication.h> | 30 | #include <qpe/qpeapplication.h> |
23 | #include <qpe/custom.h> | 31 | #include <qpe/custom.h> |
24 | #include <qimage.h> | 32 | |
25 | #include <qpainter.h> | ||
26 | #if !defined(QT_NO_COP) | 33 | #if !defined(QT_NO_COP) |
27 | #include <qpe/qcopenvelope_qws.h> | 34 | #include <qpe/qcopenvelope_qws.h> |
28 | #endif | 35 | #endif |
29 | #include "mediaplayerplugininterface.h" | 36 | |
37 | #include <opie2/odebug.h> | ||
38 | |||
39 | /* QT */ | ||
40 | #include <qimage.h> | ||
41 | #include <qpainter.h> | ||
42 | |||
43 | /* STD */ | ||
30 | #include <stdio.h> | 44 | #include <stdio.h> |
31 | #include <stdlib.h> | 45 | #include <stdlib.h> |
32 | #include <string.h> | 46 | #include <string.h> |
33 | #include <time.h> | 47 | #include <time.h> |
34 | #include <unistd.h> | 48 | #include <unistd.h> |
35 | #include <pthread.h> | 49 | #include <pthread.h> |
36 | #include "loopcontrol.h" | ||
37 | #include "audiodevice.h" | ||
38 | #include "videowidget.h" | ||
39 | #include "audiowidget.h" | ||
40 | #include "mediaplayerstate.h" | ||
41 | |||
42 | |||
43 | |||
44 | 50 | ||
45 | 51 | ||
46 | extern VideoWidget *videoUI; // now only needed to tell it to play a frame | 52 | extern VideoWidget *videoUI; // now only needed to tell it to play a frame |
47 | extern MediaPlayerState *mediaPlayerState; | 53 | extern MediaPlayerState *mediaPlayerState; |
48 | 54 | ||
49 | 55 | ||
50 | #define DecodeLoopDebug(x) qDebug x | 56 | #define DecodeLoopDebug(x) qDebug x |
51 | //#define DecodeLoopDebug(x) | 57 | //#define DecodeLoopDebug(x) |
52 | 58 | ||
53 | 59 | ||
54 | static char *audioBuffer = NULL; | 60 | static char *audioBuffer = NULL; |
55 | static AudioDevice *audioDevice = NULL; | 61 | static AudioDevice *audioDevice = NULL; |
56 | static bool disabledSuspendScreenSaver = FALSE; | 62 | static bool disabledSuspendScreenSaver = FALSE; |
57 | 63 | ||
58 | 64 | ||
59 | pthread_t video_tid; | 65 | pthread_t video_tid; |
60 | pthread_attr_t video_attr; | 66 | pthread_attr_t video_attr; |
61 | pthread_t audio_tid; | 67 | pthread_t audio_tid; |
62 | pthread_attr_t audio_attr; | 68 | pthread_attr_t audio_attr; |
63 | 69 | ||
64 | 70 | ||
65 | bool emitPlayFinished = FALSE; | 71 | bool emitPlayFinished = FALSE; |
66 | bool emitChangePos = FALSE; | 72 | bool emitChangePos = FALSE; |
67 | 73 | ||
68 | 74 | ||
69 | class Mutex { | 75 | class Mutex { |
70 | public: | 76 | public: |
71 | Mutex() { | 77 | Mutex() { |
72 | pthread_mutexattr_t attr; | 78 | pthread_mutexattr_t attr; |
73 | pthread_mutexattr_init( &attr ); | 79 | pthread_mutexattr_init( &attr ); |
74 | pthread_mutex_init( &mutex, &attr ); | 80 | pthread_mutex_init( &mutex, &attr ); |
75 | pthread_mutexattr_destroy( &attr ); | 81 | pthread_mutexattr_destroy( &attr ); |
76 | } | 82 | } |
77 | 83 | ||
78 | ~Mutex() { | 84 | ~Mutex() { |
79 | pthread_mutex_destroy( &mutex ); | 85 | pthread_mutex_destroy( &mutex ); |
80 | } | 86 | } |
81 | 87 | ||
82 | void lock() { | 88 | void lock() { |
83 | pthread_mutex_lock( &mutex ); | 89 | pthread_mutex_lock( &mutex ); |
84 | } | 90 | } |
85 | 91 | ||
86 | void unlock() { | 92 | void unlock() { |
87 | pthread_mutex_unlock( &mutex ); | 93 | pthread_mutex_unlock( &mutex ); |
88 | } | 94 | } |
89 | /* | 95 | /* |
90 | bool locked() { | 96 | bool locked() { |
91 | switch ( pthread_mutex_trylock( &mutex ) ) { | 97 | switch ( pthread_mutex_trylock( &mutex ) ) { |
@@ -146,97 +152,97 @@ LoopControl::~LoopControl() { | |||
146 | killTimer( timerid ); | 152 | killTimer( timerid ); |
147 | } | 153 | } |
148 | 154 | ||
149 | 155 | ||
150 | static bool sendingNewPos = FALSE; | 156 | static bool sendingNewPos = FALSE; |
151 | static long prev_frame = 0; | 157 | static long prev_frame = 0; |
152 | static int currentSample = 0; | 158 | static int currentSample = 0; |
153 | 159 | ||
154 | 160 | ||
155 | void LoopControl::timerEvent( QTimerEvent* ) { | 161 | void LoopControl::timerEvent( QTimerEvent* ) { |
156 | // We need to emit playFinished from the main thread, not one of the | 162 | // We need to emit playFinished from the main thread, not one of the |
157 | // decoding threads else we'll have all kinds of yucky things happen (reentrance). | 163 | // decoding threads else we'll have all kinds of yucky things happen (reentrance). |
158 | // playFinished will eventually call stop() which stops these threads. | 164 | // playFinished will eventually call stop() which stops these threads. |
159 | if ( emitPlayFinished ) { | 165 | if ( emitPlayFinished ) { |
160 | emitPlayFinished = FALSE; | 166 | emitPlayFinished = FALSE; |
161 | mediaPlayerState->setPlaying( FALSE ); | 167 | mediaPlayerState->setPlaying( FALSE ); |
162 | } | 168 | } |
163 | 169 | ||
164 | if ( emitChangePos ) { | 170 | if ( emitChangePos ) { |
165 | 171 | ||
166 | emitChangePos = FALSE; | 172 | emitChangePos = FALSE; |
167 | 173 | ||
168 | if ( hasVideoChannel && hasAudioChannel ) { | 174 | if ( hasVideoChannel && hasAudioChannel ) { |
169 | sendingNewPos = TRUE; | 175 | sendingNewPos = TRUE; |
170 | mediaPlayerState->setPosition( current_frame ); | 176 | mediaPlayerState->setPosition( current_frame ); |
171 | } else if ( hasVideoChannel ) { | 177 | } else if ( hasVideoChannel ) { |
172 | sendingNewPos = TRUE; | 178 | sendingNewPos = TRUE; |
173 | mediaPlayerState->setPosition( current_frame ); | 179 | mediaPlayerState->setPosition( current_frame ); |
174 | } else if ( hasAudioChannel ) { | 180 | } else if ( hasAudioChannel ) { |
175 | sendingNewPos = TRUE; | 181 | sendingNewPos = TRUE; |
176 | mediaPlayerState->setPosition( audioSampleCounter ); | 182 | mediaPlayerState->setPosition( audioSampleCounter ); |
177 | } | 183 | } |
178 | 184 | ||
179 | } | 185 | } |
180 | } | 186 | } |
181 | 187 | ||
182 | 188 | ||
183 | 189 | ||
184 | 190 | ||
185 | void LoopControl::setPosition( long pos ) { | 191 | void LoopControl::setPosition( long pos ) { |
186 | if ( sendingNewPos ) { | 192 | if ( sendingNewPos ) { |
187 | sendingNewPos = FALSE; | 193 | sendingNewPos = FALSE; |
188 | return; | 194 | return; |
189 | } | 195 | } |
190 | 196 | ||
191 | if ( hasVideoChannel && hasAudioChannel ) { | 197 | if ( hasVideoChannel && hasAudioChannel ) { |
192 | videoMutex->lock(); | 198 | videoMutex->lock(); |
193 | audioMutex->lock(); | 199 | audioMutex->lock(); |
194 | //qDebug("setting position"); | 200 | //odebug << "setting position" << oendl; |
195 | playtime.restart(); | 201 | playtime.restart(); |
196 | playtime = playtime.addMSecs( -pos * 1000 / framerate ); | 202 | playtime = playtime.addMSecs( -pos * 1000 / framerate ); |
197 | //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; | 203 | //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; |
198 | current_frame = pos + 1; | 204 | current_frame = pos + 1; |
199 | mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); | 205 | mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); |
200 | prev_frame = current_frame - 1; | 206 | prev_frame = current_frame - 1; |
201 | currentSample = (int)( current_frame * freq / framerate ); | 207 | currentSample = (int)( current_frame * freq / framerate ); |
202 | mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); | 208 | mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); |
203 | audioSampleCounter = currentSample - 1; | 209 | audioSampleCounter = currentSample - 1; |
204 | audioMutex->unlock(); | 210 | audioMutex->unlock(); |
205 | videoMutex->unlock(); | 211 | videoMutex->unlock(); |
206 | } else if ( hasVideoChannel ) { | 212 | } else if ( hasVideoChannel ) { |
207 | videoMutex->lock(); | 213 | videoMutex->lock(); |
208 | playtime.restart(); | 214 | playtime.restart(); |
209 | playtime = playtime.addMSecs( -pos * 1000 / framerate ); | 215 | playtime = playtime.addMSecs( -pos * 1000 / framerate ); |
210 | //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; | 216 | //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; |
211 | current_frame = pos + 1; | 217 | current_frame = pos + 1; |
212 | mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); | 218 | mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); |
213 | videoMutex->unlock(); | 219 | videoMutex->unlock(); |
214 | prev_frame = current_frame - 1; | 220 | prev_frame = current_frame - 1; |
215 | } else if ( hasAudioChannel ) { | 221 | } else if ( hasAudioChannel ) { |
216 | audioMutex->lock(); | 222 | audioMutex->lock(); |
217 | playtime.restart(); | 223 | playtime.restart(); |
218 | playtime = playtime.addMSecs( -pos * 1000 / freq ); | 224 | playtime = playtime.addMSecs( -pos * 1000 / freq ); |
219 | //begin = clock() - (double)pos * CLOCKS_PER_SEC / freq; | 225 | //begin = clock() - (double)pos * CLOCKS_PER_SEC / freq; |
220 | currentSample = pos + 1; // (int)( current_frame * freq / framerate ); | 226 | currentSample = pos + 1; // (int)( current_frame * freq / framerate ); |
221 | mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); | 227 | mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); |
222 | audioSampleCounter = currentSample - 1; | 228 | audioSampleCounter = currentSample - 1; |
223 | audioMutex->unlock(); | 229 | audioMutex->unlock(); |
224 | } | 230 | } |
225 | } | 231 | } |
226 | 232 | ||
227 | 233 | ||
228 | void *startVideoThread( void *ptr ) { | 234 | void *startVideoThread( void *ptr ) { |
229 | LoopControl *mpegView = (LoopControl *)ptr; | 235 | LoopControl *mpegView = (LoopControl *)ptr; |
230 | mpegView->startVideo(); | 236 | mpegView->startVideo(); |
231 | return 0; | 237 | return 0; |
232 | } | 238 | } |
233 | 239 | ||
234 | void *startAudioThread( void *ptr ) { | 240 | void *startAudioThread( void *ptr ) { |
235 | LoopControl *mpegView = (LoopControl *)ptr; | 241 | LoopControl *mpegView = (LoopControl *)ptr; |
236 | mpegView->startAudio(); | 242 | mpegView->startAudio(); |
237 | return 0; | 243 | return 0; |
238 | } | 244 | } |
239 | 245 | ||
240 | void LoopControl::startVideo() { | 246 | void LoopControl::startVideo() { |
241 | moreVideo = TRUE; | 247 | moreVideo = TRUE; |
242 | 248 | ||
@@ -247,317 +253,317 @@ void LoopControl::startVideo() { | |||
247 | if ( hasAudioChannel && !isMuted ) { | 253 | if ( hasAudioChannel && !isMuted ) { |
248 | 254 | ||
249 | bool done = FALSE; | 255 | bool done = FALSE; |
250 | 256 | ||
251 | do { | 257 | do { |
252 | 258 | ||
253 | 259 | ||
254 | /* | 260 | /* |
255 | videoMutex->lock(); | 261 | videoMutex->lock(); |
256 | current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); | 262 | current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); |
257 | //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; | 263 | //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; |
258 | 264 | ||
259 | // Sync to Audio | 265 | // Sync to Audio |
260 | // current_frame = (long)((double)(audioSampleCounter - 1000) * framerate / (double)freq); | 266 | // current_frame = (long)((double)(audioSampleCounter - 1000) * framerate / (double)freq); |
261 | 267 | ||
262 | long mSecsToNextFrame = 0; | 268 | long mSecsToNextFrame = 0; |
263 | 269 | ||
264 | if ( current_frame == prev_frame ) { | 270 | if ( current_frame == prev_frame ) { |
265 | int nf = current_frame + 1; | 271 | int nf = current_frame + 1; |
266 | if ( nf > 0 && nf != total_video_frames ) | 272 | if ( nf > 0 && nf != total_video_frames ) |
267 | // mSecsToNextFrame = long(double(nf * CLOCKS_PER_SEC) / framerate) - ( clock() - begin ); | 273 | // mSecsToNextFrame = long(double(nf * CLOCKS_PER_SEC) / framerate) - ( clock() - begin ); |
268 | mSecsToNextFrame = long(double(nf * 1000) / framerate) - ( playtime.elapsed() ); | 274 | mSecsToNextFrame = long(double(nf * 1000) / framerate) - ( playtime.elapsed() ); |
269 | } | 275 | } |
270 | videoMutex->unlock(); | 276 | videoMutex->unlock(); |
271 | 277 | ||
272 | if ( mSecsToNextFrame ) { | 278 | if ( mSecsToNextFrame ) { |
273 | usleep( mSecsToNextFrame ); // wait a bit | 279 | usleep( mSecsToNextFrame ); // wait a bit |
274 | 280 | ||
275 | videoMutex->lock(); | 281 | videoMutex->lock(); |
276 | // This should now be the next frame | 282 | // This should now be the next frame |
277 | current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); | 283 | current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); |
278 | //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; | 284 | //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; |
279 | videoMutex->unlock(); | 285 | videoMutex->unlock(); |
280 | } | 286 | } |
281 | 287 | ||
282 | videoMutex->lock(); | 288 | videoMutex->lock(); |
283 | done = current_frame >= prev_frame; | 289 | done = current_frame >= prev_frame; |
284 | videoMutex->unlock(); | 290 | videoMutex->unlock(); |
285 | */ | 291 | */ |
286 | videoMutex->lock(); | 292 | videoMutex->lock(); |
287 | current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); | 293 | current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); |
288 | done = current_frame >= prev_frame; | 294 | done = current_frame >= prev_frame; |
289 | videoMutex->unlock(); | 295 | videoMutex->unlock(); |
290 | if ( !done ) | 296 | if ( !done ) |
291 | usleep( 1000 ); // wait a bit | 297 | usleep( 1000 ); // wait a bit |
292 | 298 | ||
293 | } while ( !done ); | 299 | } while ( !done ); |
294 | 300 | ||
295 | // qDebug("elapsed: %i %i (%f)", int( playtime.elapsed() ), current_frame, framerate ); | 301 | // odebug << "elapsed: " << int( playtime.elapsed() ) << " " << current_frame << " (" << framerate << ")" << oendl; |
296 | 302 | ||
297 | } else { | 303 | } else { |
298 | videoMutex->lock(); | 304 | videoMutex->lock(); |
299 | current_frame++; | 305 | current_frame++; |
300 | videoMutex->unlock(); | 306 | videoMutex->unlock(); |
301 | } | 307 | } |
302 | 308 | ||
303 | videoMutex->lock(); | 309 | videoMutex->lock(); |
304 | bool check = current_frame && current_frame > prev_frame; | 310 | bool check = current_frame && current_frame > prev_frame; |
305 | videoMutex->unlock(); | 311 | videoMutex->unlock(); |
306 | 312 | ||
307 | if ( check ) { | 313 | if ( check ) { |
308 | videoMutex->lock(); | 314 | videoMutex->lock(); |
309 | if ( current_frame > prev_frame + 1 ) { | 315 | if ( current_frame > prev_frame + 1 ) { |
310 | // qDebug("skipped a frame"); | 316 | // odebug << "skipped a frame" << oendl; |
311 | mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); | 317 | mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); |
312 | } | 318 | } |
313 | prev_frame = current_frame; | 319 | prev_frame = current_frame; |
314 | if ( moreVideo = videoUI->playVideo() ) | 320 | if ( moreVideo = videoUI->playVideo() ) |
315 | emitChangePos = TRUE; | 321 | emitChangePos = TRUE; |
316 | videoMutex->unlock(); | 322 | videoMutex->unlock(); |
317 | } | 323 | } |
318 | 324 | ||
319 | } else | 325 | } else |
320 | moreVideo = FALSE; | 326 | moreVideo = FALSE; |
321 | 327 | ||
322 | } | 328 | } |
323 | 329 | ||
324 | if ( !moreVideo && !moreAudio ) | 330 | if ( !moreVideo && !moreAudio ) |
325 | emitPlayFinished = TRUE; | 331 | emitPlayFinished = TRUE; |
326 | 332 | ||
327 | pthread_exit(NULL); | 333 | pthread_exit(NULL); |
328 | } | 334 | } |
329 | 335 | ||
330 | void LoopControl::startAudio() { | 336 | void LoopControl::startAudio() { |
331 | moreAudio = TRUE; | 337 | moreAudio = TRUE; |
332 | 338 | ||
333 | while ( moreAudio ) { | 339 | while ( moreAudio ) { |
334 | 340 | ||
335 | if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) { | 341 | if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) { |
336 | 342 | ||
337 | audioMutex->lock(); | 343 | audioMutex->lock(); |
338 | currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream ); | 344 | currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream ); |
339 | 345 | ||
340 | if ( currentSample == 0 ) | 346 | if ( currentSample == 0 ) |
341 | currentSample = audioSampleCounter + 1; | 347 | currentSample = audioSampleCounter + 1; |
342 | 348 | ||
343 | // if ( currentSample != audioSampleCounter + 1 ) | 349 | // if ( currentSample != audioSampleCounter + 1 ) |
344 | // qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter); | 350 | // odebug << "out of sync with decoder " << currentSample << " " << audioSampleCounter << "" << oendl; |
345 | audioMutex->unlock(); | 351 | audioMutex->unlock(); |
346 | 352 | ||
347 | /* | 353 | /* |
348 | int sampleWeShouldBeAt = int( playtime.elapsed() ) * freq / 1000; | 354 | int sampleWeShouldBeAt = int( playtime.elapsed() ) * freq / 1000; |
349 | 355 | ||
350 | if ( sampleWeShouldBeAt - currentSample > 20000 ) { | 356 | if ( sampleWeShouldBeAt - currentSample > 20000 ) { |
351 | mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); | 357 | mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); |
352 | currentSample = sampleWeShouldBeAt; | 358 | currentSample = sampleWeShouldBeAt; |
353 | } | 359 | } |
354 | */ | 360 | */ |
355 | long samplesRead = 0; | 361 | long samplesRead = 0; |
356 | 362 | ||
357 | const long samples = 1024; | 363 | const long samples = 1024; |
358 | 364 | ||
359 | moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream ); | 365 | moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream ); |
360 | 366 | ||
361 | audioMutex->lock(); | 367 | audioMutex->lock(); |
362 | long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; | 368 | long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; |
363 | //long sampleWeShouldBeAt = long( clock() - begin ) * (double) freq / CLOCKS_PER_SEC; | 369 | //long sampleWeShouldBeAt = long( clock() - begin ) * (double) freq / CLOCKS_PER_SEC; |
364 | long sampleWaitTime = currentSample - sampleWeShouldBeAt; | 370 | long sampleWaitTime = currentSample - sampleWeShouldBeAt; |
365 | audioMutex->unlock(); | 371 | audioMutex->unlock(); |
366 | 372 | ||
367 | if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) { | 373 | if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) { |
368 | //qDebug("sampleWaitTime: %i", sampleWaitTime); | 374 | //odebug << "sampleWaitTime: " << sampleWaitTime << "" << oendl; |
369 | usleep( ( sampleWaitTime * 1000000 ) / ( freq ) ); | 375 | usleep( ( sampleWaitTime * 1000000 ) / ( freq ) ); |
370 | } else { | 376 | } else { |
371 | audioMutex->lock(); | 377 | audioMutex->lock(); |
372 | if ( sampleWaitTime <= -2000 ) { | 378 | if ( sampleWaitTime <= -2000 ) { |
373 | // qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt ); | 379 | // odebug << "need to catch up by: " << -sampleWaitTime << " (" << currentSample << "," << sampleWeShouldBeAt << ")" << oendl; |
374 | mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); | 380 | mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); |
375 | currentSample = sampleWeShouldBeAt; | 381 | currentSample = sampleWeShouldBeAt; |
376 | } | 382 | } |
377 | audioMutex->unlock(); | 383 | audioMutex->unlock(); |
378 | } | 384 | } |
379 | 385 | ||
380 | audioDevice->write( audioBuffer, samplesRead * 2 * channels ); | 386 | audioDevice->write( audioBuffer, samplesRead * 2 * channels ); |
381 | 387 | ||
382 | audioMutex->lock(); | 388 | audioMutex->lock(); |
383 | // audioSampleCounter += samplesRead; | 389 | // audioSampleCounter += samplesRead; |
384 | audioSampleCounter = currentSample + samplesRead - 1; | 390 | audioSampleCounter = currentSample + samplesRead - 1; |
385 | audioMutex->unlock(); | 391 | audioMutex->unlock(); |
386 | 392 | ||
387 | if ( !hasVideoChannel ) | 393 | if ( !hasVideoChannel ) |
388 | emitChangePos = TRUE; | 394 | emitChangePos = TRUE; |
389 | 395 | ||
390 | //qDebug("currentSample: %i audioSampleCounter: %i total_audio_samples: %i", currentSample, audioSampleCounter, total_audio_samples); | 396 | //odebug << "currentSample: " << currentSample << " audioSampleCounter: " << audioSampleCounter << " total_audio_samples: " << total_audio_samples << "" << oendl; |
391 | // qDebug("current: %i counter: %i total: %i", currentSample, audioSampleCounter, (int)total_audio_samples); | 397 | // odebug << "current: " << currentSample << " counter: " << audioSampleCounter << " total: " << (int)total_audio_samples << "" << oendl; |
392 | moreAudio = audioSampleCounter <= total_audio_samples; | 398 | moreAudio = audioSampleCounter <= total_audio_samples; |
393 | 399 | ||
394 | } else { | 400 | } else { |
395 | 401 | ||
396 | if ( mediaPlayerState->curDecoder() && hasAudioChannel ) | 402 | if ( mediaPlayerState->curDecoder() && hasAudioChannel ) |
397 | usleep( 100000 ); // Check every 1/10 sec to see if mute is off | 403 | usleep( 100000 ); // Check every 1/10 sec to see if mute is off |
398 | else | 404 | else |
399 | moreAudio = FALSE; | 405 | moreAudio = FALSE; |
400 | 406 | ||
401 | } | 407 | } |
402 | } | 408 | } |
403 | 409 | ||
404 | // qDebug( "End of file" ); | 410 | // odebug << "End of file" << oendl; |
405 | 411 | ||
406 | if ( !moreVideo && !moreAudio ) | 412 | if ( !moreVideo && !moreAudio ) |
407 | emitPlayFinished = TRUE; | 413 | emitPlayFinished = TRUE; |
408 | 414 | ||
409 | pthread_exit(NULL); | 415 | pthread_exit(NULL); |
410 | } | 416 | } |
411 | 417 | ||
412 | void LoopControl::killTimers() { | 418 | void LoopControl::killTimers() { |
413 | if ( hasVideoChannel ) { | 419 | if ( hasVideoChannel ) { |
414 | if ( pthread_self() != video_tid ) { | 420 | if ( pthread_self() != video_tid ) { |
415 | if ( pthread_cancel(video_tid) == 0 ) { | 421 | if ( pthread_cancel(video_tid) == 0 ) { |
416 | void *thread_result = 0; | 422 | void *thread_result = 0; |
417 | if ( pthread_join(video_tid,&thread_result) != 0 ) | 423 | if ( pthread_join(video_tid,&thread_result) != 0 ) |
418 | // qDebug("thread join error 1"); | 424 | // odebug << "thread join error 1" << oendl; |
419 | pthread_attr_destroy(&video_attr); | 425 | pthread_attr_destroy(&video_attr); |
420 | } | 426 | } |
421 | } | 427 | } |
422 | } | 428 | } |
423 | if ( hasAudioChannel ) { | 429 | if ( hasAudioChannel ) { |
424 | if ( pthread_self() != audio_tid ) { | 430 | if ( pthread_self() != audio_tid ) { |
425 | if ( pthread_cancel(audio_tid) == 0 ) { | 431 | if ( pthread_cancel(audio_tid) == 0 ) { |
426 | void *thread_result = 0; | 432 | void *thread_result = 0; |
427 | if ( pthread_join(audio_tid,&thread_result) != 0 ) | 433 | if ( pthread_join(audio_tid,&thread_result) != 0 ) |
428 | // qDebug("thread join error 2"); | 434 | // odebug << "thread join error 2" << oendl; |
429 | pthread_attr_destroy(&audio_attr); | 435 | pthread_attr_destroy(&audio_attr); |
430 | } | 436 | } |
431 | } | 437 | } |
432 | } | 438 | } |
433 | } | 439 | } |
434 | 440 | ||
435 | void LoopControl::startTimers() { | 441 | void LoopControl::startTimers() { |
436 | moreVideo = FALSE; | 442 | moreVideo = FALSE; |
437 | moreAudio = FALSE; | 443 | moreAudio = FALSE; |
438 | 444 | ||
439 | if ( hasVideoChannel ) { | 445 | if ( hasVideoChannel ) { |
440 | moreVideo = TRUE; | 446 | moreVideo = TRUE; |
441 | pthread_attr_init(&video_attr); | 447 | pthread_attr_init(&video_attr); |
442 | pthread_create(&video_tid, &video_attr, (void * (*)(void *))startVideoThread, this); | 448 | pthread_create(&video_tid, &video_attr, (void * (*)(void *))startVideoThread, this); |
443 | } | 449 | } |
444 | 450 | ||
445 | if ( hasAudioChannel ) { | 451 | if ( hasAudioChannel ) { |
446 | moreAudio = TRUE; | 452 | moreAudio = TRUE; |
447 | pthread_attr_init(&audio_attr); | 453 | pthread_attr_init(&audio_attr); |
448 | #ifdef USE_REALTIME_AUDIO_THREAD | 454 | #ifdef USE_REALTIME_AUDIO_THREAD |
449 | pthread_attr_setschedpolicy(&audio_attr,SCHED_RR); // Real-time round robin | 455 | pthread_attr_setschedpolicy(&audio_attr,SCHED_RR); // Real-time round robin |
450 | //qDebug("min: %i, max: %i", sched_get_priority_min( SCHED_RR ), sched_get_priority_max( SCHED_RR ) ); | 456 | //odebug << "min: " << sched_get_priority_min( SCHED_RR ) << ", max: " << sched_get_priority_max( SCHED_RR ) << "" << oendl; |
451 | sched_param params; | 457 | sched_param params; |
452 | params.sched_priority = 50; | 458 | params.sched_priority = 50; |
453 | pthread_attr_setschedparam(&audio_attr,¶ms); | 459 | pthread_attr_setschedparam(&audio_attr,¶ms); |
454 | #endif | 460 | #endif |
455 | pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this); | 461 | pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this); |
456 | } | 462 | } |
457 | } | 463 | } |
458 | 464 | ||
459 | 465 | ||
460 | 466 | ||
461 | 467 | ||
462 | void LoopControl::setPaused( bool pause ) { | 468 | void LoopControl::setPaused( bool pause ) { |
463 | static int whenPaused = 0; | 469 | static int whenPaused = 0; |
464 | 470 | ||
465 | if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() ) | 471 | if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() ) |
466 | return; | 472 | return; |
467 | 473 | ||
468 | if ( pause ) { | 474 | if ( pause ) { |
469 | // Remember where we are | 475 | // Remember where we are |
470 | whenPaused = playtime.elapsed(); | 476 | whenPaused = playtime.elapsed(); |
471 | killTimers(); | 477 | killTimers(); |
472 | } else { | 478 | } else { |
473 | // Just like we never stopped | 479 | // Just like we never stopped |
474 | playtime.restart(); | 480 | playtime.restart(); |
475 | playtime = playtime.addMSecs( -whenPaused ); | 481 | playtime = playtime.addMSecs( -whenPaused ); |
476 | whenPaused = 0; | 482 | whenPaused = 0; |
477 | startTimers(); | 483 | startTimers(); |
478 | } | 484 | } |
479 | } | 485 | } |
480 | 486 | ||
481 | 487 | ||
482 | void LoopControl::stop( bool willPlayAgainShortly ) { | 488 | void LoopControl::stop( bool willPlayAgainShortly ) { |
483 | 489 | ||
484 | #if defined(Q_WS_QWS) && !defined(QT_NO_COP) | 490 | #if defined(Q_WS_QWS) && !defined(QT_NO_COP) |
485 | if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) { | 491 | if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) { |
486 | disabledSuspendScreenSaver = FALSE; | 492 | disabledSuspendScreenSaver = FALSE; |
487 | // Re-enable the suspend mode | 493 | // Re-enable the suspend mode |
488 | QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; | 494 | QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; |
489 | } | 495 | } |
490 | #endif | 496 | #endif |
491 | 497 | ||
492 | if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) { | 498 | if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) { |
493 | 499 | ||
494 | killTimers(); | 500 | killTimers(); |
495 | 501 | ||
496 | mediaPlayerState->curDecoder()->close(); | 502 | mediaPlayerState->curDecoder()->close(); |
497 | 503 | ||
498 | if ( audioDevice ) { | 504 | if ( audioDevice ) { |
499 | delete audioDevice; | 505 | delete audioDevice; |
500 | delete audioBuffer; | 506 | delete audioBuffer; |
501 | audioDevice = 0; | 507 | audioDevice = 0; |
502 | audioBuffer = 0; | 508 | audioBuffer = 0; |
503 | } | 509 | } |
504 | 510 | ||
505 | } | 511 | } |
506 | } | 512 | } |
507 | 513 | ||
508 | 514 | ||
509 | bool LoopControl::init( const QString& filename ) { | 515 | bool LoopControl::init( const QString& filename ) { |
510 | stop(); | 516 | stop(); |
511 | fileName = filename; | 517 | fileName = filename; |
512 | stream = 0; // only play stream 0 for now | 518 | stream = 0; // only play stream 0 for now |
513 | current_frame = total_video_frames = total_audio_samples = 0; | 519 | current_frame = total_video_frames = total_audio_samples = 0; |
514 | 520 | ||
515 | // qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() ); | 521 | // odebug << "Using the " << mediaPlayerState->curDecoder()->pluginName() << " decoder" << oendl; |
516 | 522 | ||
517 | // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin | 523 | // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin |
518 | if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) { | 524 | if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) { |
519 | if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) { | 525 | if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) { |
520 | total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 ); | 526 | total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 ); |
521 | mediaPlayerState->libMpeg3Decoder()->close(); | 527 | mediaPlayerState->libMpeg3Decoder()->close(); |
522 | } | 528 | } |
523 | } | 529 | } |
524 | 530 | ||
525 | if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) | 531 | if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) |
526 | return FALSE; | 532 | return FALSE; |
527 | 533 | ||
528 | hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0; | 534 | hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0; |
529 | hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0; | 535 | hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0; |
530 | 536 | ||
531 | if ( hasAudioChannel ) { | 537 | if ( hasAudioChannel ) { |
532 | int astream = 0; | 538 | int astream = 0; |
533 | 539 | ||
534 | channels = mediaPlayerState->curDecoder()->audioChannels( astream ); | 540 | channels = mediaPlayerState->curDecoder()->audioChannels( astream ); |
535 | DecodeLoopDebug(( "channels = %d\n", channels )); | 541 | DecodeLoopDebug(( "channels = %d\n", channels )); |
536 | 542 | ||
537 | if ( !total_audio_samples ) | 543 | if ( !total_audio_samples ) |
538 | total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream ); | 544 | total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream ); |
539 | 545 | ||
540 | mediaPlayerState->setLength( total_audio_samples ); | 546 | mediaPlayerState->setLength( total_audio_samples ); |
541 | 547 | ||
542 | freq = mediaPlayerState->curDecoder()->audioFrequency( astream ); | 548 | freq = mediaPlayerState->curDecoder()->audioFrequency( astream ); |
543 | DecodeLoopDebug(( "frequency = %d\n", freq )); | 549 | DecodeLoopDebug(( "frequency = %d\n", freq )); |
544 | 550 | ||
545 | audioSampleCounter = 0; | 551 | audioSampleCounter = 0; |
546 | 552 | ||
547 | static const int bytes_per_sample = 2; //16 bit | 553 | static const int bytes_per_sample = 2; //16 bit |
548 | 554 | ||
549 | audioDevice = new AudioDevice( freq, channels, bytes_per_sample ); | 555 | audioDevice = new AudioDevice( freq, channels, bytes_per_sample ); |
550 | audioBuffer = new char[ audioDevice->bufferSize() ]; | 556 | audioBuffer = new char[ audioDevice->bufferSize() ]; |
551 | channels = audioDevice->channels(); | 557 | channels = audioDevice->channels(); |
552 | 558 | ||
553 | //### must check which frequency is actually used. | 559 | //### must check which frequency is actually used. |
554 | static const int size = 1; | 560 | static const int size = 1; |
555 | short int buf[size]; | 561 | short int buf[size]; |
556 | long samplesRead = 0; | 562 | long samplesRead = 0; |
557 | mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream ); | 563 | mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream ); |
558 | } | 564 | } |
559 | 565 | ||
560 | if ( hasVideoChannel ) { | 566 | if ( hasVideoChannel ) { |
561 | total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream ); | 567 | total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream ); |
562 | 568 | ||
563 | mediaPlayerState->setLength( total_video_frames ); | 569 | mediaPlayerState->setLength( total_video_frames ); |