⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oggmultithread.cpp

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 *  Copyright (c) 2005 S. Fisher
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

// Platform settings
#include <OggOs.h>

// This file is for MULTI_THREAD_PLAYBACK only
#if defined(MULTI_THREAD_PLAYBACK)

#include <e32std.h>
#include "OggLog.h"
#include "OggTremor.h"
#include "OggMultiThread.h"


// Shared data class
TStreamingThreadData::TStreamingThreadData(COggPlayback& aOggPlayback, RThread& aUIThread, RThread& aBufferingThread)
: iOggPlayback(aOggPlayback), iUIThread(aUIThread), iBufferingThread(aBufferingThread),
iNumBuffersRead(0), iNumBuffersPlayed(0), iPrimeBufNum(0), iBufRequestInProgress(EFalse), iLastBuffer(NULL),
iBufferBytesRead(0), iBufferBytesPlayed(0), iTotalBufferBytes(0), iSampleRate(8000), iChannels(1), iBufferingMode(ENoBuffering)
{
}

// Buffering AO (base class for CBufferingThreadAO and CStreamingThreadAO)
CBufferingAO::CBufferingAO(TInt aPriority, TStreamingThreadData& aSharedData)
: CActive(aPriority), iSharedData(aSharedData)
{
}

CBufferingAO::~CBufferingAO()
{
}

// Decode (prime) the next audio buffer
// iSharedData.iPrimeBufNum holds the index of the next buffer
// Set the last buffer ptr if eof is encountered
void CBufferingAO::PrimeNextBuffer()
{
	TBool lastBuffer = iSharedData.iOggPlayback.PrimeBuffer(*(iSharedData.iOggPlayback.iBuffer[iSharedData.iPrimeBufNum]));
	TInt bufferBytes = iSharedData.iOggPlayback.iBuffer[iSharedData.iPrimeBufNum]->Length();
	iSharedData.iTotalBufferBytes += bufferBytes;

	iSharedData.iBufferBytesRead += bufferBytes;
	iSharedData.iNumBuffersRead++;

	if (lastBuffer)
		iSharedData.iLastBuffer = iSharedData.iOggPlayback.iBuffer[iSharedData.iPrimeBufNum];
 
	iSharedData.iPrimeBufNum++;
	if (iSharedData.iPrimeBufNum == iSharedData.iMaxBuffers)
		iSharedData.iPrimeBufNum = 0;
}

// Buffering thread AO (used in MultiThread mode only)
// This AO is owned by the COggPlayback object and runs in the buffering thread
CBufferingThreadAO::CBufferingThreadAO(TStreamingThreadData& aSharedData)
: CBufferingAO(EPriorityIdle, aSharedData)
{
}

CBufferingThreadAO::~CBufferingThreadAO()
{
}

void CBufferingThreadAO::StartListening()
{
	// Set the AO active (wait for the streaming thread to make a buffering request)
	iStatus = KRequestPending;
	SetActive();
}

// Prime the next buffer and self complete to prime more buffers if possible
void CBufferingThreadAO::RunL()
{
	// Decode the next buffer
	PrimeNextBuffer();

	// Stop buffering if we have filled all the buffers (or if we have got to the last buffer)
	if ((iSharedData.NumBuffers() == iSharedData.iBuffersToUse) && !iSharedData.iLastBuffer)
	{
	  // Listen for the next buffering request
	  iStatus = KRequestPending;
	  SetActive();

	  iSharedData.iBufRequestInProgress = EFalse;
	}
	else if (!iSharedData.iLastBuffer)
	{
	  // More buffers are required, so self complete
	  TRequestStatus* status = &iStatus;
	  User::RequestComplete(status, KErrNone);

	  SetActive();
	}
	else
	  iSharedData.iBufRequestInProgress = EFalse;
}

// The buffering thread AO is owned by COggPlayback
// The COggPlayback object must ensure that the buffering AO is not cancelled if the streaming thread could be about to make a buffering request
// In other words, the streaming thread must be in a known, "inactive", state before the buffering thread AO is cancelled
void CBufferingThreadAO::DoCancel()
{
	// If iSharedData.iBufRequestInProgress is true we will have self completed so there is nothing to do
	// If iSharedData.iBufRequestInProgress is false we are waiting for a request from the streaming thread so we must complete the request with KErrCancel
	if (!iSharedData.iBufRequestInProgress)
	{
		TRequestStatus* status = &iStatus;
		User::RequestComplete(status, KErrCancel);
	}

	iSharedData.iBufRequestInProgress = EFalse;
}

// Streaming thread AO (It is used in SingleThread and MultiThread mode only)
// The streaming thread AO is owned by the playback engine and runs in the streaming thread
// aBufferFlushPending and aBufferingThreadPriority are references to the values held in the playback engine
CStreamingThreadAO::CStreamingThreadAO(TStreamingThreadData& aSharedData, TBool& aBufferFlushPending, TThreadPriority& aBufferingThreadPriority)
: CBufferingAO(EPriorityIdle, aSharedData),iBufferFlushPending(aBufferFlushPending), iBufferingThreadPriority(aBufferingThreadPriority)
{
}

CStreamingThreadAO::~CStreamingThreadAO()
{
}

void CStreamingThreadAO::StartBuffering()
{
	// Fetch the pre buffers
	for (TInt i = 0 ; i<KPreBuffers ; i++)
		PrimeNextBuffer();

	// Start the AO
	ResumeBuffering();
}

void CStreamingThreadAO::ResumeBuffering()
{
	// Schedule the buffering (self complete)
	TRequestStatus* status = &iStatus;
	User::RequestComplete(status, KErrNone);

	SetActive();
}

