author | schurig <schurig> | 2003-06-04 10:30:28 (UTC) |
---|---|---|
committer | schurig <schurig> | 2003-06-04 10:30:28 (UTC) |
commit | df76591a8ee920c6549bc55b026ab66926917667 (patch) (side-by-side diff) | |
tree | 3d11b883a8f4a54fd11569cc9856a32f32de8e9d | |
parent | 77eff544a1a3421679f978d322e2cdcfab958c8f (diff) | |
download | opie-df76591a8ee920c6549bc55b026ab66926917667.zip opie-df76591a8ee920c6549bc55b026ab66926917667.tar.gz opie-df76591a8ee920c6549bc55b026ab66926917667.tar.bz2 |
ramses want's realtime, too
-rw-r--r-- | core/multimedia/opieplayer/loopcontrol_threaded.cpp | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/core/multimedia/opieplayer/loopcontrol_threaded.cpp b/core/multimedia/opieplayer/loopcontrol_threaded.cpp index 6817d5b..e99c97b 100644 --- a/core/multimedia/opieplayer/loopcontrol_threaded.cpp +++ b/core/multimedia/opieplayer/loopcontrol_threaded.cpp @@ -1,426 +1,426 @@ /********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #define _REENTRANT #include <qpe/qpeapplication.h> #include <qimage.h> #include <qpainter.h> #ifdef Q_WS_QWS #include <qpe/qcopenvelope_qws.h> #endif #include "mediaplayerplugininterface.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include <pthread.h> #include "loopcontrol.h" #include "audiodevice.h" #include "videowidget.h" #include "audiowidget.h" #include "mediaplayerstate.h" -#if defined(QT_QWS_SL5XXX) || defined(QT_QWS_IPAQ) +#if defined(QT_QWS_SL5XXX) || defined(QT_QWS_IPAQ) || defined(QT_QWS_RAMSES) #define USE_REALTIME_AUDIO_THREAD #endif extern VideoWidget *videoUI; // now only needed to tell it to play a frame extern MediaPlayerState *mediaPlayerState; #define DecodeLoopDebug(x) qDebug x //#define DecodeLoopDebug(x) static char *audioBuffer = NULL; static AudioDevice *audioDevice = NULL; static bool disabledSuspendScreenSaver = FALSE; pthread_t video_tid; pthread_attr_t video_attr; pthread_t audio_tid; pthread_attr_t audio_attr; bool emitPlayFinished = FALSE; bool emitChangePos = FALSE; class Mutex { public: Mutex() { pthread_mutexattr_t attr; pthread_mutexattr_init( &attr ); pthread_mutex_init( &mutex, &attr ); pthread_mutexattr_destroy( &attr ); } ~Mutex() { pthread_mutex_destroy( &mutex ); } void lock() { pthread_mutex_lock( &mutex ); } void unlock() { pthread_mutex_unlock( &mutex ); } /* bool locked() { switch ( pthread_mutex_trylock( &mutex ) ) { case EBUSY: return TRUE; case 0: pthread_mutex_unlock( &mutex ); default: return FALSE; } } */ private: pthread_mutex_t mutex; }; class currentFrameObj { public: currentFrameObj() : value( 0 ) { } void set( long f ) { mutex.lock(); value = f; mediaPlayerState->curDecoder()->videoSetFrame( f, 0 ); mutex.unlock(); } long get() { return value; } private: long value; Mutex mutex; }; Mutex *videoMutex; Mutex *audioMutex; Mutex *globalMutex; clock_t begin; LoopControl::LoopControl( QObject *parent, const char *name ) : QObject( parent, name ) { isMuted = FALSE; connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) ); timerid = startTimer( 200 ); videoMutex = new Mutex; audioMutex = new Mutex; globalMutex = new Mutex; //begin = clock(); } LoopControl::~LoopControl() { stop(); killTimer( timerid ); } static bool sendingNewPos = FALSE; static long prev_frame = 0; static int currentSample = 0; void LoopControl::timerEvent( QTimerEvent* ) { // We need to emit playFinished from the main thread, not one of the // decoding threads else we'll have all kinds of yucky things happen (reentrance). // playFinished will eventually call stop() which stops these threads. if ( emitPlayFinished ) { emitPlayFinished = FALSE; mediaPlayerState->setPlaying( FALSE ); } if ( emitChangePos ) { emitChangePos = FALSE; if ( hasVideoChannel && hasAudioChannel ) { sendingNewPos = TRUE; mediaPlayerState->setPosition( current_frame ); } else if ( hasVideoChannel ) { sendingNewPos = TRUE; mediaPlayerState->setPosition( current_frame ); } else if ( hasAudioChannel ) { sendingNewPos = TRUE; mediaPlayerState->setPosition( audioSampleCounter ); } } } void LoopControl::setPosition( long pos ) { if ( sendingNewPos ) { sendingNewPos = FALSE; return; } if ( hasVideoChannel && hasAudioChannel ) { videoMutex->lock(); audioMutex->lock(); qDebug("setting position"); playtime.restart(); playtime = playtime.addMSecs( -pos * 1000 / framerate ); //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; current_frame = pos + 1; mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); prev_frame = current_frame - 1; currentSample = (int)( current_frame * freq / framerate ); mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); audioSampleCounter = currentSample - 1; audioMutex->unlock(); videoMutex->unlock(); } else if ( hasVideoChannel ) { videoMutex->lock(); playtime.restart(); playtime = playtime.addMSecs( -pos * 1000 / framerate ); //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; current_frame = pos + 1; mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); videoMutex->unlock(); prev_frame = current_frame - 1; } else if ( hasAudioChannel ) { audioMutex->lock(); playtime.restart(); playtime = playtime.addMSecs( -pos * 1000 / freq ); //begin = clock() - (double)pos * CLOCKS_PER_SEC / freq; currentSample = pos + 1; // (int)( current_frame * freq / framerate ); mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); audioSampleCounter = currentSample - 1; audioMutex->unlock(); } } void *startVideoThread( void *ptr ) { LoopControl *mpegView = (LoopControl *)ptr; mpegView->startVideo(); return 0; } void *startAudioThread( void *ptr ) { LoopControl *mpegView = (LoopControl *)ptr; mpegView->startAudio(); return 0; } void LoopControl::startVideo() { moreVideo = TRUE; while ( moreVideo ) { if ( mediaPlayerState->curDecoder() && hasVideoChannel ) { if ( hasAudioChannel && !isMuted ) { bool done = FALSE; do { /* videoMutex->lock(); current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; // Sync to Audio // current_frame = (long)((double)(audioSampleCounter - 1000) * framerate / (double)freq); long mSecsToNextFrame = 0; if ( current_frame == prev_frame ) { int nf = current_frame + 1; if ( nf > 0 && nf != total_video_frames ) // mSecsToNextFrame = long(double(nf * CLOCKS_PER_SEC) / framerate) - ( clock() - begin ); mSecsToNextFrame = long(double(nf * 1000) / framerate) - ( playtime.elapsed() ); } videoMutex->unlock(); if ( mSecsToNextFrame ) { usleep( mSecsToNextFrame ); // wait a bit videoMutex->lock(); // This should now be the next frame current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; videoMutex->unlock(); } videoMutex->lock(); done = current_frame >= prev_frame; videoMutex->unlock(); */ videoMutex->lock(); current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); done = current_frame >= prev_frame; videoMutex->unlock(); if ( !done ) usleep( 1000 ); // wait a bit } while ( !done ); // qDebug("elapsed: %i %i (%f)", int( playtime.elapsed() ), current_frame, framerate ); } else { videoMutex->lock(); current_frame++; videoMutex->unlock(); } videoMutex->lock(); bool check = current_frame && current_frame > prev_frame; videoMutex->unlock(); if ( check ) { videoMutex->lock(); if ( current_frame > prev_frame + 1 ) { qDebug("skipped a frame"); mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); } prev_frame = current_frame; if ( moreVideo = videoUI->playVideo() ) emitChangePos = TRUE; videoMutex->unlock(); } } else moreVideo = FALSE; } if ( !moreVideo && !moreAudio ) emitPlayFinished = TRUE; pthread_exit(NULL); } void LoopControl::startAudio() { moreAudio = TRUE; while ( moreAudio ) { if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) { audioMutex->lock(); currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream ); if ( currentSample == 0 ) currentSample = audioSampleCounter + 1; if ( currentSample != audioSampleCounter + 1 ) qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter); audioMutex->unlock(); /* int sampleWeShouldBeAt = int( playtime.elapsed() ) * freq / 1000; if ( sampleWeShouldBeAt - currentSample > 20000 ) { mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); currentSample = sampleWeShouldBeAt; } */ long samplesRead = 0; const long samples = 1024; moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream ); audioMutex->lock(); long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; //long sampleWeShouldBeAt = long( clock() - begin ) * (double) freq / CLOCKS_PER_SEC; long sampleWaitTime = currentSample - sampleWeShouldBeAt; audioMutex->unlock(); if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) { //qDebug("sampleWaitTime: %i", sampleWaitTime); usleep( ( sampleWaitTime * 1000000 ) / ( freq ) ); } else { audioMutex->lock(); if ( sampleWaitTime <= -2000 ) { qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt ); mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); currentSample = sampleWeShouldBeAt; } audioMutex->unlock(); } audioDevice->write( audioBuffer, samplesRead * 2 * channels ); audioMutex->lock(); // audioSampleCounter += samplesRead; audioSampleCounter = currentSample + samplesRead - 1; audioMutex->unlock(); if ( !hasVideoChannel ) emitChangePos = TRUE; //qDebug("currentSample: %i audioSampleCounter: %i total_audio_samples: %i", currentSample, audioSampleCounter, total_audio_samples); // qDebug("current: %i counter: %i total: %i", currentSample, audioSampleCounter, (int)total_audio_samples); moreAudio = audioSampleCounter <= total_audio_samples; } else { if ( mediaPlayerState->curDecoder() && hasAudioChannel ) usleep( 100000 ); // Check every 1/10 sec to see if mute is off else moreAudio = FALSE; } } qDebug( "End of file" ); if ( !moreVideo && !moreAudio ) emitPlayFinished = TRUE; pthread_exit(NULL); } void LoopControl::killTimers() { if ( hasVideoChannel ) { if ( pthread_self() != video_tid ) { if ( pthread_cancel(video_tid) == 0 ) { void *thread_result = 0; if ( pthread_join(video_tid,&thread_result) != 0 ) qDebug("thread join error 1"); pthread_attr_destroy(&video_attr); } } } if ( hasAudioChannel ) { if ( pthread_self() != audio_tid ) { if ( pthread_cancel(audio_tid) == 0 ) { |