00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define _REENTRANT
00021
00022 #include "mediaplayerplugininterface.h"
00023 #include "loopcontrol.h"
00024 #include "audiodevice.h"
00025 #include "videowidget.h"
00026 #include "audiowidget.h"
00027 #include "mediaplayerstate.h"
00028
00029
00030 #include <qpe/qpeapplication.h>
00031 #include <qpe/custom.h>
00032
00033 #if !defined(QT_NO_COP)
00034 #include <qpe/qcopenvelope_qws.h>
00035 #endif
00036
00037 #include <opie2/odebug.h>
00038
00039
00040 #include <qimage.h>
00041 #include <qpainter.h>
00042
00043
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <time.h>
00048 #include <unistd.h>
00049 #include <pthread.h>
00050
00051
00052 extern VideoWidget *videoUI;
00053 extern MediaPlayerState *mediaPlayerState;
00054
00055
00056 #define DecodeLoopDebug(x) qDebug x
00057
00058
00059
00060 static char *audioBuffer = NULL;
00061 static AudioDevice *audioDevice = NULL;
00062 static bool disabledSuspendScreenSaver = FALSE;
00063
00064
00065 pthread_t video_tid;
00066 pthread_attr_t video_attr;
00067 pthread_t audio_tid;
00068 pthread_attr_t audio_attr;
00069
00070
00071 bool emitPlayFinished = FALSE;
00072 bool emitChangePos = FALSE;
00073
00074
00075 class Mutex {
00076 public:
00077 Mutex() {
00078 pthread_mutexattr_t attr;
00079 pthread_mutexattr_init( &attr );
00080 pthread_mutex_init( &mutex, &attr );
00081 pthread_mutexattr_destroy( &attr );
00082 }
00083
00084 ~Mutex() {
00085 pthread_mutex_destroy( &mutex );
00086 }
00087
00088 void lock() {
00089 pthread_mutex_lock( &mutex );
00090 }
00091
00092 void unlock() {
00093 pthread_mutex_unlock( &mutex );
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 private:
00108 pthread_mutex_t mutex;
00109 };
00110
00111
00112 class currentFrameObj {
00113 public:
00114 currentFrameObj() : value( 0 ) { }
00115 void set( long f ) {
00116 mutex.lock();
00117 value = f;
00118 mediaPlayerState->curDecoder()->videoSetFrame( f, 0 );
00119 mutex.unlock();
00120 }
00121 long get() {
00122 return value;
00123 }
00124 private:
00125 long value;
00126 Mutex mutex;
00127 };
00128
00129
00130 Mutex *videoMutex;
00131 Mutex *audioMutex;
00132 Mutex *globalMutex;
00133
00134
00135 clock_t begin;
00136
00137
00138 LoopControl::LoopControl( QObject *parent, const char *name )
00139 : QObject( parent, name ) {
00140 isMuted = FALSE;
00141 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) );
00142 timerid = startTimer( 200 );
00143 videoMutex = new Mutex;
00144 audioMutex = new Mutex;
00145 globalMutex = new Mutex;
00146
00147 }
00148
00149
00150 LoopControl::~LoopControl() {
00151 stop();
00152 killTimer( timerid );
00153 }
00154
00155
00156 static bool sendingNewPos = FALSE;
00157 static long prev_frame = 0;
00158 static int currentSample = 0;
00159
00160
00161 void LoopControl::timerEvent( QTimerEvent* ) {
00162
00163
00164
00165 if ( emitPlayFinished ) {
00166 emitPlayFinished = FALSE;
00167 mediaPlayerState->setPlaying( FALSE );
00168 }
00169
00170 if ( emitChangePos ) {
00171
00172 emitChangePos = FALSE;
00173
00174 if ( hasVideoChannel && hasAudioChannel ) {
00175 sendingNewPos = TRUE;
00176 mediaPlayerState->setPosition( current_frame );
00177 } else if ( hasVideoChannel ) {
00178 sendingNewPos = TRUE;
00179 mediaPlayerState->setPosition( current_frame );
00180 } else if ( hasAudioChannel ) {
00181 sendingNewPos = TRUE;
00182 mediaPlayerState->setPosition( audioSampleCounter );
00183 }
00184
00185 }
00186 }
00187
00188
00189
00190
00191 void LoopControl::setPosition( long pos ) {
00192 if ( sendingNewPos ) {
00193 sendingNewPos = FALSE;
00194 return;
00195 }
00196
00197 if ( hasVideoChannel && hasAudioChannel ) {
00198 videoMutex->lock();
00199 audioMutex->lock();
00200
00201 playtime.restart();
00202 playtime = playtime.addMSecs( -pos * 1000 / framerate );
00203
00204 current_frame = pos + 1;
00205 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
00206 prev_frame = current_frame - 1;
00207 currentSample = (int)( current_frame * freq / framerate );
00208 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream );
00209 audioSampleCounter = currentSample - 1;
00210 audioMutex->unlock();
00211 videoMutex->unlock();
00212 } else if ( hasVideoChannel ) {
00213 videoMutex->lock();
00214 playtime.restart();
00215 playtime = playtime.addMSecs( -pos * 1000 / framerate );
00216
00217 current_frame = pos + 1;
00218 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
00219 videoMutex->unlock();
00220 prev_frame = current_frame - 1;
00221 } else if ( hasAudioChannel ) {
00222 audioMutex->lock();
00223 playtime.restart();
00224 playtime = playtime.addMSecs( -pos * 1000 / freq );
00225
00226 currentSample = pos + 1;
00227 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream );
00228 audioSampleCounter = currentSample - 1;
00229 audioMutex->unlock();
00230 }
00231 }
00232
00233
00234 void *startVideoThread( void *ptr ) {
00235 LoopControl *mpegView = (LoopControl *)ptr;
00236 mpegView->startVideo();
00237 return 0;
00238 }
00239
00240 void *startAudioThread( void *ptr ) {
00241 LoopControl *mpegView = (LoopControl *)ptr;
00242 mpegView->startAudio();
00243 return 0;
00244 }
00245
00246 void LoopControl::startVideo() {
00247 moreVideo = TRUE;
00248
00249 while ( moreVideo ) {
00250
00251 if ( mediaPlayerState->curDecoder() && hasVideoChannel ) {
00252
00253 if ( hasAudioChannel && !isMuted ) {
00254
00255 bool done = FALSE;
00256
00257 do {
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 videoMutex->lock();
00293 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 );
00294 done = current_frame >= prev_frame;
00295 videoMutex->unlock();
00296 if ( !done )
00297 usleep( 1000 );
00298
00299 } while ( !done );
00300
00301
00302
00303 } else {
00304 videoMutex->lock();
00305 current_frame++;
00306 videoMutex->unlock();
00307 }
00308
00309 videoMutex->lock();
00310 bool check = current_frame && current_frame > prev_frame;
00311 videoMutex->unlock();
00312
00313 if ( check ) {
00314 videoMutex->lock();
00315 if ( current_frame > prev_frame + 1 ) {
00316
00317 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
00318 }
00319 prev_frame = current_frame;
00320 if ( moreVideo = videoUI->playVideo() )
00321 emitChangePos = TRUE;
00322 videoMutex->unlock();
00323 }
00324
00325 } else
00326 moreVideo = FALSE;
00327
00328 }
00329
00330 if ( !moreVideo && !moreAudio )
00331 emitPlayFinished = TRUE;
00332
00333 pthread_exit(NULL);
00334 }
00335
00336 void LoopControl::startAudio() {
00337 moreAudio = TRUE;
00338
00339 while ( moreAudio ) {
00340
00341 if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) {
00342
00343 audioMutex->lock();
00344 currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream );
00345
00346 if ( currentSample == 0 )
00347 currentSample = audioSampleCounter + 1;
00348
00349
00350
00351 audioMutex->unlock();
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 long samplesRead = 0;
00362
00363 const long samples = 1024;
00364
00365 moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream );
00366
00367 audioMutex->lock();
00368 long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000;
00369
00370 long sampleWaitTime = currentSample - sampleWeShouldBeAt;
00371 audioMutex->unlock();
00372
00373 if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) {
00374
00375 usleep( ( sampleWaitTime * 1000000 ) / ( freq ) );
00376 } else {
00377 audioMutex->lock();
00378 if ( sampleWaitTime <= -2000 ) {
00379
00380 mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream );
00381 currentSample = sampleWeShouldBeAt;
00382 }
00383 audioMutex->unlock();
00384 }
00385
00386 audioDevice->write( audioBuffer, samplesRead * 2 * channels );
00387
00388 audioMutex->lock();
00389
00390 audioSampleCounter = currentSample + samplesRead - 1;
00391 audioMutex->unlock();
00392
00393 if ( !hasVideoChannel )
00394 emitChangePos = TRUE;
00395
00396
00397
00398 moreAudio = audioSampleCounter <= total_audio_samples;
00399
00400 } else {
00401
00402 if ( mediaPlayerState->curDecoder() && hasAudioChannel )
00403 usleep( 100000 );
00404 else
00405 moreAudio = FALSE;
00406
00407 }
00408 }
00409
00410
00411
00412 if ( !moreVideo && !moreAudio )
00413 emitPlayFinished = TRUE;
00414
00415 pthread_exit(NULL);
00416 }
00417
00418 void LoopControl::killTimers() {
00419 if ( hasVideoChannel ) {
00420 if ( pthread_self() != video_tid ) {
00421 if ( pthread_cancel(video_tid) == 0 ) {
00422 void *thread_result = 0;
00423 if ( pthread_join(video_tid,&thread_result) != 0 )
00424
00425 pthread_attr_destroy(&video_attr);
00426 }
00427 }
00428 }
00429 if ( hasAudioChannel ) {
00430 if ( pthread_self() != audio_tid ) {
00431 if ( pthread_cancel(audio_tid) == 0 ) {
00432 void *thread_result = 0;
00433 if ( pthread_join(audio_tid,&thread_result) != 0 )
00434
00435 pthread_attr_destroy(&audio_attr);
00436 }
00437 }
00438 }
00439 }
00440
00441 void LoopControl::startTimers() {
00442 moreVideo = FALSE;
00443 moreAudio = FALSE;
00444
00445 if ( hasVideoChannel ) {
00446 moreVideo = TRUE;
00447 pthread_attr_init(&video_attr);
00448 pthread_create(&video_tid, &video_attr, (void * (*)(void *))startVideoThread, this);
00449 }
00450
00451 if ( hasAudioChannel ) {
00452 moreAudio = TRUE;
00453 pthread_attr_init(&audio_attr);
00454 #ifdef USE_REALTIME_AUDIO_THREAD
00455 pthread_attr_setschedpolicy(&audio_attr,SCHED_RR);
00456
00457 sched_param params;
00458 params.sched_priority = 50;
00459 pthread_attr_setschedparam(&audio_attr,¶ms);
00460 #endif
00461 pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this);
00462 }
00463 }
00464
00465
00466
00467
00468 void LoopControl::setPaused( bool pause ) {
00469 static int whenPaused = 0;
00470
00471 if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() )
00472 return;
00473
00474 if ( pause ) {
00475
00476 whenPaused = playtime.elapsed();
00477 killTimers();
00478 } else {
00479
00480 playtime.restart();
00481 playtime = playtime.addMSecs( -whenPaused );
00482 whenPaused = 0;
00483 startTimers();
00484 }
00485 }
00486
00487
00488 void LoopControl::stop( bool willPlayAgainShortly ) {
00489
00490 #if defined(Q_WS_QWS) && !defined(QT_NO_COP)
00491 if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) {
00492 disabledSuspendScreenSaver = FALSE;
00493
00494 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
00495 }
00496 #endif
00497
00498 if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) {
00499
00500 killTimers();
00501
00502 mediaPlayerState->curDecoder()->close();
00503
00504 if ( audioDevice ) {
00505 delete audioDevice;
00506 delete audioBuffer;
00507 audioDevice = 0;
00508 audioBuffer = 0;
00509 }
00510
00511 }
00512 }
00513
00514
00515 bool LoopControl::init( const QString& filename ) {
00516 stop();
00517 fileName = filename;
00518 stream = 0;
00519 current_frame = total_video_frames = total_audio_samples = 0;
00520
00521
00522
00523
00524 if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) {
00525 if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) {
00526 total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 );
00527 mediaPlayerState->libMpeg3Decoder()->close();
00528 }
00529 }
00530
00531 if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) )
00532 return FALSE;
00533
00534 hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0;
00535 hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0;
00536
00537 if ( hasAudioChannel ) {
00538 int astream = 0;
00539
00540 channels = mediaPlayerState->curDecoder()->audioChannels( astream );
00541 DecodeLoopDebug(( "channels = %d\n", channels ));
00542
00543 if ( !total_audio_samples )
00544 total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream );
00545
00546 mediaPlayerState->setLength( total_audio_samples );
00547
00548 freq = mediaPlayerState->curDecoder()->audioFrequency( astream );
00549 DecodeLoopDebug(( "frequency = %d\n", freq ));
00550
00551 audioSampleCounter = 0;
00552
00553 static const int bytes_per_sample = 2;
00554
00555 audioDevice = new AudioDevice( freq, channels, bytes_per_sample );
00556 audioBuffer = new char[ audioDevice->bufferSize() ];
00557 channels = audioDevice->channels();
00558
00559
00560 static const int size = 1;
00561 short int buf[size];
00562 long samplesRead = 0;
00563 mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream );
00564 }
00565
00566 if ( hasVideoChannel ) {
00567 total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream );
00568
00569 mediaPlayerState->setLength( total_video_frames );
00570
00571 framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream );
00572 DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames ));
00573
00574 if ( framerate <= 1.0 ) {
00575 DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" ));
00576 framerate = 25;
00577 }
00578
00579 if ( total_video_frames == 1 ) {
00580 DecodeLoopDebug(( "Cannot seek to frame" ));
00581 }
00582
00583 }
00584
00585 videoMutex->lock();
00586 current_frame = 0;
00587 prev_frame = -1;
00588 videoMutex->unlock();
00589
00590 connect( mediaPlayerState, SIGNAL( positionChanged(long) ), this, SLOT( setPosition(long) ) );
00591 connect( mediaPlayerState, SIGNAL( pausedToggled(bool) ), this, SLOT( setPaused(bool) ) );
00592
00593
00594 return TRUE;
00595 }
00596
00597
00598 void LoopControl::play() {
00599
00600 #if defined(Q_WS_QWS) && !defined(QT_NO_COP)
00601 if ( !disabledSuspendScreenSaver ) {
00602 disabledSuspendScreenSaver = TRUE;
00603
00604 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" )
00605 << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend );
00606 }
00607 #endif
00608
00609
00610 playtime.start();
00611 startTimers();
00612
00613 }
00614
00615
00616 void LoopControl::setMute( bool on ) {
00617 if ( isMuted != on ) {
00618 isMuted = on;
00619 if ( isMuted ) {
00620 } else {
00621 int frame = current_frame;
00622 playtime.restart();
00623 playtime = playtime.addMSecs( -frame * 1000 / framerate );
00624
00625 mediaPlayerState->curDecoder()->audioSetSample( frame*freq/framerate, stream );
00626 }
00627 }
00628 }
00629
00630