// Prime the next buffer and self complete to prime more buffers if possible
// In MultiThread mode transfer the buffering to the buffering thread once there are KPrimeBuffers available
void CStreamingThreadAO::RunL()
{
	// Decode the next buffer
	PrimeNextBuffer();

	// If we've got enough buffers and more buffering is required, transfer the buffering to the buffering thread
	if ((iSharedData.NumBuffers() > KPrimeBuffers) && !iSharedData.iLastBuffer && (iSharedData.iBufferingMode == EBufferThread))
	{
		// We can't transfer the buffering if there is a buffer flush pending, so simply return
		if (iBufferFlushPending)
			return;

		// Set the buffering request flag
		iSharedData.iBufRequestInProgress = ETrue;

		// Increase the buffering thread priority
		iBufferingThreadPriority = (iBufferingThreadPriority == EPriorityNormal) ? EPriorityMore : EPriorityAbsoluteHigh;
		iSharedData.iBufferingThread.SetPriority(iBufferingThreadPriority);

		// Transfer buffering to the buffering thread
		TRequestStatus* status = &iSharedData.iBufferingThreadAO->iStatus;
		iSharedData.iBufferingThread.RequestComplete(status, KErrNone);
	}
	else if ((iSharedData.NumBuffers() < iSharedData.iBuffersToUse) && !iSharedData.iLastBuffer)
	{
		// Self complete (keep buffering)
		TRequestStatus* status = &iStatus;
		User::RequestComplete(status, KErrNone);

		SetActive();
	}
}

void CStreamingThreadAO::DoCancel()
{
	// There is nothing to do here:
	// this AO is either inactive or will have self completed
}

// Streaming thread command handler AO
// The streaming thread command handler is owned by the COggPlayback object and runs in the streaming thread
// Accepts commands from the UI thread (the command thread)
// Executes commands in the streaming thread (the command handler thread)
CStreamingThreadCommandHandler::CStreamingThreadCommandHandler(RThread& aCommandThread, RThread& aStreamingThread, CThreadPanicHandler& aPanicHandler)
: CThreadCommandHandler(EPriorityHigh, aCommandThread, aStreamingThread, aPanicHandler)
{
}

CStreamingThreadCommandHandler::~CStreamingThreadCommandHandler()
{
}

void CStreamingThreadCommandHandler::Volume()
{
	SendCommand(EStreamingThreadVolume);
}

void CStreamingThreadCommandHandler::SetVolume()
{
	SendCommand(EStreamingThreadSetVolume);
}

TInt CStreamingThreadCommandHandler::SetAudioProperties()
{
	return SendCommand(EStreamingThreadSetAudioProperties);
}

void CStreamingThreadCommandHandler::StartStreaming()
{
	SendCommand(EStreamingThreadStartStreaming);
}

void CStreamingThreadCommandHandler::StopStreaming()
{
	SendCommand(EStreamingThreadStopStreaming);
}

void CStreamingThreadCommandHandler::SetBufferingMode()
{
	SendCommand(EStreamingThreadSetBufferingMode);
}

void CStreamingThreadCommandHandler::SetThreadPriority()
{
	SendCommand(EStreamingThreadSetThreadPriority);
}

void CStreamingThreadCommandHandler::Position()
{
	SendCommand(EStreamingThreadPosition);
}

TBool CStreamingThreadCommandHandler::PrepareToFlushBuffers()
{
	return SendCommand(EStreamingThreadPrepareToFlushBuffers) ? ETrue : EFalse;
}

TBool CStreamingThreadCommandHandler::FlushBuffers()
{
	return SendCommand(EStreamingThreadFlushBuffers) ? ETrue : EFalse;
}

// Wait for commands
// Commands are passed to the playback engine
void CStreamingThreadCommandHandler::ListenForCommands(CStreamingThreadPlaybackEngine& aPlaybackEngine)
{
	iPlaybackEngine = &aPlaybackEngine;
	CThreadCommandHandler::ListenForCommands();
}

// Handle commands
// The AO completion status is the command to execute
void CStreamingThreadCommandHandler::RunL()
{
	// Get the status
	TInt status = iStatus.Int();

	// Start listening again
	iStatus = KRequestPending;
	SetActive();

	// Dispatch commands to the playback engine
	TInt err = KErrNone;
	switch (status)
	{
	case EStreamingThreadSetAudioProperties:
		TRAP(err, iPlaybackEngine->SetAudioPropertiesL());
		break;

	case EStreamingThreadVolume:
		iPlaybackEngine->Volume();
		break;

	case EStreamingThreadSetVolume:
		iPlaybackEngine->SetVolume();
		break;

	case EStreamingThreadStartStreaming:
		iPlaybackEngine->StartStreaming();
		break;

	case EStreamingThreadStopStreaming:
		iPlaybackEngine->StopStreaming();
		break;

	case EStreamingThreadSetBufferingMode:
		iPlaybackEngine->SetBufferingMode();
		break;

	case EStreamingThreadSetThreadPriority:
		iPlaybackEngine->SetThreadPriority();
		break;

	case EStreamingThreadPosition:
		iPlaybackEngine->Position();
		break;

	case EStreamingThreadPrepareToFlushBuffers:
		err = iPlaybackEngine->PrepareToFlushBuffers() ? 1 : 0;
		break;

	case EStreamingThreadFlushBuffers:
		err = iPlaybackEngine->FlushBuffers() ? 1 : 0;
		break;

	case EThreadShutdown:
		iPlaybackEngine->Shutdown();
		CActiveScheduler::Stop();
		return;

	default:
		// Panic if we get an unkown command
		User::Panic(_L("STCL: RunL"), 0);
		break;
	}

	// Complete the request
	RequestComplete(err);
}

void CStreamingThreadCommandHandler::DoCancel()
{
	// Stop listening

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -