Changeset 2438


Ignore:
Timestamp:
Feb 5, 2009 10:59:14 AM (11 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.
Location:
pjproject/branches/projects/aps-direct
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/build.symbian/bld.inf

    r2434 r2438  
    2121libgsmcodec.mmp 
    2222libspeexcodec.mmp 
     23libpassthroughcodec.mmp 
    2324 
    2425/* Sound device impl */ 
  • pjproject/branches/projects/aps-direct/build.symbian/symbian_ua.mmp

    r2434 r2438  
    3535STATICLIBRARY           pjnath.lib pjlib_util.lib pjlib.lib 
    3636STATICLIBRARY           libsrtp.lib 
    37 STATICLIBRARY           libgsmcodec.lib libspeexcodec.lib 
     37STATICLIBRARY           libgsmcodec.lib libspeexcodec.lib libpassthroughcodec.lib 
    3838STATICLIBRARY           symbian_audio.lib 
    3939 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-codec.h

    r2394 r2438  
    3232#include <pjmedia-codec/g722.h> 
    3333#include <pjmedia-codec/ipp_codecs.h> 
     34#include <pjmedia-codec/passthrough.h> 
    3435 
    3536 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-codec/config.h

    r2436 r2438  
    218218#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU 
    219219#   define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU   1 
    220 #endif 
    221  
    222 #ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_G729 
     220#   undef PJMEDIA_HAS_G711_CODEC 
     221#endif 
     222 
     223#ifndef PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA 
    223224#   define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA   1 
     225#   undef PJMEDIA_HAS_G711_CODEC 
    224226#endif 
    225227 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/port.h

    r2437 r2438  
    360360         
    361361/** 
     362 * Pop out first n subframes from #pjmedia_frame_ext. 
     363 * 
     364 * @param frm               The #pjmedia_frame_ext. 
     365 * @param n                 Number of first subframes to be popped out. 
     366 * 
     367 * @return                  PJ_SUCCESS, or PJ_ENOTFOUND if frame is empty. 
     368 */ 
     369PJ_INLINE(pj_status_t)  
     370          pjmedia_frame_ext_pop_subframes(pjmedia_frame_ext *frm, unsigned n) 
     371{ 
     372    pjmedia_frame_ext_subframe *sf; 
     373    pj_uint8_t *move_src; 
     374    unsigned move_len; 
     375 
     376    if (frm->subframe_cnt <= n) { 
     377        frm->subframe_cnt = 0; 
     378        frm->samples_cnt = 0; 
     379        return PJ_SUCCESS; 
     380    } 
     381 
     382    move_src = (pj_uint8_t*)pjmedia_frame_ext_get_subframe(frm, n); 
     383    sf = pjmedia_frame_ext_get_subframe(frm, frm->subframe_cnt-1); 
     384    move_len = (pj_uint8_t*)sf - move_src + sf->bitlen/8; 
     385    if (sf->bitlen % 8 != 0) 
     386        ++move_len; 
     387    pj_memmove((pj_uint8_t*)frm+sizeof(pjmedia_frame_ext),  
     388               move_src, move_len); 
     389             
     390    frm->samples_cnt = (pj_uint16_t) 
     391                   (frm->samples_cnt - n*frm->samples_cnt/frm->subframe_cnt); 
     392    frm->subframe_cnt = (pj_uint16_t) (frm->subframe_cnt - n); 
     393 
     394    return PJ_SUCCESS; 
     395} 
     396         
     397/** 
    362398 * Port interface. 
    363399 */ 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/sound.h

    r2394 r2438  
    9292    unsigned    play_latency;       /**< Playback latency, in samples.      */ 
    9393} pjmedia_snd_stream_info; 
     94 
     95 
     96/**  
     97 * Stream setting for opening sound device with non-PCM data. 
     98 */ 
     99typedef struct pjmedia_snd_setting 
     100{ 
     101    pjmedia_fourcc      format;   /**< Format (FourCC ID).          */  
     102    pj_uint32_t         bitrate;  /**< Bitrate (bps).               */ 
     103    pj_uint32_t         mode;     /**< Mode, e.g: iLBC format has 
     104                                       20ms or 30ms frame size.     */ 
     105    pj_bool_t           plc;      /**< PLC enabled/disabled.        */ 
     106    pj_bool_t           vad;      /**< VAD enabled/disabled.        */ 
     107    pj_bool_t           cng;      /**< CNG enabled/disabled.        */ 
     108    pj_bool_t           loudspk;  /**< Audio routed to loudspeaker. */ 
     109} pjmedia_snd_setting; 
    94110 
    95111 
     
    274290 
    275291/** 
     292 * Create sound stream for capturing audio and/or audio playback, from the  
     293 * same device. This also allows opening sound stream with extended settings,  
     294 * e.g: stream format, see #pjmedia_snd_setting. 
     295 * 
     296 * @param dir               Sound stream direction. 
     297 * @param rec_id            Device index for recorder/capture stream, or 
     298 *                          -1 to use the first capable device. 
     299 * @param play_id           Device index for playback stream, or -1 to use  
     300 *                          the first capable device. 
     301 * @param clock_rate        Sound device's clock rate to set. 
     302 * @param channel_count     Set number of channels, 1 for mono, or 2 for 
     303 *                          stereo. The channel count determines the format 
     304 *                          of the frame. 
     305 * @param samples_per_frame Number of samples per frame. 
     306 * @param bits_per_sample   Set the number of bits per sample. The normal  
     307 *                          value for this parameter is 16 bits per sample. 
     308 * @param rec_cb            Callback to handle captured audio samples. 
     309 * @param play_cb           Callback to be called when the sound player needs 
     310 *                          more audio samples to play. 
     311 * @param user_data         User data to be associated with the stream. 
     312 * @param setting           Sound device extended setting. 
     313 * @param p_snd_strm        Pointer to receive the stream instance. 
     314 * 
     315 * @return                  PJ_SUCCESS on success. 
     316 */ 
     317PJ_DECL(pj_status_t) pjmedia_snd_open2( pjmedia_dir dir, 
     318                                        int rec_id, 
     319                                        int play_id, 
     320                                        unsigned clock_rate, 
     321                                        unsigned channel_count, 
     322                                        unsigned samples_per_frame, 
     323                                        unsigned bits_per_sample, 
     324                                        pjmedia_snd_rec_cb rec_cb, 
     325                                        pjmedia_snd_play_cb play_cb, 
     326                                        void *user_data, 
     327                                        const pjmedia_snd_setting *setting, 
     328                                        pjmedia_snd_stream **p_snd_strm); 
     329 
     330 
     331/** 
    276332 * Get information about live stream. 
    277333 * 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/sound_port.h

    r2394 r2438  
    160160                                                    unsigned options, 
    161161                                                    pjmedia_snd_port **p_port); 
    162                                                
     162 
     163 
     164/** 
     165 * Create unidirectional or bidirectional sound port. This also allows 
     166 * creating sound port with extended settings, e.g: audio format, see  
     167 * #pjmedia_snd_setting. 
     168 * 
     169 * @param pool              Pool to allocate sound port structure. 
     170 * @param dir               Sound device direction. 
     171 * @param rec_id            Device index for recorder/capture stream, or 
     172 *                          -1 to use the first capable device. 
     173 * @param play_id           Device index for playback stream, or -1 to use  
     174 *                          the first capable device. 
     175 * @param clock_rate        Sound device's clock rate to set. 
     176 * @param channel_count     Set number of channels, 1 for mono, or 2 for 
     177 *                          stereo. The channel count determines the format 
     178 *                          of the frame. 
     179 * @param samples_per_frame Number of samples per frame. 
     180 * @param bits_per_sample   Set the number of bits per sample. The normal  
     181 *                          value for this parameter is 16 bits per sample. 
     182 * @param setting           Sound device extended settings, see  
     183 *                          #pjmedia_snd_setting. 
     184 * @param p_port            Pointer to receive the sound device port instance. 
     185 * 
     186 * @return                  PJ_SUCCESS on success, or the appropriate error 
     187 *                          code. 
     188 */ 
     189PJ_DECL(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
     190                                              pjmedia_dir dir, 
     191                                              int rec_id, 
     192                                              int play_id, 
     193                                              unsigned clock_rate, 
     194                                              unsigned channel_count, 
     195                                              unsigned samples_per_frame, 
     196                                              unsigned bits_per_sample, 
     197                                              const pjmedia_snd_setting *setting, 
     198                                              pjmedia_snd_port **p_port); 
     199 
    163200 
    164201/** 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/symbian_sound_aps.h

    r2434 r2438  
    5454 * 
    5555 * @param stream        The sound device stream, the stream should be started  
    56  *                      before calling this function. This param can be NULL 
    57  *                      to set the behaviour of next opened stream. 
     56 *                      before calling this function. 
    5857 * @param active        Specify PJ_TRUE to activate loudspeaker, and PJ_FALSE 
    5958 *                      otherwise. 
     
    6564                                                pj_bool_t active); 
    6665 
    67  
    68 /** 
    69  * Set a codec and its settings to be used on the next sound device session. 
    70  * 
    71  * @param setting       APS sound device setting, see @pjmedia_snd_aps_setting. 
    72  * 
    73  * @return              PJ_SUCCESS on success. 
    74  */ 
    75 PJ_DECL(pj_status_t) pjmedia_snd_aps_modify_setting( 
    76                                     const pjmedia_snd_aps_setting *setting); 
    77  
    78  
    7966PJ_END_DECL 
    8067 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/types.h

    r2434 r2438  
    191191 * FourCC packing macro. 
    192192 */ 
    193 #define PJMEDIA_FOURCC_PACK(C1, C2, C3, C4) ( C1<<24 | C2<<16 | C3<<8 | C4 ) 
     193#define PJMEDIA_FOURCC_PACK(C1, C2, C3, C4) ( C4<<24 | C3<<16 | C2<<8 | C1 ) 
    194194 
    195195/** 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-codec/passthrough.c

    r2436 r2438  
    460460                                    codec_desc[i].channel_count /  
    461461                                    codec_desc[i].clock_rate); 
    462             attr->info.format.u32 = codec_desc[i].format.u32; 
     462            attr->info.format = codec_desc[i].format; 
    463463 
    464464            /* Default flags. */ 
    465465            attr->setting.frm_per_pkt = codec_desc[i].frm_per_pkt; 
    466             attr->setting.plc = 1; 
     466            attr->setting.plc = 0; 
    467467            attr->setting.penh= 0; 
    468             attr->setting.vad = 1; 
     468            attr->setting.vad = 0; 
    469469            attr->setting.cng = attr->setting.vad; 
    470470            attr->setting.dec_fmtp = codec_desc[i].dec_fmtp; 
     
    720720        frames[count].timestamp.u64 = ts->u64 + count*desc->samples_per_frame; 
    721721 
    722         pkt = ((char*)pkt) + codec_data->avg_frame_size; 
     722        pkt = (pj_uint8_t*)pkt + codec_data->avg_frame_size; 
    723723        pkt_size -= codec_data->avg_frame_size; 
    724724 
     
    800800    pjmedia_frame_ext *output_ = (pjmedia_frame_ext*) output; 
    801801 
    802     /* Check if input is formatted in pjmedia_frame */ 
    803     pj_assert(input && input->type == PJMEDIA_FRAME_TYPE_AUDIO); 
     802    pj_assert(input && input->size > 0); 
    804803 
    805804#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR 
     
    818817    } 
    819818#endif 
    820  
    821     pj_bzero(output_, sizeof(pjmedia_frame_ext)); 
    822     output_->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
    823      
    824     if (input && input->size > 0) { 
    825         PJ_ASSERT_RETURN(output_buf_len >= sizeof(pjmedia_frame_ext) + 
    826                                            sizeof(pjmedia_frame_ext_subframe) + 
    827                                            input->size, 
    828                          PJMEDIA_CODEC_EFRMTOOSHORT); 
    829  
    830         pjmedia_frame_ext_append_subframe(output_, input->buf,  
    831                                           (pj_uint16_t)(input->size << 3), 
    832                                           (pj_uint16_t)desc->samples_per_frame); 
    833     } 
     819    /* 
     820    PJ_ASSERT_RETURN(output_buf_len >= sizeof(pjmedia_frame_ext) + 
     821                                       sizeof(pjmedia_frame_ext_subframe) + 
     822                                       input->size, 
     823                     PJMEDIA_CODEC_EFRMTOOSHORT); 
     824     */ 
     825 
     826    pjmedia_frame_ext_append_subframe(output_, input->buf,  
     827                                      (pj_uint16_t)(input->size << 3), 
     828                                      (pj_uint16_t)desc->samples_per_frame); 
    834829 
    835830    return PJ_SUCCESS; 
     
    843838                                  struct pjmedia_frame *output) 
    844839{ 
    845     return codec_decode(codec, NULL, output_buf_len, output); 
     840    codec_private_t *codec_data = (codec_private_t*) codec->codec_data; 
     841    struct codec_desc *desc = &codec_desc[codec_data->codec_idx]; 
     842    pjmedia_frame_ext *output_ = (pjmedia_frame_ext*) output; 
     843 
     844    PJ_UNUSED_ARG(output_buf_len); 
     845 
     846    pjmedia_frame_ext_append_subframe(output_, NULL, 0, 
     847                                      (pj_uint16_t)desc->samples_per_frame); 
     848 
     849    return PJ_SUCCESS; 
    846850} 
    847851 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conf_switch.c

    r2437 r2438  
    997997                                           (pjmedia_frame*)f_dst); 
    998998 
    999                     /* Update TX timestamp. */ 
    1000                     pj_add_timestamp32(&cport_dst->ts_tx,  
    1001                                        cport_dst->samples_per_frame); 
    1002  
    1003999                    /* Reset TX buffer. */ 
    10041000                    f_dst->subframe_cnt = 0; 
    10051001                    f_dst->samples_cnt = 0; 
    10061002                } 
     1003 
     1004                /* Update TX timestamp. */ 
     1005                pj_add_timestamp32(&cport_dst->ts_tx,  
     1006                                   cport_dst->samples_per_frame); 
     1007 
    10071008            } 
    10081009        } 
     
    10371038                    pjmedia_port_put_frame(cport_dst->port, frm_dst); 
    10381039 
    1039                     /* Update TX timestamp. */ 
    1040                     pj_add_timestamp32(&cport_dst->ts_tx,  
    1041                                        cport_dst->samples_per_frame); 
    1042                   
    10431040                    /* Reset TX buffer. */ 
    10441041                    frm_dst->size = 0; 
    10451042                } 
     1043 
     1044                /* Update TX timestamp. */ 
     1045                pj_add_timestamp32(&cport_dst->ts_tx,  
     1046                                   cport_dst->samples_per_frame); 
    10461047            } 
    10471048        } 
     
    10631064                frm_dst->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    10641065                frm_dst->size = cport_dst->samples_per_frame << 1; 
    1065                 if (cport_dst->port) 
     1066                if (cport_dst->port) { 
    10661067                    pjmedia_port_put_frame(cport_dst->port, frm_dst); 
     1068 
     1069                    /* Reset TX buffer. */ 
     1070                    frm_dst->size = 0; 
     1071                } 
    10671072 
    10681073                /* Update TX timestamp. */ 
    10691074                pj_add_timestamp32(&cport_dst->ts_tx,  
    10701075                                   cport_dst->samples_per_frame); 
    1071  
    1072                 /* Reset TX buffer. */ 
    1073                 frm_dst->size = 0; 
    10741076            } 
    10751077        } else { 
     
    10801082                pjmedia_frame_ext_append_subframe(f_dst, NULL, 0, (pj_uint16_t) 
    10811083                                                  (cport_dst->samples_per_frame- 
    1082                                                   f_dst->samples_cnt)); 
    1083                 if (cport_dst->port) 
     1084                                                   f_dst->samples_cnt)); 
     1085                if (cport_dst->port) { 
    10841086                    pjmedia_port_put_frame(cport_dst->port, frm_dst); 
     1087 
     1088                    /* Reset TX buffer. */ 
     1089                    f_dst->subframe_cnt = 0; 
     1090                    f_dst->samples_cnt = 0; 
     1091                } 
    10851092 
    10861093                /* Update TX timestamp. */ 
    10871094                pj_add_timestamp32(&cport_dst->ts_tx,  
    10881095                                   cport_dst->samples_per_frame); 
    1089  
    1090                 /* Reset TX buffer. */ 
    1091                 f_dst->subframe_cnt = 0; 
    1092                 f_dst->samples_cnt = 0; 
    10931096            } 
    10941097        } 
     
    10961099        /* Synchronize clock. */ 
    10971100        while (pj_cmp_timestamp(&cport_dst->ts_clock,  
    1098                                 &cport_dst->ts_tx) >= 0) 
     1101                                &cport_dst->ts_tx) > 0) 
    10991102        { 
    1100             if (cport_dst->port) { 
    1101                 frm_dst->type = PJMEDIA_FRAME_TYPE_NONE; 
    1102                 frm_dst->timestamp = cport_dst->ts_tx; 
     1103            frm_dst->type = PJMEDIA_FRAME_TYPE_NONE; 
     1104            frm_dst->timestamp = cport_dst->ts_tx; 
     1105            if (cport_dst->port) 
    11031106                pjmedia_port_put_frame(cport_dst->port, frm_dst); 
    1104             } 
     1107 
     1108            /* Update TX timestamp. */ 
    11051109            pj_add_timestamp32(&cport_dst->ts_tx, cport_dst->samples_per_frame); 
    11061110        } 
     
    12351239            cport->tx_level = 0; 
    12361240 
    1237             while (pj_cmp_timestamp(&cport->ts_clock, &cport->ts_tx) >= 0) 
     1241            while (pj_cmp_timestamp(&cport->ts_clock, &cport->ts_tx) > 0) 
    12381242            { 
    12391243                if (cport->tx_setting == PJMEDIA_PORT_ENABLE) { 
     
    12651269            pj_uint16_t samples_per_subframe; 
    12661270             
     1271            if (f_src_->samples_cnt < this_cport->samples_per_frame) { 
     1272                pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext)); 
     1273                frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     1274                break; 
     1275            } 
     1276 
    12671277            f_dst->samples_cnt = 0; 
    12681278            f_dst->subframe_cnt = 0; 
     
    12701280            samples_per_subframe = f_src_->samples_cnt / f_src_->subframe_cnt; 
    12711281 
     1282 
    12721283            while (f_dst->samples_cnt < this_cport->samples_per_frame) { 
    12731284                sf = pjmedia_frame_ext_get_subframe(f_src_, i++); 
     1285                pj_assert(sf); 
    12741286                pjmedia_frame_ext_append_subframe(f_dst, sf->data, sf->bitlen, 
    12751287                                                  samples_per_subframe); 
     
    12771289 
    12781290            /* Shift left TX buffer. */ 
    1279             sf = pjmedia_frame_ext_get_subframe(f_src_, i); 
    1280             if (sf) { 
    1281                 pjmedia_frame_ext_subframe *sf_end; 
    1282                 unsigned len; 
    1283  
    1284                 sf_end = pjmedia_frame_ext_get_subframe(f_src_,  
    1285                                                     f_src_->subframe_cnt -1); 
    1286                 len = (pj_uint8_t*)sf_end - (pj_uint8_t*)sf + sf_end->bitlen/8; 
    1287                 if (sf_end->bitlen % 8 != 0) 
    1288                     ++len; 
    1289                 pj_memmove(this_cport->tx_buf + sizeof(pjmedia_frame_ext), sf, 
    1290                            len); 
     1291            pjmedia_frame_ext_pop_subframes(f_src_, i); 
     1292 
     1293        } else if (f_src->type == PJMEDIA_FRAME_TYPE_AUDIO) { 
     1294            if ((f_src->size>>1) < this_cport->samples_per_frame) { 
     1295                pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext)); 
     1296                frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     1297                break; 
    12911298            } 
    1292             f_src_->samples_cnt = f_src_->samples_cnt -  
    1293                                   (pj_uint16_t)(i * samples_per_subframe); 
    1294             f_src_->subframe_cnt = f_src_->subframe_cnt - (pj_uint16_t)i; 
    1295  
    1296         } else if (f_src->type == PJMEDIA_FRAME_TYPE_AUDIO) { 
     1299 
    12971300            pjmedia_copy_samples((pj_int16_t*)frame->buf,  
    12981301                                 (pj_int16_t*)f_src->buf,  
     
    13071310                                     this_cport->samples_per_frame, 
    13081311                                     f_src->size >> 1); 
     1312        } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
     1313            /* Reset TX buffer */ 
     1314            pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext)); 
     1315            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    13091316        } 
    13101317    } while (0); 
     
    13261333    unsigned j; 
    13271334    pj_int32_t level; 
    1328  
    1329     /* Check for correct size. */ 
    1330     PJ_ASSERT_RETURN( f->size == conf->samples_per_frame * 
    1331                                  conf->bits_per_sample / 8, 
    1332                       PJMEDIA_ENCSAMPLESPFRAME); 
    13331335 
    13341336    pj_add_timestamp32(&cport->ts_rx, cport->samples_per_frame); 
  • 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 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/stream.c

    r2394 r2438  
    411411 
    412412 
     413/* The other version of get_frame callback used when stream port format 
     414 * is non linear PCM. 
     415 */ 
     416static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame) 
     417{ 
     418    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     419    pjmedia_channel *channel = stream->dec; 
     420    pjmedia_frame_ext *f = (pjmedia_frame_ext*)frame; 
     421    unsigned samples_per_frame, samples_required; 
     422    pj_status_t status; 
     423 
     424    /* Return no frame if channel is paused */ 
     425    if (channel->paused) { 
     426        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     427        return PJ_SUCCESS; 
     428    } 
     429 
     430    /* Repeat get frame from the jitter buffer and decode the frame 
     431     * until we have enough frames according to codec's ptime. 
     432     */ 
     433 
     434    samples_required = stream->port.info.samples_per_frame; 
     435    samples_per_frame = stream->codec_param.info.frm_ptime * 
     436                        stream->codec_param.info.clock_rate * 
     437                        stream->codec_param.info.channel_cnt /  
     438                        1000; 
     439 
     440    pj_bzero(f, sizeof(pjmedia_frame_ext)); 
     441    f->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     442 
     443    while (f->samples_cnt < samples_required) { 
     444        char frame_type; 
     445        pj_size_t frame_size; 
     446        pj_uint32_t bit_info; 
     447 
     448        /* Lock jitter buffer mutex first */ 
     449        pj_mutex_lock( stream->jb_mutex ); 
     450 
     451        /* Get frame from jitter buffer. */ 
     452        pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size, 
     453                                &frame_type, &bit_info); 
     454         
     455        /* Unlock jitter buffer mutex. */ 
     456        pj_mutex_unlock( stream->jb_mutex ); 
     457 
     458        if (frame_type == PJMEDIA_JB_NORMAL_FRAME) { 
     459            /* Got "NORMAL" frame from jitter buffer */ 
     460            pjmedia_frame frame_in; 
     461 
     462            /* Decode */ 
     463            frame_in.buf = channel->out_pkt; 
     464            frame_in.size = frame_size; 
     465            frame_in.bit_info = bit_info; 
     466            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     467 
     468            status = stream->codec->op->decode( stream->codec, &frame_in, 
     469                                                0, frame); 
     470            if (status != PJ_SUCCESS) { 
     471                LOGERR_((port->info.name.ptr, "codec decode() error",  
     472                         status)); 
     473                pjmedia_frame_ext_append_subframe(f, NULL, 0, 
     474                                            (pj_uint16_t)samples_per_frame); 
     475            } 
     476        } else { 
     477            status = (*stream->codec->op->recover)(stream->codec, 
     478                                                   0, frame); 
     479            if (status != PJ_SUCCESS) { 
     480                pjmedia_frame_ext_append_subframe(f, NULL, 0, 
     481                                            (pj_uint16_t)samples_per_frame); 
     482            } 
     483 
     484            if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 
     485                PJ_LOG(1,(stream->port.info.name.ptr,  "Frame lost!")); 
     486            } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
     487                /* Jitter buffer is empty. Check if this is the first "empty"  
     488                 * state. 
     489                 */ 
     490                if (frame_type != stream->jb_last_frm) { 
     491                    pjmedia_jb_state jb_state; 
     492 
     493                    /* Report the state of jitter buffer */ 
     494                    pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     495                    PJ_LOG(1,(stream->port.info.name.ptr,  
     496                              "Jitter buffer empty (prefetch=%d)",  
     497                              jb_state.prefetch)); 
     498                } 
     499            } else { 
     500                pjmedia_jb_state jb_state; 
     501 
     502                /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */ 
     503                pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME); 
     504 
     505                /* Get the state of jitter buffer */ 
     506                pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     507 
     508                if (stream->jb_last_frm != frame_type) { 
     509                    PJ_LOG(1,(stream->port.info.name.ptr,  
     510                              "Jitter buffer is bufferring (prefetch=%d)", 
     511                              jb_state.prefetch)); 
     512                } 
     513            } 
     514        } 
     515 
     516        stream->jb_last_frm = frame_type; 
     517    } 
     518 
     519    return PJ_SUCCESS; 
     520} 
     521 
     522 
    413523/* 
    414524 * Transmit DTMF 
     
    689799    if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) 
    690800        ts_len = (frame->size >> 1) / stream->codec_param.info.channel_cnt; 
     801    else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) 
     802        ts_len = stream->port.info.samples_per_frame /  
     803                 stream->port.info.channel_count; 
    691804    else 
    692805        ts_len = 0; 
     
    755868    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
    756869               frame->buf == NULL && 
     870               (stream->port.info.format.u32 == 0 || 
     871                stream->port.info.format.u32 == PJMEDIA_FOURCC_L16) && 
    757872               (stream->dir & PJMEDIA_DIR_ENCODING) && 
    758873               stream->codec_param.info.frm_ptime * 
     
    14921607    stream->port.info.clock_rate = info->fmt.clock_rate; 
    14931608    stream->port.info.channel_count = info->fmt.channel_cnt; 
     1609    stream->port.info.format = info->param->info.format; 
    14941610    stream->port.port_data.pdata = stream; 
    1495     stream->port.put_frame = &put_frame; 
    1496     stream->port.get_frame = &get_frame; 
     1611    if (stream->port.info.format.u32 == 0 || 
     1612        stream->port.info.format.u32 == PJMEDIA_FOURCC_L16) 
     1613    { 
     1614        stream->port.put_frame = &put_frame; 
     1615        stream->port.get_frame = &get_frame; 
     1616    } else { 
     1617        stream->port.put_frame = &put_frame; 
     1618        stream->port.get_frame = &get_frame_ext; 
     1619    } 
    14971620 
    14981621 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/symbian_sound_aps.cpp

    r2434 r2438  
    1818 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1919 */ 
     20#include <pjmedia/sound.h> 
    2021#include <pjmedia/symbian_sound_aps.h> 
    21 #include <pjmedia/sound.h> 
    2222#include <pjmedia/alaw_ulaw.h> 
    2323#include <pjmedia/errno.h> 
     24#include <pjmedia/port.h> 
    2425#include <pj/assert.h> 
    2526#include <pj/log.h> 
     
    5960/* App UID to open global APS queues to communicate with the APS server. */ 
    6061extern TPtrC                APP_UID; 
    61  
    62 /* Default setting */ 
    63 static pjmedia_snd_aps_setting def_setting; 
    6462 
    6563/* APS G.711 frame length */ 
     
    8886    pjmedia_snd_play_cb  play_cb; 
    8987    void                *user_data; 
     88    pjmedia_snd_setting  setting; 
    9089 
    9190    // Audio engine 
     
    405404    // the client session. 
    406405    TTime start, now; 
    407     enum { APS_CLOSE_WAIT_TIME = 200 }; 
     406    enum { APS_CLOSE_WAIT_TIME = 200 }; /* in msecs */ 
     407     
    408408    start.UniversalTime(); 
    409     now.UniversalTime(); 
    410     while (now.MicroSecondsFrom(start) < APS_CLOSE_WAIT_TIME * 1000) { 
     409    do { 
    411410        pj_symbianos_poll(-1, APS_CLOSE_WAIT_TIME); 
    412411        now.UniversalTime(); 
    413     } 
     412    } while (now.MicroSecondsFrom(start) < APS_CLOSE_WAIT_TIME * 1000); 
    414413 
    415414    iSession.Close(); 
     
    618617    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
    619618 
     619    /* Buffer has to contain normal speech. */ 
    620620    pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0); 
    621621 
     
    660660    unsigned g711_frame_len = aps_g711_frame_len; 
    661661 
     662    /* Init buffer attributes and header. */ 
    662663    buf.iCommand = CQueueHandler::EAPSPlayData; 
    663664    buf.iStatus = 0; 
     
    697698static void RecCb(TAPSCommBuffer &buf, void *user_data) 
    698699{ 
     700    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
     701    pjmedia_frame_ext *frame = (pjmedia_frame_ext*) strm->rec_buf; 
     702    unsigned samples_processed = 0; 
     703 
     704    switch(strm->setting.format.u32) { 
     705     
     706    case PJMEDIA_FOURCC_G711U: 
     707    case PJMEDIA_FOURCC_G711A: 
     708        pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0); 
     709 
     710        /* Detect the recorder G.711 frame size, player frame size will follow 
     711         * this recorder frame size. 
     712         */ 
     713        if (aps_g711_frame_len == 0) { 
     714            aps_g711_frame_len = buf.iBuffer.Length() < 160? 80 : 160; 
     715            TRACE_((THIS_FILE, "Detected APS G.711 frame size = %u samples", 
     716                    aps_g711_frame_len)); 
     717        } 
     718         
     719        /* Convert APS buffer format into pjmedia_frame_ext. Whenever  
     720         * samples count in the frame is equal to stream's samples per frame, 
     721         * call parent stream callback. 
     722         */ 
     723        while (samples_processed < aps_g711_frame_len) { 
     724            unsigned tmp; 
     725            const pj_uint8_t *pb = (const pj_uint8_t*)buf.iBuffer.Ptr() + 2 + 
     726                                   samples_processed; 
     727 
     728            tmp = PJ_MIN(strm->samples_per_frame - frame->samples_cnt, 
     729                         aps_g711_frame_len - samples_processed); 
     730             
     731            pjmedia_frame_ext_append_subframe(frame, pb, tmp << 3, tmp); 
     732            samples_processed += tmp; 
     733 
     734            if (frame->samples_cnt == strm->samples_per_frame) { 
     735                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     736                strm->rec_cb(strm->user_data, 0, strm->rec_buf, 0); 
     737                frame->samples_cnt = 0; 
     738                frame->subframe_cnt = 0; 
     739            } 
     740        } 
     741        break; 
     742         
     743    default: 
     744        break; 
     745    } 
    699746} 
    700747 
    701748static void PlayCb(TAPSCommBuffer &buf, void *user_data) 
    702749{ 
     750    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
     751    pjmedia_frame_ext *frame = (pjmedia_frame_ext*) strm->play_buf; 
     752    unsigned g711_frame_len = aps_g711_frame_len; 
     753    unsigned samples_ready = 0; 
     754 
     755    /* Init buffer attributes and header. */ 
     756    buf.iCommand = CQueueHandler::EAPSPlayData; 
     757    buf.iStatus = 0; 
     758    buf.iBuffer.Zero(); 
     759 
     760    switch(strm->setting.format.u32) { 
     761     
     762    case PJMEDIA_FOURCC_G711U: 
     763    case PJMEDIA_FOURCC_G711A: 
     764        /* Add header. */ 
     765        buf.iBuffer.Append(1); 
     766        buf.iBuffer.Append(0); 
     767 
     768        /* Assume frame size is 10ms if frame size hasn't been known. */ 
     769        if (g711_frame_len == 0) 
     770            g711_frame_len = 80; 
     771         
     772        /* Call parent stream callback to get samples to play. */ 
     773        while (samples_ready < g711_frame_len) { 
     774            if (frame->samples_cnt == 0) { 
     775                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     776                strm->play_cb(strm->user_data, 0, strm->play_buf, 
     777                              strm->samples_per_frame<<1); 
     778                 
     779                pj_assert(frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED || 
     780                          frame->base.type == PJMEDIA_FRAME_TYPE_NONE); 
     781            } 
     782 
     783            if (frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) {  
     784                pjmedia_frame_ext_subframe *sf; 
     785                unsigned samples_cnt; 
     786                 
     787                sf = pjmedia_frame_ext_get_subframe(frame, 0); 
     788                samples_cnt = frame->samples_cnt / frame->subframe_cnt; 
     789                if (sf->data && sf->bitlen) 
     790                    buf.iBuffer.Append((TUint8*)sf->data, sf->bitlen>>3); 
     791                else  
     792                    buf.iBuffer.AppendFill(0, samples_cnt); 
     793                samples_ready += samples_cnt; 
     794                 
     795                pjmedia_frame_ext_pop_subframes(frame, 1); 
     796             
     797            } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
     798                buf.iBuffer.AppendFill(0, g711_frame_len - samples_ready); 
     799                samples_ready = g711_frame_len; 
     800                frame->samples_cnt = 0; 
     801                frame->subframe_cnt = 0; 
     802            } 
     803        } 
     804        break; 
     805         
     806    default: 
     807        break; 
     808    } 
     809     
     810    unsigned tes = buf.iBuffer.Length(); 
    703811} 
    704812 
     
    709817{ 
    710818    snd_pool_factory = factory; 
    711  
    712     def_setting.format.u32 = PJMEDIA_FOURCC_L16; 
    713     def_setting.mode = 0; 
    714     def_setting.bitrate = 128000; 
    715     def_setting.plc = PJ_FALSE; 
    716     def_setting.vad = PJ_FALSE; 
    717     def_setting.cng = PJ_FALSE; 
    718     def_setting.loudspk = PJ_FALSE; 
    719819 
    720820    return PJ_SUCCESS; 
     
    751851                              pjmedia_snd_play_cb play_cb, 
    752852                              void *user_data, 
     853                              const pjmedia_snd_setting *setting, 
    753854                              pjmedia_snd_stream **p_snd_strm) 
    754855{ 
    755856    pj_pool_t *pool; 
    756857    pjmedia_snd_stream *strm; 
    757     CPjAudioSetting setting; 
     858    CPjAudioSetting aps_setting; 
    758859    PjAudioCallback aps_rec_cb; 
    759860    PjAudioCallback aps_play_cb; 
     
    779880    strm->channel_count = channel_count; 
    780881    strm->samples_per_frame = samples_per_frame; 
     882    strm->setting = *setting; 
     883 
     884    if (strm->setting.format.u32 == 0) 
     885        strm->setting.format.u32 = PJMEDIA_FOURCC_L16; 
    781886 
    782887    /* Set audio engine settings. */ 
    783     if (def_setting.format.u32 == PJMEDIA_FOURCC_G711U || 
    784         def_setting.format.u32 == PJMEDIA_FOURCC_L16) 
     888    if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U || 
     889        strm->setting.format.u32 == PJMEDIA_FOURCC_L16) 
    785890    { 
    786         setting.fourcc = TFourCC(KMCPFourCCIdG711); 
     891        aps_setting.fourcc = TFourCC(KMCPFourCCIdG711); 
    787892    } else { 
    788         setting.fourcc = TFourCC(def_setting.format.u32); 
    789     } 
    790  
    791     if (def_setting.format.u32 == PJMEDIA_FOURCC_AMR) 
     893        aps_setting.fourcc = TFourCC(strm->setting.format.u32); 
     894    } 
     895 
     896    if (strm->setting.format.u32 == PJMEDIA_FOURCC_AMR) 
    792897    { 
    793         setting.mode = (TAPSCodecMode)def_setting.bitrate; 
    794     } else if (def_setting.format.u32 == PJMEDIA_FOURCC_G711U || 
    795                def_setting.format.u32 == PJMEDIA_FOURCC_L16   || 
    796               (def_setting.format.u32 == PJMEDIA_FOURCC_ILBC  && 
    797                def_setting.mode == 30)) 
     898        aps_setting.mode = (TAPSCodecMode)strm->setting.bitrate; 
     899    } else if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U || 
     900               strm->setting.format.u32 == PJMEDIA_FOURCC_L16   || 
     901              (strm->setting.format.u32 == PJMEDIA_FOURCC_ILBC  && 
     902               strm->setting.mode == 30)) 
    798903    { 
    799         setting.mode = EULawOr30ms; 
     904        aps_setting.mode = EULawOr30ms; 
    800905    } else { 
    801         setting.mode = EALawOr20ms; 
    802     } 
    803  
    804     setting.vad = def_setting.vad; 
    805     setting.plc = def_setting.plc; 
    806     setting.cng = def_setting.cng; 
    807     setting.loudspk = def_setting.loudspk; 
    808  
    809     if (def_setting.format.u32 == PJMEDIA_FOURCC_AMR || 
    810         def_setting.format.u32 == PJMEDIA_FOURCC_G711A || 
    811         def_setting.format.u32 == PJMEDIA_FOURCC_G711U || 
    812         def_setting.format.u32 == PJMEDIA_FOURCC_G729 || 
    813         def_setting.format.u32 == PJMEDIA_FOURCC_ILBC) 
    814     { 
     906        aps_setting.mode = EALawOr20ms; 
     907    } 
     908 
     909    aps_setting.vad = strm->setting.format.u32==PJMEDIA_FOURCC_L16?  
     910                                        EFalse : strm->setting.vad; 
     911    aps_setting.plc = strm->setting.plc; 
     912    aps_setting.cng = strm->setting.cng; 
     913    aps_setting.loudspk = strm->setting.loudspk; 
     914 
     915    if (strm->setting.format.u32 == PJMEDIA_FOURCC_L16) { 
     916        aps_play_cb = &PlayCbPcm; 
     917        aps_rec_cb  = &RecCbPcm; 
     918    } else { 
    815919        aps_play_cb = &PlayCb; 
    816920        aps_rec_cb  = &RecCb; 
    817     } else { 
    818         aps_play_cb = &PlayCbPcm; 
    819         aps_rec_cb  = &RecCbPcm; 
    820921    } 
    821922 
     
    823924    TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm, 
    824925                                                   aps_rec_cb, aps_play_cb, 
    825                                                    strm, setting)); 
     926                                                   strm, aps_setting)); 
    826927    if (err != KErrNone) { 
    827928        pj_pool_release(pool); 
     
    834935 
    835936    /* play_buf size is samples per frame. */ 
    836     strm->play_buf = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame << 1); 
     937    strm->play_buf = (pj_int16_t*)pj_pool_zalloc(pool, samples_per_frame << 1); 
    837938    strm->play_buf_len = 0; 
    838939    strm->play_buf_start = 0; 
    839940 
    840941    /* rec_buf size is samples per frame. */ 
    841     strm->rec_buf  = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame << 1); 
     942    strm->rec_buf  = (pj_int16_t*)pj_pool_zalloc(pool, samples_per_frame << 1); 
    842943    strm->rec_buf_len = 0; 
    843944 
     
    861962                                          pjmedia_snd_stream **p_snd_strm) 
    862963{ 
     964    pjmedia_snd_setting setting; 
     965     
    863966    if (index < 0) index = 0; 
    864967    PJ_ASSERT_RETURN(index == 0, PJ_EINVAL); 
    865968 
     969    pj_bzero(&setting, sizeof(setting)); 
     970    setting.format.u32 = PJMEDIA_FOURCC_L16; 
     971    setting.bitrate = 128000; 
     972     
    866973    return sound_open(PJMEDIA_DIR_CAPTURE, clock_rate, channel_count, 
    867974                      samples_per_frame, bits_per_sample, rec_cb, NULL, 
    868                       user_data, p_snd_strm); 
     975                      user_data, &setting, p_snd_strm); 
    869976} 
    870977 
     
    878985                                        pjmedia_snd_stream **p_snd_strm ) 
    879986{ 
     987    pjmedia_snd_setting setting; 
     988     
    880989    if (index < 0) index = 0; 
    881990    PJ_ASSERT_RETURN(index == 0, PJ_EINVAL); 
    882991 
     992    pj_bzero(&setting, sizeof(setting)); 
     993    setting.format.u32 = PJMEDIA_FOURCC_L16; 
     994    setting.bitrate = 128000; 
     995 
    883996    return sound_open(PJMEDIA_DIR_PLAYBACK, clock_rate, channel_count, 
    884997                      samples_per_frame, bits_per_sample, NULL, play_cb, 
    885                       user_data, p_snd_strm); 
     998                      user_data, &setting, p_snd_strm); 
    886999} 
    8871000 
     
    8971010                                      pjmedia_snd_stream **p_snd_strm) 
    8981011{ 
     1012    pjmedia_snd_setting setting; 
     1013 
    8991014    if (rec_id < 0) rec_id = 0; 
    9001015    if (play_id < 0) play_id = 0; 
    9011016    PJ_ASSERT_RETURN(play_id == 0 && rec_id == 0, PJ_EINVAL); 
    9021017 
     1018    pj_bzero(&setting, sizeof(setting)); 
     1019    setting.format.u32 = PJMEDIA_FOURCC_L16; 
     1020    setting.bitrate = 128000; 
     1021 
    9031022    return sound_open(PJMEDIA_DIR_CAPTURE_PLAYBACK, clock_rate, channel_count, 
    9041023                      samples_per_frame, bits_per_sample, rec_cb, play_cb, 
    905                       user_data, p_snd_strm); 
     1024                      user_data, &setting, p_snd_strm); 
     1025} 
     1026 
     1027PJ_DEF(pj_status_t) pjmedia_snd_open2( pjmedia_dir dir, 
     1028                                       int rec_id, 
     1029                                       int play_id, 
     1030                                       unsigned clock_rate, 
     1031                                       unsigned channel_count, 
     1032                                       unsigned samples_per_frame, 
     1033                                       unsigned bits_per_sample, 
     1034                                       pjmedia_snd_rec_cb rec_cb, 
     1035                                       pjmedia_snd_play_cb play_cb, 
     1036                                       void *user_data, 
     1037                                       const pjmedia_snd_setting *setting, 
     1038                                       pjmedia_snd_stream **p_snd_strm) 
     1039{ 
     1040    if (rec_id < 0) rec_id = 0; 
     1041    if (play_id < 0) play_id = 0; 
     1042    PJ_ASSERT_RETURN(play_id == 0 && rec_id == 0, PJ_EINVAL); 
     1043 
     1044    return sound_open(dir, clock_rate, channel_count, 
     1045                      samples_per_frame, bits_per_sample, rec_cb, play_cb, 
     1046                      user_data, setting, p_snd_strm); 
    9061047} 
    9071048 
     
    9941135} 
    9951136 
    996  
    9971137/* 
    9981138 * Activate/deactivate loudspeaker. 
     
    10021142                                        pj_bool_t active) 
    10031143{ 
    1004     if (stream == NULL) { 
    1005         def_setting.loudspk = active; 
    1006     } else { 
    1007         if (stream->engine == NULL) 
    1008             return PJ_EINVAL; 
    1009  
    1010         TInt err = stream->engine->ActivateSpeaker(active); 
    1011         if (err != KErrNone) 
    1012             return PJ_RETURN_OS_ERROR(err); 
    1013     } 
     1144    PJ_ASSERT_RETURN(stream && stream->engine, PJ_EINVAL); 
     1145     
     1146    TInt err = stream->engine->ActivateSpeaker(active); 
     1147    if (err != KErrNone) 
     1148        return PJ_RETURN_OS_ERROR(err); 
    10141149 
    10151150    return PJ_SUCCESS; 
    10161151} 
    10171152 
    1018 /** 
    1019  * Set a codec and its settings to be used on the next sound device session. 
    1020  */ 
    1021 PJ_DEF(pj_status_t) pjmedia_snd_aps_modify_setting( 
    1022                                     const pjmedia_snd_aps_setting *setting) 
    1023 { 
    1024     PJ_ASSERT_RETURN(setting, PJ_EINVAL); 
    1025  
    1026     def_setting = *setting; 
    1027  
    1028     return PJ_SUCCESS; 
    1029 } 
    1030  
    10311153#endif // PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_APS_SOUND 
  • pjproject/branches/projects/aps-direct/pjsip-apps/src/symbian_ua/ua.cpp

    r2394 r2438  
    9191static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID; 
    9292 
     93static pj_pool_t *app_pool; 
     94static pjmedia_snd_port *snd_port; 
     95 
    9396 
    9497/* Callback called by the library upon receiving incoming call */ 
     
    130133        if (call_id == g_call_id) 
    131134            g_call_id = PJSUA_INVALID_ID; 
     135        if (snd_port) { 
     136            pjmedia_snd_port_destroy(snd_port); 
     137            snd_port = NULL; 
     138        } 
    132139    } else if (ci.state != PJSIP_INV_STATE_INCOMING) { 
    133140        if (g_call_id == PJSUA_INVALID_ID) 
     
    250257} 
    251258 
     259/* Notification that stream is created. */ 
     260static void on_stream_created(pjsua_call_id call_id,  
     261                              pjmedia_session *sess, 
     262                              unsigned stream_idx,  
     263                              pjmedia_port **p_port) 
     264{ 
     265    pjmedia_port *conf; 
     266    pjmedia_session_info sess_info; 
     267    pjmedia_stream_info *strm_info; 
     268    pjmedia_snd_setting setting; 
     269    unsigned samples_per_frame; 
     270    pj_status_t status; 
     271     
     272    status = pjmedia_session_get_info(sess, &sess_info); 
     273    if (status != PJ_SUCCESS) { 
     274        PJ_LOG(1,(THIS_FILE, "on_stream_created() failed to get session info, " 
     275                             "status=%d", status)); 
     276        return; 
     277    } 
     278     
     279    strm_info = &sess_info.stream_info[stream_idx]; 
     280    if (strm_info->type != PJMEDIA_TYPE_AUDIO) 
     281        return; 
     282 
     283    /* Don't need to reopen sound device when the session doesn't use 
     284     * PCM format.  
     285     */ 
     286    if (strm_info->param->info.format.u32 == 0 || 
     287        strm_info->param->info.format.u32 == PJMEDIA_FOURCC_L16)  
     288    { 
     289        return; 
     290    } 
     291     
     292    pj_bzero(&setting, sizeof(setting)); 
     293    setting.format = strm_info->param->info.format; 
     294    setting.bitrate = strm_info->param->info.avg_bps; 
     295    setting.cng = strm_info->param->setting.cng; 
     296    setting.vad = strm_info->param->setting.vad; 
     297    setting.plc = strm_info->param->setting.plc; 
     298 
     299    /* Reopen sound device. */ 
     300    conf = pjsua_set_no_snd_dev(); 
     301 
     302    samples_per_frame = conf->info.samples_per_frame; 
     303     
     304    status = pjmedia_snd_port_create2(app_pool,  
     305                                      PJMEDIA_DIR_CAPTURE_PLAYBACK, 
     306                                      0, 
     307                                      0, 
     308                                      8000, 
     309                                      1, 
     310                                      samples_per_frame, 
     311                                      16, 
     312                                      &setting, 
     313                                      &snd_port); 
     314    if (status != PJ_SUCCESS) { 
     315        PJ_LOG(1,(THIS_FILE, "on_stream_created() failed to reopen sound " 
     316                             "device, status=%d", status)); 
     317        return; 
     318    } 
     319     
     320    status = pjmedia_snd_port_connect(snd_port, conf); 
     321    if (status != PJ_SUCCESS) { 
     322        PJ_LOG(1,(THIS_FILE, "on_stream_created() failed to connect sound " 
     323                             "device to conference, status=%d", status)); 
     324        return; 
     325    } 
     326} 
    252327 
    253328//#include<e32debug.h> 
     
    290365    } 
    291366 
     367    /* Create pool for application */ 
     368    app_pool = pjsua_pool_create("pjsua-app", 1000, 1000); 
     369     
    292370    /* Init pjsua */ 
    293371    pjsua_config cfg; 
     
    310388    cfg.cb.on_call_replaced = &on_call_replaced; 
    311389    cfg.cb.on_nat_detect = &on_nat_detect; 
     390    cfg.cb.on_stream_created = &on_stream_created; 
    312391     
    313392    if (SIP_PROXY) { 
     
    338417    med_cfg.has_ioqueue = PJ_FALSE; 
    339418    med_cfg.clock_rate = 8000; 
    340 #if defined(PJMEDIA_SYM_SND_USE_APS) && (PJMEDIA_SYM_SND_USE_APS==1) 
    341     med_cfg.audio_frame_ptime = 20; 
    342 #else 
    343419    med_cfg.audio_frame_ptime = 40; 
    344 #endif 
    345420    med_cfg.ec_tail_len = 0; 
    346421    med_cfg.enable_ice = USE_ICE; 
    347     med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed 
     422    med_cfg.snd_auto_close_time = 0; // wait for 0 seconds idle before sound dev get auto-closed 
    348423     
    349424    status = pjsua_init(&cfg, &log_cfg, &med_cfg); 
     
    803878#endif 
    804879         
     880    // Let pjsua destroys app pool, since the pool may still be used by app 
     881    // until pjsua_destroy() finished. 
     882    // e.g: quitting app when there is an active call may cause sound port  
     883    // memory destroyed before sound port itself gets closed/destroyed. 
     884    /* 
     885    // Release application pool 
     886    if (app_pool) { 
     887        pj_pool_release(app_pool); 
     888        app_pool = NULL; 
     889    } 
     890    */ 
     891     
    805892    // Shutdown pjsua 
    806893    pjsua_destroy(); 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_media.c

    r2425 r2438  
    173173#endif /* PJMEDIA_HAS_INTEL_IPP */ 
    174174 
     175#if PJMEDIA_HAS_PASSTHROUGH_CODECS 
     176    /* Register passthrough codecs */ 
     177    status = pjmedia_codec_passthrough_init(pjsua_var.med_endpt); 
     178    if (status != PJ_SUCCESS) { 
     179        pjsua_perror(THIS_FILE, "Error initializing passthrough codecs", 
     180                     status); 
     181        return status; 
     182    } 
     183#endif /* PJMEDIA_HAS_PASSTHROUGH_CODECS */ 
     184 
    175185#if PJMEDIA_HAS_L16_CODEC 
    176186    /* Register L16 family codecs, but disable all */ 
     
    574584            pjmedia_codec_ipp_deinit(); 
    575585#       endif   /* PJMEDIA_HAS_INTEL_IPP */ 
     586 
     587#       if PJMEDIA_HAS_PASSTHROUGH_CODECS 
     588            pjmedia_codec_passthrough_deinit(); 
     589#       endif /* PJMEDIA_HAS_PASSTHROUGH_CODECS */ 
    576590 
    577591#       if PJMEDIA_HAS_L16_CODEC 
Note: See TracChangeset for help on using the changeset viewer.