summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-12-28 18:55:02 +0000
committerBenny Prijono <bennylp@teluu.com>2007-12-28 18:55:02 +0000
commit4cc0627a188a719358d9deb8a884b3941ee86820 (patch)
treeb8151af7aae830dec86bd54d1fa2aa68f8a08d5e
parenta1a1a2babda1465967373157c26c3d88a44f3cca (diff)
Ticket #435: Fixed and tested audio on Symbian device
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1641 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/config_site_sample.h4
-rw-r--r--pjmedia/src/pjmedia/symbian_sound.cpp98
-rw-r--r--pjsip-apps/src/symbian_ua/ua.cpp15
-rw-r--r--pjsip-apps/src/symsndtest/app_main.cpp32
4 files changed, 123 insertions, 26 deletions
diff --git a/pjlib/include/pj/config_site_sample.h b/pjlib/include/pj/config_site_sample.h
index 1f1ed58a..a786c959 100644
--- a/pjlib/include/pj/config_site_sample.h
+++ b/pjlib/include/pj/config_site_sample.h
@@ -76,7 +76,9 @@
# define PJSIP_MAX_TSX_COUNT 31
# define PJSIP_MAX_DIALOG_COUNT 31
# define PJSUA_MAX_CALLS 31
-
+
+# define PJMEDIA_SOUND_BUFFER_COUNT 12
+
#endif
diff --git a/pjmedia/src/pjmedia/symbian_sound.cpp b/pjmedia/src/pjmedia/symbian_sound.cpp
index ee49f487..4d5ea7b0 100644
--- a/pjmedia/src/pjmedia/symbian_sound.cpp
+++ b/pjmedia/src/pjmedia/symbian_sound.cpp
@@ -64,6 +64,7 @@ struct pjmedia_snd_stream
pj_pool_t *pool;
// Common settings.
+ pjmedia_dir dir;
unsigned clock_rate;
unsigned channel_count;
unsigned samples_per_frame;
@@ -162,6 +163,15 @@ private:
TInt lastError_;
pj_uint32_t timeStamp_;
+ // cache variable
+ // to avoid calculating frame length repeatedly
+ TInt frameLen_;
+
+ // in some SymbianOS (e.g: OSv9.1), sometimes recorded size != requested framesize
+ // so let's provide a buffer to make sure the rec callback returns framesize as requested.
+ TUint8 *frameRecBuf_;
+ TInt frameRecBufLen_;
+
CPjAudioInputEngine(pjmedia_snd_stream *parent_strm,
pjmedia_snd_rec_cb rec_cb,
void *user_data);
@@ -179,24 +189,34 @@ public:
CPjAudioInputEngine::CPjAudioInputEngine(pjmedia_snd_stream *parent_strm,
pjmedia_snd_rec_cb rec_cb,
void *user_data)
- : state_(STATE_INACTIVE), parentStrm_(parent_strm), recCb_(rec_cb),
+ : state_(STATE_INACTIVE), parentStrm_(parent_strm),
+ recCb_(rec_cb), userData_(user_data),
iInputStream_(NULL), iStreamBuffer_(NULL), iFramePtr_(0, 0),
- userData_(user_data), lastError_(KErrNone), timeStamp_(0)
+ lastError_(KErrNone), timeStamp_(0),
+ frameLen_(parent_strm->samples_per_frame * parent_strm->channel_count * BYTES_PER_SAMPLE),
+ frameRecBuf_(NULL), frameRecBufLen_(0)
{
}
CPjAudioInputEngine::~CPjAudioInputEngine()
{
Stop();
+
delete iStreamBuffer_;
iStreamBuffer_ = NULL;
+
+ delete [] frameRecBuf_;
+ frameRecBuf_ = NULL;
+ frameRecBufLen_ = 0;
}
void CPjAudioInputEngine::ConstructL()
{
- iStreamBuffer_ = HBufC8::NewL(parentStrm_->samples_per_frame *
- parentStrm_->channel_count *
- BYTES_PER_SAMPLE);
+ iStreamBuffer_ = HBufC8::NewL(frameLen_);
+ CleanupStack::PushL(iStreamBuffer_);
+
+ frameRecBuf_ = new TUint8[frameLen_*2];
+ CleanupStack::PushL(frameRecBuf_);
}
CPjAudioInputEngine *CPjAudioInputEngine::NewLC(pjmedia_snd_stream *parent,
@@ -216,6 +236,8 @@ CPjAudioInputEngine *CPjAudioInputEngine::NewL(pjmedia_snd_stream *parent,
void *user_data)
{
CPjAudioInputEngine *self = NewLC(parent, rec_cb, user_data);
+ CleanupStack::Pop(self->frameRecBuf_);
+ CleanupStack::Pop(self->iStreamBuffer_);
CleanupStack::Pop(self);
return self;
}
@@ -289,11 +311,8 @@ void CPjAudioInputEngine::Stop()
TPtr8 & CPjAudioInputEngine::GetFrame()
{
- TInt l = parentStrm_->samples_per_frame *
- parentStrm_->channel_count *
- BYTES_PER_SAMPLE;
- iStreamBuffer_->Des().FillZ(l);
- iFramePtr_.Set((TUint8*)(iStreamBuffer_->Ptr()), l, l);
+ //iStreamBuffer_->Des().FillZ(frameLen_);
+ iFramePtr_.Set((TUint8*)(iStreamBuffer_->Ptr()), frameLen_, frameLen_);
return iFramePtr_;
}
@@ -326,11 +345,27 @@ void CPjAudioInputEngine::MaiscBufferCopied(TInt aError,
return;
}
- // Call the callback.
- recCb_(userData_, timeStamp_, (void*)aBuffer.Ptr(), aBuffer.Size());
+ if (frameRecBufLen_ || aBuffer.Size() < frameLen_) {
+ pj_memcpy(frameRecBuf_ + frameRecBufLen_, (void*) aBuffer.Ptr(), aBuffer.Size());
+ frameRecBufLen_ += aBuffer.Size();
+ }
+
+ if (frameRecBufLen_) {
+ while (frameRecBufLen_ >= frameLen_) {
+ // Call the callback.
+ recCb_(userData_, timeStamp_, frameRecBuf_, frameLen_);
+ // Increment timestamp.
+ timeStamp_ += parentStrm_->samples_per_frame;
- // Increment timestamp.
- timeStamp_ += (aBuffer.Size() * BYTES_PER_SAMPLE);
+ frameRecBufLen_ -= frameLen_;
+ pj_memmove(frameRecBuf_, frameRecBuf_+frameLen_, frameRecBufLen_);
+ }
+ } else {
+ // Call the callback.
+ recCb_(userData_, timeStamp_, (void*) aBuffer.Ptr(), aBuffer.Size());
+ // Increment timestamp.
+ timeStamp_ += parentStrm_->samples_per_frame;
+ }
// Record next frame
TPtr8 & frm = GetFrame();
@@ -525,8 +560,8 @@ void CPjAudioOutputEngine::MaoscOpenComplete(TInt aError)
iOutputStream_->SetAudioPropertiesL(iSettings.iSampleRate,
iSettings.iChannels);
- // set volume to 1/4th of stream max volume
- iOutputStream_->SetVolume(iOutputStream_->MaxVolume()/4);
+ // set volume to 1/2th of stream max volume
+ iOutputStream_->SetVolume(iOutputStream_->MaxVolume()/2);
// set stream priority to normal and time sensitive
iOutputStream_->SetPriority(EPriorityNormal,
@@ -628,6 +663,9 @@ PJ_DEF(int) pjmedia_snd_get_dev_count(void)
PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
{
/* Always return the default sound device */
+ if (index == (unsigned)-1)
+ index = 0;
+
PJ_ASSERT_RETURN(index==0, NULL);
return &symbian_snd_dev_info;
}
@@ -662,6 +700,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
sizeof(pjmedia_snd_stream));
+ strm->dir = PJMEDIA_DIR_CAPTURE;
strm->pool = pool;
strm->clock_rate = clock_rate;
strm->channel_count = channel_count;
@@ -676,10 +715,9 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
user_data));
if (err != KErrNone) {
pj_pool_release(pool);
- return PJ_RETURN_OS_ERROR(err);
+ return PJ_RETURN_OS_ERROR(err);
}
-
// Done.
*p_snd_strm = strm;
return PJ_SUCCESS;
@@ -710,6 +748,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
sizeof(pjmedia_snd_stream));
+ strm->dir = PJMEDIA_DIR_PLAYBACK;
strm->pool = pool;
strm->clock_rate = clock_rate;
strm->channel_count = channel_count;
@@ -761,6 +800,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id,
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
sizeof(pjmedia_snd_stream));
+ strm->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
strm->pool = pool;
strm->clock_rate = clock_rate;
strm->channel_count = channel_count;
@@ -794,6 +834,28 @@ PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id,
return PJ_SUCCESS;
}
+/*
+ * Get stream info.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,
+ pjmedia_snd_stream_info *pi)
+{
+ PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
+
+ pj_bzero(pi, sizeof(*pi));
+ pi->dir = strm->dir;
+ pi->play_id = 0;
+ pi->rec_id = 0;
+ pi->clock_rate = strm->clock_rate;
+ pi->channel_count = strm->channel_count;
+ pi->samples_per_frame = strm->samples_per_frame;
+ pi->bits_per_sample = BYTES_PER_SAMPLE * 8;
+ pi->rec_latency = 0;
+ pi->play_latency = 0;
+
+ return PJ_SUCCESS;
+}
+
PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
{
diff --git a/pjsip-apps/src/symbian_ua/ua.cpp b/pjsip-apps/src/symbian_ua/ua.cpp
index f8a2ec38..1dd8a20d 100644
--- a/pjsip-apps/src/symbian_ua/ua.cpp
+++ b/pjsip-apps/src/symbian_ua/ua.cpp
@@ -31,7 +31,7 @@
//
// Destination URI (to make call, or to subscribe presence)
//
-#define SIP_DST_URI "sip:192.168.0.7:5061"
+#define SIP_DST_URI "sip:192.168.0.11:5060"
//
// Account
@@ -57,7 +57,7 @@
//
// STUN server
-#if 1
+#if 0
// Use this to have the STUN server resolved normally
# define STUN_DOMAIN NULL
# define STUN_SERVER "stun.fwdnet.net"
@@ -74,7 +74,7 @@
//
// Use ICE?
//
-#define USE_ICE 1
+#define USE_ICE 0
//
@@ -320,6 +320,7 @@ static pj_status_t app_startup()
med_cfg.thread_cnt = 0; // Disable threading on Symbian
med_cfg.has_ioqueue = PJ_FALSE;
med_cfg.clock_rate = 8000;
+ med_cfg.audio_frame_ptime = 40;
med_cfg.ec_tail_len = 0;
med_cfg.enable_ice = USE_ICE;
@@ -452,6 +453,8 @@ static void PrintMenu()
" d Dump states\n"
" D Dump states detail\n"
" P Dump pool factory\n"
+ " l Start loopback audio device\n"
+ " L Stop loopback audio device\n"
" m Call " SIP_DST_URI "\n"
" a Answer call\n"
" h Hangup all calls\n"
@@ -481,6 +484,12 @@ void ConsoleUI::RunL()
case 'P':
pj_pool_factory_dump(pjsua_get_pool_factory(), PJ_TRUE);
break;
+ case 'l':
+ pjsua_conf_connect(0, 0);
+ break;
+ case 'L':
+ pjsua_conf_disconnect(0, 0);
+ break;
case 'm':
if (g_call_id != PJSUA_INVALID_ID) {
PJ_LOG(3,(THIS_FILE, "Another call is active"));
diff --git a/pjsip-apps/src/symsndtest/app_main.cpp b/pjsip-apps/src/symsndtest/app_main.cpp
index dcd6ed88..981e5308 100644
--- a/pjsip-apps/src/symsndtest/app_main.cpp
+++ b/pjsip-apps/src/symsndtest/app_main.cpp
@@ -28,9 +28,9 @@
#define CLOCK_RATE 8000
#define CHANNEL_COUNT 1
#define PTIME 100
-#define SAMPLES_PER_FRAME (2048)
+#define SAMPLES_PER_FRAME (80)
#define BITS_PER_SAMPLE 16
-
+#define LOOPBACK_BUFF_COUNT 100
extern CConsoleBase* console;
@@ -40,6 +40,9 @@ static unsigned rec_cnt, play_cnt;
static pj_time_val t_start;
+static pj_int16_t buff_loopback[SAMPLES_PER_FRAME*LOOPBACK_BUFF_COUNT];
+static pj_uint32_t pointer_w, pointer_r;
+
/* Logging callback */
static void log_writer(int level, const char *buf, unsigned len)
{
@@ -70,6 +73,7 @@ static pj_status_t app_init()
/* Redirect log */
pj_log_set_log_func((void (*)(int,const char*,int)) &log_writer);
pj_log_set_decor(PJ_LOG_HAS_NEWLINE);
+ pj_log_set_level(5);
/* Init pjlib */
status = pj_init();
@@ -114,6 +118,18 @@ static pj_status_t rec_cb(void *user_data,
PJ_UNUSED_ARG(timestamp);
PJ_UNUSED_ARG(input);
PJ_UNUSED_ARG(size);
+
+ pj_memcpy(&buff_loopback[pointer_w*SAMPLES_PER_FRAME], input, size);
+
+ if (size != SAMPLES_PER_FRAME*2) {
+ PJ_LOG(3, (THIS_FILE, "Size captured = %u",
+ size));
+ pj_bzero(&buff_loopback[pointer_w*SAMPLES_PER_FRAME]+size/2, SAMPLES_PER_FRAME*2 - size);
+ }
+
+ if (++pointer_w >= LOOPBACK_BUFF_COUNT) {
+ pointer_w = 0;
+ }
++rec_cnt;
return PJ_SUCCESS;
@@ -128,7 +144,12 @@ static pj_status_t play_cb(void *user_data,
PJ_UNUSED_ARG(user_data);
PJ_UNUSED_ARG(timestamp);
- pj_bzero(output, size);
+ //pj_bzero(output, size);
+ pj_memcpy(output, &buff_loopback[pointer_r*SAMPLES_PER_FRAME], SAMPLES_PER_FRAME*2);
+
+ if (++pointer_r >= LOOPBACK_BUFF_COUNT) {
+ pointer_r = 0;
+ }
++play_cnt;
return PJ_SUCCESS;
@@ -173,6 +194,9 @@ static pj_status_t snd_start(unsigned flag)
return status;
}
+ pointer_w = LOOPBACK_BUFF_COUNT/2;
+ pointer_r = 0;
+
return PJ_SUCCESS;
}
@@ -297,7 +321,7 @@ void ConsoleUI::RunL()
break;
case 'p':
snd_start(PJMEDIA_DIR_PLAYBACK);
- break;
+ break;
case 'c':
snd_stop();
break;