📄 loopcontrol.cpp
字号:
/************************************************************************ Copyright (C) 2000-2002 Trolltech AS. All rights reserved.**** This file is part of the 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.************************************************************************/#include <qtopia/qpeapplication.h>#ifdef Q_WS_QWS#include <qtopia/qcopenvelope_qws.h>#endif#include <qtopia/mediaplayerplugininterface.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <errno.h>#include <unistd.h>#include "loopcontrol.h"#include "videowidget.h"#include "audiodevice.h"#include "mediaplayerstate.h"//#define DecodeLoopDebug(x) qDebug x#define DecodeLoopDebug(x)static char *audioBuffer = NULL;static AudioDevice *audioDevice = NULL;static bool disabledSuspendScreenSaver = FALSE;static bool previousSuspendMode = FALSE;pthread_t audio_tid;pthread_attr_t audio_attr;pthread_cond_t audioCond;bool threadOkToGo = 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 ); } void waitForCondition( pthread_cond_t *cond ) { lock(); pthread_cond_wait ( cond, &mutex ); unlock(); }private: pthread_mutex_t mutex;};Mutex *audioMutex;void *startAudioThread( void *ptr ){ LoopControl *mpegView = (LoopControl *)ptr; while ( TRUE ) { audioMutex->waitForCondition( &audioCond ); while ( threadOkToGo && mpegView->moreAudio ) { audioMutex->lock(); mpegView->startAudio(); audioMutex->unlock(); } } return 0;}void LoopControl::setPriority( AudioPriority priority ){ if ( getuid() == 0 ) { qDebug("running as root, can change realtime priority"); sched_param params; switch ( priority ) { case Normal: params.sched_priority = 0; // Attempt to set it back to normal priority if ( pthread_setschedparam(audio_tid,SCHED_OTHER,¶ms) != 0 ) { qDebug( "Failed to set thread priority normal" ); } break; case High: params.sched_priority = 50; // Attempt to set it to real-time round robin if ( pthread_setschedparam(audio_tid,SCHED_RR,¶ms) != 0 ) { qDebug( "Failed to set thread priority to realtime round robin" ); } break; default: break; } }}LoopControl::LoopControl( QObject *parent, const char *name ) : QObject( parent, name ), videoId(0), sliderId(0){ isMuted = FALSE; connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) ); connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) ); connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) ); audioMutex = new Mutex; pthread_condattr_t cattr; pthread_condattr_init(&cattr); pthread_cond_init(&audioCond, &cattr); pthread_condattr_destroy(&cattr); pthread_attr_init(&audio_attr);// pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this);// setPriority( High ); if ( getuid() == 0 ) { qDebug("running as root, can set realtime priority"); // Attempt to set it to real-time round robin if ( pthread_attr_setschedpolicy( &audio_attr, SCHED_RR ) == 0 ) { sched_param params; params.sched_priority = 50; pthread_attr_setschedparam(&audio_attr,¶ms); } else { qDebug( "Error setting up a realtime thread, reverting to using a normal thread." ); pthread_attr_destroy(&audio_attr); pthread_attr_init(&audio_attr); } } pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this);}LoopControl::~LoopControl(){ stop();}static long prev_frame = 0;static int currentSample = 0;unsigned int startTime;void LoopControl::timerEvent( QTimerEvent *te ){ if ( te->timerId() == videoId ) startVideo(); if ( te->timerId() == sliderId ) { if ( mediaPlayerState->decoderVersion() == Decoder_1_6 ) { MediaPlayerDecoder_1_6 *decoder = (MediaPlayerDecoder_1_6 *)mediaPlayerState->decoder(); mediaPlayerState->updatePosition( decoder->tell() ); } else { if ( hasAudioChannel && !hasVideoChannel && moreAudio ) { mediaPlayerState->updatePosition( audioSampleCounter ); } else if ( hasVideoChannel && moreVideo ) { mediaPlayerState->updatePosition( current_frame ); } } } if ( !moreVideo && !moreAudio ) { mediaPlayerState->setPlaying( FALSE ); mediaPlayerState->setNext(); }}long LoopControl::totalPlaytime(){ if ( mediaPlayerState->decoderVersion() == Decoder_1_6 ) { MediaPlayerDecoder_1_6 *decoder = (MediaPlayerDecoder_1_6 *)mediaPlayerState->decoder(); if ( decoder->totalTimeAvailable() ) return decoder->totalTime(); else return -1; } if ( hasVideoChannel ) { if ( framerate != 0.0 ) return (long)(total_video_frames / framerate); } else { if ( freq ) return total_audio_samples / freq; } return -1;}void LoopControl::setPosition( long pos ){ audioMutex->lock(); if ( mediaPlayerState->decoderVersion() == Decoder_1_6 ) { MediaPlayerDecoder_1_6 *decoder = (MediaPlayerDecoder_1_6 *)mediaPlayerState->decoder(); if ( decoder->seekAvailable() ) decoder->seek( pos ); audioMutex->unlock(); return; } if ( mediaPlayerState->seekable() ) { if ( hasVideoChannel && hasAudioChannel ) { playtime.restart(); playtime = playtime.addMSecs( long((long long)-pos * 1000 / framerate) ); current_frame = pos + 1; mediaPlayerState->decoder()->videoSetFrame( current_frame, vstream ); prev_frame = current_frame - 1; currentSample = (int)( (long long)current_frame * freq / framerate ); mediaPlayerState->decoder()->audioSetSample( currentSample, astream ); audioSampleCounter = currentSample - 1; } else if ( hasVideoChannel ) { playtime.restart(); playtime = playtime.addMSecs( long((long long)-pos * 1000 / framerate) ); current_frame = pos + 1; mediaPlayerState->decoder()->videoSetFrame( current_frame, vstream ); prev_frame = current_frame - 1; } else if ( hasAudioChannel ) { playtime.restart(); playtime = playtime.addMSecs( long((long long)-pos * 1000 / freq) ); currentSample = pos + 1; mediaPlayerState->decoder()->audioSetSample( currentSample, astream ); audioSampleCounter = currentSample - 1; } } audioMutex->unlock();}void LoopControl::startVideo(){ if ( moreVideo ) { if ( mediaPlayerState->decoder() ) { current_frame = long( playtime.elapsed() * framerate / 1000 ); if ( mediaPlayerState->decoderVersion() == Decoder_1_6 ) { MediaPlayerDecoder_1_6 *decoder = (MediaPlayerDecoder_1_6 *)mediaPlayerState->decoder(); if ( current_frame != prev_frame ) { // Enough time has elapsed that it is time to display another frame moreVideo = mediaPlayerState->videoUI()->playVideo(); prev_frame = current_frame; // Resync the video with the audio if ( decoder->syncAvailable() ) decoder->sync(); } } else { if ( hasAudioChannel ) { if ( prev_frame != -1 && current_frame <= prev_frame ) return; } else { // Don't skip current_frame++; } if ( prev_frame == -1 || current_frame > prev_frame ) { if ( current_frame > prev_frame + 1 ) { mediaPlayerState->decoder()->videoSetFrame( current_frame, vstream ); } moreVideo = mediaPlayerState->videoUI()->playVideo();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -