📄 symbian_sound.cpp
字号:
rec_cb,
user_data);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CPjAudioOutputEngine *
CPjAudioOutputEngine::NewL(pjmedia_snd_stream *parent_strm,
pjmedia_snd_play_cb play_cb,
void *user_data)
{
CPjAudioOutputEngine *self = NewLC(parent_strm, play_cb, user_data);
CleanupStack::Pop(self);
return self;
}
pj_status_t CPjAudioOutputEngine::StartPlay()
{
// Ignore command if playing is in progress.
if (state_ == STATE_ACTIVE)
return PJ_SUCCESS;
// Destroy existing stream.
if (iOutputStream_) delete iOutputStream_;
iOutputStream_ = NULL;
// Create the stream
TRAPD(err, iOutputStream_ = CMdaAudioOutputStream::NewL(*this));
if (err != KErrNone)
return PJ_RETURN_OS_ERROR(err);
// Initialize settings.
TMdaAudioDataSettings iStreamSettings;
iStreamSettings.iChannels = get_channel_cap(parentStrm_->channel_count);
iStreamSettings.iSampleRate = get_clock_rate_cap(parentStrm_->clock_rate);
pj_assert(iStreamSettings.iChannels != 0 &&
iStreamSettings.iSampleRate != 0);
PJ_LOG(4,(THIS_FILE, "Opening sound device for playback, "
"clock rate=%d, channel count=%d..",
parentStrm_->clock_rate,
parentStrm_->channel_count));
// Open stream.
lastError_ = KRequestPending;
iOutputStream_->Open(&iStreamSettings);
// Wait until callback is called.
while (lastError_ == KRequestPending)
pj_thread_sleep(100);
// Handle failure.
if (lastError_ != KErrNone) {
delete iOutputStream_;
iOutputStream_ = NULL;
return PJ_RETURN_OS_ERROR(lastError_);
}
// Success
PJ_LOG(4,(THIS_FILE, "Sound playback started"));
return PJ_SUCCESS;
}
void CPjAudioOutputEngine::Stop()
{
// Stop stream if it's playing
if (iOutputStream_ && state_ != STATE_INACTIVE) {
lastError_ = KRequestPending;
iOutputStream_->Stop();
// Wait until it's actually stopped
while (lastError_ == KRequestPending)
pj_thread_sleep(100);
}
if (iOutputStream_) {
delete iOutputStream_;
iOutputStream_ = NULL;
}
state_ = STATE_INACTIVE;
}
void CPjAudioOutputEngine::MaoscOpenComplete(TInt aError)
{
lastError_ = aError;
if (aError==KErrNone) {
// output stream opened succesfully, set status to Active
state_ = STATE_ACTIVE;
// set stream properties, 16bit 8KHz mono
TMdaAudioDataSettings iSettings;
iSettings.iChannels = get_channel_cap(parentStrm_->channel_count);
iSettings.iSampleRate = get_clock_rate_cap(parentStrm_->clock_rate);
iOutputStream_->SetAudioPropertiesL(iSettings.iSampleRate,
iSettings.iChannels);
// set volume to 1/4th of stream max volume
iOutputStream_->SetVolume(iOutputStream_->MaxVolume()/4);
// set stream priority to normal and time sensitive
iOutputStream_->SetPriority(EPriorityNormal,
EMdaPriorityPreferenceTime);
// Call callback to retrieve frame from upstream.
pj_status_t status;
status = playCb_(this->userData_, timestamp_, frameBuf_,
frameBufSize_);
if (status != PJ_SUCCESS) {
this->Stop();
return;
}
// Increment timestamp.
timestamp_ += (frameBufSize_ / BYTES_PER_SAMPLE);
// issue WriteL() to write the first audio data block,
// subsequent calls to WriteL() will be issued in
// MMdaAudioOutputStreamCallback::MaoscBufferCopied()
// until whole data buffer is written.
TPtrC8 frame(frameBuf_, frameBufSize_);
iOutputStream_->WriteL(frame);
}
}
void CPjAudioOutputEngine::MaoscBufferCopied(TInt aError,
const TDesC8& aBuffer)
{
PJ_UNUSED_ARG(aBuffer);
if (aError==KErrNone) {
// Buffer successfully written, feed another one.
// Call callback to retrieve frame from upstream.
pj_status_t status;
status = playCb_(this->userData_, timestamp_, frameBuf_,
frameBufSize_);
if (status != PJ_SUCCESS) {
this->Stop();
return;
}
// Increment timestamp.
timestamp_ += (frameBufSize_ / BYTES_PER_SAMPLE);
// Write to playback stream.
TPtrC8 frame(frameBuf_, frameBufSize_);
iOutputStream_->WriteL(frame);
} else if (aError==KErrAbort) {
// playing was aborted, due to call to CMdaAudioOutputStream::Stop()
state_ = STATE_INACTIVE;
} else {
// error writing data to output
lastError_ = aError;
state_ = STATE_INACTIVE;
}
}
void CPjAudioOutputEngine::MaoscPlayComplete(TInt aError)
{
lastError_ = aError;
state_ = STATE_INACTIVE;
}
//////////////////////////////////////////////////////////////////////////////
//
/*
* Initialize sound subsystem.
*/
PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
{
snd_pool_factory = factory;
return PJ_SUCCESS;
}
/*
* Get device count.
*/
PJ_DEF(int) pjmedia_snd_get_dev_count(void)
{
/* Always return 1 */
return 1;
}
/*
* Get device info.
*/
PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
{
/* Always return the default sound device */
PJ_ASSERT_RETURN(index==0, NULL);
return &symbian_snd_dev_info;
}
/*
* Open sound recorder stream.
*/
PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample,
pjmedia_snd_rec_cb rec_cb,
void *user_data,
pjmedia_snd_stream **p_snd_strm)
{
pj_pool_t *pool;
pjmedia_snd_stream *strm;
PJ_ASSERT_RETURN(index == 0, PJ_EINVAL);
PJ_ASSERT_RETURN(clock_rate && channel_count && samples_per_frame &&
bits_per_sample && rec_cb && p_snd_strm, PJ_EINVAL);
pool = pj_pool_create(snd_pool_factory, POOL_NAME, POOL_SIZE, POOL_INC,
NULL);
if (!pool)
return PJ_ENOMEM;
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
sizeof(pjmedia_snd_stream));
strm->pool = pool;
strm->clock_rate = clock_rate;
strm->channel_count = channel_count;
strm->samples_per_frame = samples_per_frame;
TMdaAudioDataSettings settings;
TInt clockRateCap, channelCountCap;
clockRateCap = get_clock_rate_cap(clock_rate);
channelCountCap = get_channel_cap(channel_count);
PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
PJ_ASSERT_RETURN(clockRateCap != 0, PJ_EINVAL);
PJ_ASSERT_RETURN(channelCountCap != 0, PJ_EINVAL);
// Create the input stream.
TRAPD(err, strm->inEngine = CPjAudioInputEngine::NewL(strm, rec_cb,
user_data));
if (err != KErrNone) {
pj_pool_release(pool);
return PJ_RETURN_OS_ERROR(err);
}
// Done.
*p_snd_strm = strm;
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample,
pjmedia_snd_play_cb play_cb,
void *user_data,
pjmedia_snd_stream **p_snd_strm )
{
pj_pool_t *pool;
pjmedia_snd_stream *strm;
PJ_ASSERT_RETURN(index == 0, PJ_EINVAL);
PJ_ASSERT_RETURN(clock_rate && channel_count && samples_per_frame &&
bits_per_sample && play_cb && p_snd_strm, PJ_EINVAL);
pool = pj_pool_create(snd_pool_factory, POOL_NAME, POOL_SIZE, POOL_INC,
NULL);
if (!pool)
return PJ_ENOMEM;
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
sizeof(pjmedia_snd_stream));
strm->pool = pool;
strm->clock_rate = clock_rate;
strm->channel_count = channel_count;
strm->samples_per_frame = samples_per_frame;
TMdaAudioDataSettings settings;
TInt clockRateCap, channelCountCap;
clockRateCap = get_clock_rate_cap(clock_rate);
channelCountCap = get_channel_cap(channel_count);
PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
PJ_ASSERT_RETURN(clockRateCap != 0, PJ_EINVAL);
PJ_ASSERT_RETURN(channelCountCap != 0, PJ_EINVAL);
// Create the output stream.
TRAPD(err, strm->outEngine = CPjAudioOutputEngine::NewL(strm, play_cb,
user_data));
if (err != KErrNone) {
pj_pool_release(pool);
return PJ_RETURN_OS_ERROR(err);
}
// Done.
*p_snd_strm = strm;
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id,
int play_id,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample,
pjmedia_snd_rec_cb rec_cb,
pjmedia_snd_play_cb play_cb,
void *user_data,
pjmedia_snd_stream **p_snd_strm)
{
pj_pool_t *pool;
pjmedia_snd_stream *strm;
PJ_ASSERT_RETURN(rec_id == 0 && play_id == 0, PJ_EINVAL);
PJ_ASSERT_RETURN(clock_rate && channel_count && samples_per_frame &&
bits_per_sample && rec_cb && play_cb && p_snd_strm,
PJ_EINVAL);
pool = pj_pool_create(snd_pool_factory, POOL_NAME, POOL_SIZE, POOL_INC,
NULL);
if (!pool)
return PJ_ENOMEM;
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
sizeof(pjmedia_snd_stream));
strm->pool = pool;
strm->clock_rate = clock_rate;
strm->channel_count = channel_count;
strm->samples_per_frame = samples_per_frame;
TMdaAudioDataSettings settings;
TInt clockRateCap, channelCountCap;
clockRateCap = get_clock_rate_cap(clock_rate);
channelCountCap = get_channel_cap(channel_count);
PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
PJ_ASSERT_RETURN(clockRateCap != 0, PJ_EINVAL);
PJ_ASSERT_RETURN(channelCountCap != 0, PJ_EINVAL);
// Create the output stream.
TRAPD(err, strm->outEngine = CPjAudioOutputEngine::NewL(strm, play_cb,
user_data));
if (err != KErrNone) {
pj_pool_release(pool);
return PJ_RETURN_OS_ERROR(err);
}
// Done.
*p_snd_strm = strm;
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
{
pj_status_t status;
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
if (stream->inEngine) {
status = stream->inEngine->StartRecord();
if (status != PJ_SUCCESS)
return status;
}
if (stream->outEngine) {
status = stream->outEngine->StartPlay();
if (status != PJ_SUCCESS)
return status;
}
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)
{
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
if (stream->inEngine) {
stream->inEngine->Stop();
}
if (stream->outEngine) {
stream->outEngine->Stop();
}
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream)
{
pj_pool_t *pool;
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
if (stream->inEngine) {
delete stream->inEngine;
stream->inEngine = NULL;
}
if (stream->outEngine) {
delete stream->outEngine;
stream->outEngine = NULL;
}
pool = stream->pool;
if (pool) {
stream->pool = NULL;
pj_pool_release(pool);
}
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)
{
/* Nothing to do */
return PJ_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -