summaryrefslogtreecommitdiff
authorschurig <schurig>2003-06-04 10:30:28 (UTC)
committer schurig <schurig>2003-06-04 10:30:28 (UTC)
commitdf76591a8ee920c6549bc55b026ab66926917667 (patch) (side-by-side diff)
tree3d11b883a8f4a54fd11569cc9856a32f32de8e9d
parent77eff544a1a3421679f978d322e2cdcfab958c8f (diff)
downloadopie-df76591a8ee920c6549bc55b026ab66926917667.zip
opie-df76591a8ee920c6549bc55b026ab66926917667.tar.gz
opie-df76591a8ee920c6549bc55b026ab66926917667.tar.bz2
ramses want's realtime, too
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/loopcontrol_threaded.cpp2
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 ) {