Ignore:
Timestamp:
Feb 5, 2009 10:59:14 AM (13 years ago)
Author:
nanang
Message:
  • Added new API for sound & sound port to create/open sound device with extended setting, to allow opening sound device with non-PCM format and other settings.
  • Updated symbian_ua/ua.cpp to be able to reopen sound device when audio stream session is using non-PCM data/passthrough codec.
  • Updated stream.c to allow it works with non-PCM data.
  • Added PCMU/A frames processing into non-PCM play/record callbacks in symbian_audio_aps.cpp.
  • Added passthrough codec init/deinitialization in pjsua-lib.
  • Added a new pjmedia_frame_ext helper function, pjmedia_frame_ext_pop_subframes, to pop-out/remove some subframes.
  • Other minor updates/fixes.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/sound_port.c

    r2394 r2438  
    3636//#define TEST_OVERFLOW_UNDERFLOW 
    3737 
    38 enum 
    39 { 
    40     PJMEDIA_PLC_ENABLED     = 1, 
    41 }; 
    42  
    43 //#define DEFAULT_OPTIONS       PJMEDIA_PLC_ENABLED 
    44 #define DEFAULT_OPTIONS     0 
    45  
    4638 
    4739struct pjmedia_snd_port 
     
    5244    pjmedia_dir          dir; 
    5345    pjmedia_port        *port; 
    54     unsigned             options; 
    5546 
    5647    pjmedia_echo_state  *ec_state; 
     
    6758    unsigned             samples_per_frame; 
    6859    unsigned             bits_per_sample; 
     60    pjmedia_snd_setting  setting; 
    6961 
    7062#if PJMEDIA_SOUND_USE_DELAYBUF 
     
    245237 
    246238/* 
     239 * The callback called by sound player when it needs more samples to be 
     240 * played. This version is for non-PCM data. 
     241 */ 
     242static pj_status_t play_cb_ext(/* in */   void *user_data, 
     243                               /* in */   pj_uint32_t timestamp, 
     244                               /* out */  void *output, 
     245                               /* out */  unsigned size) 
     246{ 
     247    pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
     248    pjmedia_port *port; 
     249    pjmedia_frame *frame = (pjmedia_frame*) output; 
     250    pj_status_t status; 
     251 
     252    PJ_UNUSED_ARG(size); 
     253    PJ_UNUSED_ARG(timestamp); 
     254 
     255    /* We're risking accessing the port without holding any mutex. 
     256     * It's possible that port is disconnected then destroyed while 
     257     * we're trying to access it. 
     258     * But in the name of performance, we'll try this approach until 
     259     * someone complains when it crashes. 
     260     */ 
     261    port = snd_port->port; 
     262    if (port == NULL) { 
     263        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     264        return PJ_SUCCESS; 
     265    } 
     266 
     267    status = pjmedia_port_get_frame(port, frame); 
     268 
     269    return status; 
     270} 
     271 
     272 
     273/* 
     274 * The callback called by sound recorder when it has finished capturing a 
     275 * frame. This version is for non-PCM data. 
     276 */ 
     277static pj_status_t rec_cb_ext(/* in */   void *user_data, 
     278                              /* in */   pj_uint32_t timestamp, 
     279                              /* in */   void *input, 
     280                              /* in*/    unsigned size) 
     281{ 
     282    pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
     283    pjmedia_port *port; 
     284    pjmedia_frame *frame = (pjmedia_frame*)input; 
     285 
     286    PJ_UNUSED_ARG(size); 
     287    PJ_UNUSED_ARG(timestamp); 
     288 
     289    /* We're risking accessing the port without holding any mutex. 
     290     * It's possible that port is disconnected then destroyed while 
     291     * we're trying to access it. 
     292     * But in the name of performance, we'll try this approach until 
     293     * someone complains when it crashes. 
     294     */ 
     295    port = snd_port->port; 
     296    if (port == NULL) 
     297        return PJ_SUCCESS; 
     298 
     299    pjmedia_port_put_frame(port, frame); 
     300 
     301    return PJ_SUCCESS; 
     302} 
     303 
     304/* 
    247305 * Start the sound stream. 
    248306 * This may be called even when the sound stream has already been started. 
     
    251309                                       pjmedia_snd_port *snd_port ) 
    252310{ 
     311    pjmedia_snd_rec_cb snd_rec_cb; 
     312    pjmedia_snd_play_cb snd_play_cb; 
    253313    pj_status_t status; 
    254314 
     
    257317        return PJ_SUCCESS; 
    258318 
    259     /* Open sound stream. */ 
    260     if (snd_port->dir == PJMEDIA_DIR_CAPTURE) { 
    261         status = pjmedia_snd_open_rec( snd_port->rec_id,  
    262                                        snd_port->clock_rate, 
    263                                        snd_port->channel_count, 
    264                                        snd_port->samples_per_frame, 
    265                                        snd_port->bits_per_sample, 
    266                                        &rec_cb, 
    267                                        snd_port, 
    268                                        &snd_port->snd_stream); 
    269  
    270     } else if (snd_port->dir == PJMEDIA_DIR_PLAYBACK) { 
    271         status = pjmedia_snd_open_player( snd_port->play_id,  
    272                                           snd_port->clock_rate, 
    273                                           snd_port->channel_count, 
    274                                           snd_port->samples_per_frame, 
    275                                           snd_port->bits_per_sample, 
    276                                           &play_cb, 
    277                                           snd_port, 
    278                                           &snd_port->snd_stream); 
    279  
    280     } else if (snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK) { 
    281         status = pjmedia_snd_open( snd_port->rec_id,  
    282                                    snd_port->play_id, 
    283                                    snd_port->clock_rate, 
    284                                    snd_port->channel_count, 
    285                                    snd_port->samples_per_frame, 
    286                                    snd_port->bits_per_sample, 
    287                                    &rec_cb, 
    288                                    &play_cb, 
    289                                    snd_port, 
    290                                    &snd_port->snd_stream); 
     319    PJ_ASSERT_RETURN(snd_port->dir == PJMEDIA_DIR_CAPTURE || 
     320                     snd_port->dir == PJMEDIA_DIR_PLAYBACK || 
     321                     snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK, 
     322                     PJ_EBUG); 
     323 
     324    if (snd_port->setting.format.u32 == 0 || 
     325        snd_port->setting.format.u32 == PJMEDIA_FOURCC_L16) 
     326    { 
     327        snd_rec_cb = &rec_cb; 
     328        snd_play_cb = &play_cb; 
    291329    } else { 
    292         pj_assert(!"Invalid dir"); 
    293         status = PJ_EBUG; 
    294     } 
     330        snd_rec_cb = &rec_cb_ext; 
     331        snd_play_cb = &play_cb_ext; 
     332    } 
     333 
     334    status = pjmedia_snd_open2( snd_port->dir, 
     335                                snd_port->rec_id,  
     336                                snd_port->play_id, 
     337                                snd_port->clock_rate, 
     338                                snd_port->channel_count, 
     339                                snd_port->samples_per_frame, 
     340                                snd_port->bits_per_sample, 
     341                                snd_rec_cb, 
     342                                snd_play_cb, 
     343                                snd_port, 
     344                                &snd_port->setting, 
     345                                &snd_port->snd_stream); 
    295346 
    296347    if (status != PJ_SUCCESS) 
     
    299350 
    300351#ifdef SIMULATE_LOST_PCT 
    301     snd_port->options |= PJMEDIA_PLC_ENABLED; 
     352    snd_port->setting.plc = PJ_TRUE; 
    302353#endif 
    303354 
     
    307358     */ 
    308359    if ((snd_port->dir & PJMEDIA_DIR_PLAYBACK) && 
    309         (snd_port->options & PJMEDIA_PLC_ENABLED))  
     360        (snd_port->setting.plc))  
    310361    { 
    311362        status = pjmedia_plc_create(pool, snd_port->clock_rate,  
     
    374425    pjmedia_snd_port *snd_port; 
    375426 
     427    PJ_UNUSED_ARG(options); 
     428 
    376429    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
    377430 
     
    382435    snd_port->play_id = play_id; 
    383436    snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    384     snd_port->options = options | DEFAULT_OPTIONS; 
    385437    snd_port->clock_rate = clock_rate; 
    386438    snd_port->channel_count = channel_count; 
     
    429481    pjmedia_snd_port *snd_port; 
    430482 
     483    PJ_UNUSED_ARG(options); 
     484 
    431485    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
    432486 
     
    436490    snd_port->rec_id = dev_id; 
    437491    snd_port->dir = PJMEDIA_DIR_CAPTURE; 
    438     snd_port->options = options | DEFAULT_OPTIONS; 
    439492    snd_port->clock_rate = clock_rate; 
    440493    snd_port->channel_count = channel_count; 
     
    466519    pjmedia_snd_port *snd_port; 
    467520 
     521    PJ_UNUSED_ARG(options); 
     522 
    468523    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
    469524 
     
    473528    snd_port->play_id = dev_id; 
    474529    snd_port->dir = PJMEDIA_DIR_PLAYBACK; 
    475     snd_port->options = options | DEFAULT_OPTIONS; 
    476530    snd_port->clock_rate = clock_rate; 
    477531    snd_port->channel_count = channel_count; 
     
    486540     */ 
    487541    return start_sound_device( pool, snd_port ); 
     542} 
     543 
     544 
     545/* 
     546 * Create bidirectional port. 
     547 */ 
     548PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
     549                                             pjmedia_dir dir, 
     550                                             int rec_id, 
     551                                             int play_id, 
     552                                             unsigned clock_rate, 
     553                                             unsigned channel_count, 
     554                                             unsigned samples_per_frame, 
     555                                             unsigned bits_per_sample, 
     556                                             const pjmedia_snd_setting *setting, 
     557                                             pjmedia_snd_port **p_port) 
     558{ 
     559    pjmedia_snd_port *snd_port; 
     560 
     561    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
     562 
     563    snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 
     564    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
     565 
     566    snd_port->dir = dir; 
     567    snd_port->rec_id = rec_id; 
     568    snd_port->play_id = play_id; 
     569    snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     570    snd_port->clock_rate = clock_rate; 
     571    snd_port->channel_count = channel_count; 
     572    snd_port->samples_per_frame = samples_per_frame; 
     573    snd_port->bits_per_sample = bits_per_sample; 
     574    snd_port->setting = *setting; 
     575     
     576#if PJMEDIA_SOUND_USE_DELAYBUF 
     577    if (snd_port->setting.format.u32 == 0 || 
     578        snd_port->setting.format.u32 == PJMEDIA_FOURCC_L16)  
     579    { 
     580        pj_status_t status; 
     581        unsigned ptime; 
     582     
     583        ptime = samples_per_frame * 1000 / (clock_rate * channel_count); 
     584     
     585        status = pjmedia_delay_buf_create(pool, "snd_buff",  
     586                                          clock_rate, samples_per_frame, 
     587                                          channel_count, 
     588                                          PJMEDIA_SOUND_BUFFER_COUNT * ptime, 
     589                                          0, &snd_port->delay_buf); 
     590        PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     591    } 
     592#endif 
     593 
     594    *p_port = snd_port; 
     595 
     596 
     597    /* Start sound device immediately. 
     598     * If there's no port connected, the sound callback will return 
     599     * empty signal. 
     600     */ 
     601    return start_sound_device( pool, snd_port ); 
     602 
    488603} 
    489604 
Note: See TracChangeset for help on using the changeset viewer.