Changeset 1428


Ignore:
Timestamp:
Aug 31, 2007 3:04:52 PM (12 years ago)
Author:
bennylp
Message:

Continuing ticket #2: initial test with Symbian sound device implementation. Callback works, but not in full duplex

Location:
pjproject/trunk
Files:
4 added
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/symbian_sound.cpp

    r1242 r1428  
    116116 
    117117 
     118/* 
     119 * Utility: print sound device error 
     120 */ 
     121static void snd_perror(const char *title, TInt rc)  
     122{ 
     123    PJ_LOG(1,(THIS_FILE, "%s: error code %d", title, rc)); 
     124} 
     125  
    118126////////////////////////////////////////////////////////////////////////////// 
    119127// 
     
    122130 * Implementation: Symbian Input Stream. 
    123131 */ 
    124 class CPjAudioInputEngine : public MMdaAudioInputStreamCallback 
     132class CPjAudioInputEngine : public CBase, MMdaAudioInputStreamCallback 
    125133{ 
    126134public: 
     
    144152    void Stop(); 
    145153 
    146 public: 
     154private: 
    147155    State                    state_; 
    148156    pjmedia_snd_stream      *parentStrm_; 
     
    159167                        void *user_data); 
    160168    void ConstructL(); 
     169    TPtr8 & GetFrame(); 
    161170     
    162171public: 
     
    172181                                         void *user_data) 
    173182    : state_(STATE_INACTIVE), parentStrm_(parent_strm), recCb_(rec_cb),  
    174       iInputStream_(NULL), iStreamBuffer_(NULL), iFramePtr_(NULL, 0), 
     183      iInputStream_(NULL), iStreamBuffer_(NULL), iFramePtr_(0, 0), 
    175184      userData_(user_data), lastError_(KErrNone), timeStamp_(0) 
    176185{ 
     
    181190    Stop(); 
    182191    delete iStreamBuffer_; 
     192    iStreamBuffer_ = NULL; 
    183193} 
    184194 
    185195void CPjAudioInputEngine::ConstructL() 
    186196{ 
    187     iStreamBuffer_ = HBufC8::NewMaxL(parentStrm_->samples_per_frame * 
    188                                      parentStrm_->channel_count *  
    189                                      BYTES_PER_SAMPLE); 
     197    iStreamBuffer_ = HBufC8::NewL(parentStrm_->samples_per_frame * 
     198                                  parentStrm_->channel_count *  
     199                                  BYTES_PER_SAMPLE); 
    190200} 
    191201 
     
    242252              iStreamSettings.iSampleRate != 0); 
    243253 
    244     // Create timeout timer to wait for Open to complete 
    245     RTimer timer; 
    246     TRequestStatus reqStatus; 
    247     TInt rc; 
    248      
    249     rc = timer.CreateLocal(); 
    250     if (rc != KErrNone) { 
    251         delete iInputStream_; 
    252         iInputStream_ = NULL; 
    253         return PJ_RETURN_OS_ERROR(rc); 
    254     } 
    255  
    256254    PJ_LOG(4,(THIS_FILE, "Opening sound device for capture, " 
    257255                         "clock rate=%d, channel count=%d..", 
     
    262260    lastError_ = KRequestPending; 
    263261    iInputStream_->Open(&iStreamSettings); 
    264  
    265     // Wait until callback is called. 
    266     if (lastError_ == KRequestPending) { 
    267         timer.After(reqStatus, 5 * 1000 * 1000); 
    268  
    269         do { 
    270             User::WaitForAnyRequest(); 
    271         } while (lastError_==KRequestPending && reqStatus==KRequestPending); 
    272          
    273         if (reqStatus==KRequestPending) 
    274             timer.Cancel(); 
    275     } 
    276  
    277     // Close timer 
    278     timer.Close(); 
    279      
    280     // Handle timeout 
    281     if (lastError_ == KRequestPending) { 
    282         iInputStream_->Stop(); 
    283         delete iInputStream_; 
    284         iInputStream_ = NULL; 
    285         return PJ_ETIMEDOUT; 
    286     } 
    287     else if (lastError_ != KErrNone) { 
    288         // Handle failure. 
    289         delete iInputStream_; 
    290         iInputStream_ = NULL; 
    291         return PJ_RETURN_OS_ERROR(lastError_); 
    292     } 
    293  
    294     // Feed the first frame. 
    295     iFramePtr_ = iStreamBuffer_->Des(); 
    296     iInputStream_->ReadL(iFramePtr_); 
    297  
     262     
    298263    // Success 
    299264    PJ_LOG(4,(THIS_FILE, "Sound capture started.")); 
     
    323288 
    324289 
     290TPtr8 & CPjAudioInputEngine::GetFrame()  
     291{ 
     292    TInt l = parentStrm_->samples_per_frame * 
     293             parentStrm_->channel_count *  
     294             BYTES_PER_SAMPLE; 
     295    iStreamBuffer_->Des().FillZ(l); 
     296    iFramePtr_.Set((TUint8*)(iStreamBuffer_->Ptr()), l, l); 
     297    return iFramePtr_; 
     298} 
     299 
    325300void CPjAudioInputEngine::MaiscOpenComplete(TInt aError) 
    326301{ 
    327302    lastError_ = aError; 
     303    if (aError != KErrNone) { 
     304        snd_perror("Error in MaiscOpenComplete()", aError); 
     305        return; 
     306    } 
     307 
     308    // set stream priority to normal and time sensitive 
     309    iInputStream_->SetPriority(EPriorityNormal,  
     310                               EMdaPriorityPreferenceTime);                              
     311 
     312    // Read the first frame. 
     313    TPtr8 & frm = GetFrame(); 
     314    TRAPD(err2, iInputStream_->ReadL(frm)); 
     315    if (err2) { 
     316        PJ_LOG(4,(THIS_FILE, "Exception in iInputStream_->ReadL()")); 
     317    } 
    328318} 
    329319 
     
    332322{ 
    333323    lastError_ = aError; 
    334     if (aError != KErrNone) 
     324    if (aError != KErrNone) { 
     325        snd_perror("Error in MaiscBufferCopied()", aError); 
    335326        return; 
     327    } 
    336328 
    337329    // Call the callback. 
     
    342334 
    343335    // Record next frame 
    344     iFramePtr_ = iStreamBuffer_->Des(); 
    345     iInputStream_->ReadL(iFramePtr_); 
     336    TPtr8 & frm = GetFrame(); 
     337    TRAPD(err2, iInputStream_->ReadL(frm)); 
     338    if (err2) { 
     339        PJ_LOG(4,(THIS_FILE, "Exception in iInputStream_->ReadL()")); 
     340    } 
    346341} 
    347342 
     
    351346    lastError_ = aError; 
    352347    state_ = STATE_INACTIVE; 
     348    if (aError != KErrNone) { 
     349        snd_perror("Error in MaiscRecordComplete()", aError); 
     350    } 
    353351} 
    354352 
     
    362360 */ 
    363361 
    364 class CPjAudioOutputEngine : public MMdaAudioOutputStreamCallback 
     362class CPjAudioOutputEngine : public CBase, MMdaAudioOutputStreamCallback 
    365363{ 
    366364public: 
     
    384382    void Stop(); 
    385383 
    386 public: 
     384private: 
    387385    State                    state_; 
    388386    pjmedia_snd_stream      *parentStrm_; 
     
    392390    TUint8                  *frameBuf_; 
    393391    unsigned                 frameBufSize_; 
     392    TPtrC8                   frame_; 
    394393    TInt                     lastError_; 
    395394    unsigned                 timestamp_; 
     
    480479                         parentStrm_->clock_rate,  
    481480                         parentStrm_->channel_count)); 
    482      
     481 
    483482    // Open stream. 
    484483    lastError_ = KRequestPending; 
    485484    iOutputStream_->Open(&iStreamSettings); 
    486  
    487     // Wait until callback is called. 
    488     while (lastError_ == KRequestPending) 
    489         pj_thread_sleep(100); 
    490  
    491     // Handle failure. 
    492     if (lastError_ != KErrNone) { 
    493         delete iOutputStream_; 
    494         iOutputStream_ = NULL; 
    495         return PJ_RETURN_OS_ERROR(lastError_); 
    496     } 
    497485 
    498486    // Success 
     
    561549        // MMdaAudioOutputStreamCallback::MaoscBufferCopied()  
    562550        // until whole data buffer is written. 
    563         TPtrC8 frame(frameBuf_, frameBufSize_); 
    564         iOutputStream_->WriteL(frame); 
    565     }  
     551        frame_.Set(frameBuf_, frameBufSize_); 
     552        iOutputStream_->WriteL(frame_); 
     553    } else { 
     554        snd_perror("Error in MaoscOpenComplete()", aError); 
     555    } 
    566556} 
    567557 
     
    587577 
    588578        // Write to playback stream. 
    589         TPtrC8 frame(frameBuf_, frameBufSize_); 
    590         iOutputStream_->WriteL(frame); 
     579        frame_.Set(frameBuf_, frameBufSize_); 
     580        iOutputStream_->WriteL(frame_); 
    591581 
    592582    } else if (aError==KErrAbort) { 
     
    597587        lastError_ = aError; 
    598588        state_ = STATE_INACTIVE; 
     589        snd_perror("Error in MaoscBufferCopied()", aError); 
    599590    } 
    600591} 
     
    604595    lastError_ = aError; 
    605596    state_ = STATE_INACTIVE; 
     597    if (aError != KErrNone) { 
     598        snd_perror("Error in MaoscPlayComplete()", aError); 
     599    } 
    606600} 
    607601 
     
    656650    pjmedia_snd_stream *strm; 
    657651 
     652    if (index==-1) index = 0; 
     653     
    658654    PJ_ASSERT_RETURN(index == 0, PJ_EINVAL); 
    659655    PJ_ASSERT_RETURN(clock_rate && channel_count && samples_per_frame && 
     
    672668    strm->samples_per_frame = samples_per_frame; 
    673669 
    674     TMdaAudioDataSettings settings; 
    675     TInt clockRateCap, channelCountCap; 
    676  
    677     clockRateCap = get_clock_rate_cap(clock_rate); 
    678     channelCountCap = get_channel_cap(channel_count); 
    679  
    680670    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); 
    681     PJ_ASSERT_RETURN(clockRateCap != 0, PJ_EINVAL); 
    682     PJ_ASSERT_RETURN(channelCountCap != 0, PJ_EINVAL); 
     671    PJ_ASSERT_RETURN(get_clock_rate_cap(clock_rate) != 0, PJ_EINVAL); 
     672    PJ_ASSERT_RETURN(get_channel_cap(channel_count) != 0, PJ_EINVAL); 
    683673 
    684674    // Create the input stream. 
     
    708698    pjmedia_snd_stream *strm; 
    709699 
     700    if (index == -1) index = 0; 
     701     
    710702    PJ_ASSERT_RETURN(index == 0, PJ_EINVAL); 
    711703    PJ_ASSERT_RETURN(clock_rate && channel_count && samples_per_frame && 
     
    724716    strm->samples_per_frame = samples_per_frame; 
    725717 
    726     TMdaAudioDataSettings settings; 
    727     TInt clockRateCap, channelCountCap; 
    728  
    729     clockRateCap = get_clock_rate_cap(clock_rate); 
    730     channelCountCap = get_channel_cap(channel_count); 
    731  
    732718    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); 
    733     PJ_ASSERT_RETURN(clockRateCap != 0, PJ_EINVAL); 
    734     PJ_ASSERT_RETURN(channelCountCap != 0, PJ_EINVAL); 
     719    PJ_ASSERT_RETURN(get_clock_rate_cap(clock_rate) != 0, PJ_EINVAL); 
     720    PJ_ASSERT_RETURN(get_channel_cap(channel_count) != 0, PJ_EINVAL); 
    735721 
    736722    // Create the output stream. 
     
    761747    pjmedia_snd_stream *strm; 
    762748 
     749    if (rec_id == -1) rec_id = 0; 
     750    if (play_id == -1) play_id = 0; 
     751     
    763752    PJ_ASSERT_RETURN(rec_id == 0 && play_id == 0, PJ_EINVAL); 
    764753    PJ_ASSERT_RETURN(clock_rate && channel_count && samples_per_frame && 
     
    778767    strm->samples_per_frame = samples_per_frame; 
    779768 
    780     TMdaAudioDataSettings settings; 
    781     TInt clockRateCap, channelCountCap; 
    782  
    783     clockRateCap = get_clock_rate_cap(clock_rate); 
    784     channelCountCap = get_channel_cap(channel_count); 
    785  
    786769    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); 
    787     PJ_ASSERT_RETURN(clockRateCap != 0, PJ_EINVAL); 
    788     PJ_ASSERT_RETURN(channelCountCap != 0, PJ_EINVAL); 
     770    PJ_ASSERT_RETURN(get_clock_rate_cap(clock_rate) != 0, PJ_EINVAL); 
     771    PJ_ASSERT_RETURN(get_channel_cap(channel_count) != 0, PJ_EINVAL); 
    789772 
    790773    // Create the output stream. 
     
    796779    } 
    797780 
     781    // Create the input stream. 
     782    TRAPD(err1, strm->inEngine = CPjAudioInputEngine::NewL(strm, rec_cb,  
     783                                                           user_data)); 
     784    if (err1 != KErrNone) { 
     785        strm->inEngine = NULL; 
     786        delete strm->outEngine; 
     787        strm->outEngine = NULL; 
     788        pj_pool_release(pool);   
     789        return PJ_RETURN_OS_ERROR(err1); 
     790    } 
     791 
    798792    // Done. 
    799793    *p_snd_strm = strm; 
     
    807801     
    808802    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
     803     
     804    if (stream->outEngine) { 
     805        status = stream->outEngine->StartPlay(); 
     806        if (status != PJ_SUCCESS) 
     807            return status; 
     808    } 
    809809     
    810810    if (stream->inEngine) { 
     
    814814    } 
    815815         
    816     if (stream->outEngine) { 
    817         status = stream->outEngine->StartPlay(); 
    818         if (status != PJ_SUCCESS) 
    819             return status; 
    820     } 
    821      
    822816    return PJ_SUCCESS; 
    823817} 
Note: See TracChangeset for help on using the changeset viewer.