예제 #1
0
bool Player::PreBuffer(){
    // But not if buffer is full
    if(this->totalBufferSize>this->maxBufferSize){
        return false;
    }else{
        BufferPtr newBuffer = this->stream->NextBuffer();
        if(newBuffer){
            boost::mutex::scoped_lock lock(this->mutex);
            this->bufferQueue.push_back(newBuffer);
            this->totalBufferSize += newBuffer->Bytes();
            this->waitCondition.notify_all();
        }
        return true;
    }
}
예제 #2
0
void Player::ThreadLoop(){
    // First start the stream
    this->stream    = Stream::Create();
    if(this->stream->OpenStream(this->url)){
        {
            boost::mutex::scoped_lock lock(this->mutex);
            // Set the volume in the output
            this->output->SetVolume(this->volume);
        }

        // If it's not started, lets precache
        bool keepPrecaching(true);
        while(this->State()==Precache && keepPrecaching){
            keepPrecaching  = this->PreBuffer();
            boost::thread::yield();
        }

        // Lets wait until we are not precaching anymore
        {
            boost::mutex::scoped_lock lock(this->mutex);
            while(this->state==Precache){
                this->waitCondition.wait(lock);
            }
        }

        this->PlaybackStarted(this);

        // Player should be started or quit by now
        bool finished(false);
        while(!finished && !this->Exited()){
            if(this->setPosition!=-1){
                // Set a new position
                this->output->ClearBuffers();
                this->stream->SetPosition(this->setPosition);
                {
                    boost::mutex::scoped_lock lock(this->mutex);
                    this->bufferQueue.clear();
//                    this->lockedBuffers.clear();
                    this->setPosition       = -1;
                    this->totalBufferSize   = 0;
                }
            }

            this->output->ReleaseBuffers();

            // Get a buffer, either from the bufferQueue, or from the stream
            BufferPtr buffer;

            if(!this->BufferQueueEmpty()){
                boost::mutex::scoped_lock lock(this->mutex);
                buffer  = this->bufferQueue.front();
            }else{
                buffer  = this->stream->NextBuffer();
                if(buffer){
                    boost::mutex::scoped_lock lock(this->mutex);
                    this->bufferQueue.push_back(buffer);
                    this->totalBufferSize += buffer->Bytes();
                }
		else {
			
		}
            }

            if(buffer){

                {
                    // Add the buffer to locked buffers so the output do not have time to play and 
                    // try to release the buffer before we have to add it.
                    boost::mutex::scoped_lock lock(this->mutex);
                    this->lockedBuffers.push_back(buffer);
                }

                // Try to play the buffer
                if(!this->output->PlayBuffer(buffer.get(),this)){
                    {
                        // We didn't manage to play the buffer, remove it from the locked buffer queue
                        boost::mutex::scoped_lock lock(this->mutex);
                        this->lockedBuffers.pop_back();
                    }

                    if(!this->PreBuffer()){
#ifdef _DEBUG
        	std::cerr << "!this->PreBuffer" << std::endl;
#endif
                        // Wait for buffersize to become smaller
                        boost::mutex::scoped_lock lock(this->mutex);
                        if(this->totalBufferSize>this->maxBufferSize){
                            this->waitCondition.wait(lock);
                        }

                    }
                }else{
                    // Buffer send to output
                    boost::mutex::scoped_lock lock(this->mutex);
                    if(!this->bufferQueue.empty()){
                        this->bufferQueue.pop_front();

                        // Set currentPosition
                        if(this->lockedBuffers.size()==1){
                            this->currentPosition   = buffer->Position();
                        }
                    }

                }
            }else{
                // We have no more to decode
                finished    = true;
            }
        }

        // TODO: call a signal to notify that player is almost done
        if(!this->Exited()){
            this->PlaybackAlmostEnded(this);
        }

        // We need to wait for all the lockedBuffers to be released
        bool buffersEmpty=false;
        do{
            this->output->ReleaseBuffers();
            {
                boost::mutex::scoped_lock lock(this->mutex);
                buffersEmpty    = this->lockedBuffers.empty();
                if(!buffersEmpty && this->state!=Player::Quit){
                    this->waitCondition.wait(lock);
                }
            }
        }while(!buffersEmpty && !this->Exited());

    }else{
        // Unable to open stream
        this->PlaybackError(this);
    }

    {
        boost::mutex::scoped_lock lock(this->mutex);
        this->state    = Player::Quit;
    }

    this->PlaybackEnded(this);

    this->output->ReleaseBuffers();

    this->output.reset();
    this->stream.reset();

}