diff options
-rw-r--r-- | pjlib/include/pj/config_site_sample.h | 4 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/symbian_sound.cpp | 98 | ||||
-rw-r--r-- | pjsip-apps/src/symbian_ua/ua.cpp | 15 | ||||
-rw-r--r-- | pjsip-apps/src/symsndtest/app_main.cpp | 32 |
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; |