Ticket #1544: encode_and_pack-4.patch

File encode_and_pack-4.patch, 40.1 KB (added by bennylp, 12 years ago)

Patch to implement it. Tested, but it doesn't seem to help the iPhone 4S case hence it's pending

  • pjsip-apps/src/samples/streamutil.c

     
    6767 "  --send-recv           Set stream direction to bidirectional.        \n" 
    6868 "  --send-only           Set stream direction to send only             \n" 
    6969 "  --recv-only           Set stream direction to recv only (default)   \n" 
     70 "  --ptime=MSEC          Set packet payload length to MSEC             \n" 
    7071 
    7172#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    7273 "  --use-srtp[=NAME]     Enable SRTP with crypto suite NAME            \n" 
     
    110111static pj_status_t create_stream( pj_pool_t *pool, 
    111112                                  pjmedia_endpt *med_endpt, 
    112113                                  const pjmedia_codec_info *codec_info, 
     114                                  pjmedia_codec_param *codec_param, 
    113115                                  pjmedia_dir dir, 
    114116                                  pj_uint16_t local_port, 
    115117                                  const pj_sockaddr_in *rem_addr, 
     
    132134    /* Reset stream info. */ 
    133135    pj_bzero(&info, sizeof(info)); 
    134136 
    135  
    136137    /* Initialize stream info formats */ 
    137138    info.type = PJMEDIA_TYPE_AUDIO; 
    138139    info.dir = dir; 
    139140    pj_memcpy(&info.fmt, codec_info, sizeof(pjmedia_codec_info)); 
    140     info.tx_pt = codec_info->pt; 
     141    info.param = codec_param; 
     142    info.tx_pt = info.rx_pt = codec_info->pt; 
    141143    info.ssrc = pj_rand(); 
    142      
     144    info.tx_event_pt = info.rx_event_pt = PJMEDIA_RTP_PT_TELEPHONE_EVENTS; 
     145 
    143146#if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 
    144147    /* Set default RTCP XR enabled/disabled */ 
    145148    info.rtcp_xr_enabled = PJ_TRUE; 
     
    229232    pjmedia_stream *stream = NULL; 
    230233    pjmedia_port *stream_port; 
    231234    char tmp[10]; 
     235    unsigned ptime = 0; 
    232236    pj_status_t status;  
    233237 
    234238#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
     
    261265        OPT_SEND_RECV   = 'b', 
    262266        OPT_SEND_ONLY   = 's', 
    263267        OPT_RECV_ONLY   = 'i', 
     268        OPT_PTIME       = 't', 
    264269#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    265270        OPT_USE_SRTP    = 'S', 
    266271#endif 
     
    278283        { "send-recv",      0, 0, OPT_SEND_RECV }, 
    279284        { "send-only",      0, 0, OPT_SEND_ONLY }, 
    280285        { "recv-only",      0, 0, OPT_RECV_ONLY }, 
     286        { "ptime",          1, 0, OPT_PTIME }, 
    281287#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    282288        { "use-srtp",       2, 0, OPT_USE_SRTP }, 
    283289        { "srtp-tx-key",    1, 0, OPT_SRTP_TX_KEY }, 
     
    349355            dir = PJMEDIA_DIR_DECODING; 
    350356            break; 
    351357 
     358        case OPT_PTIME: 
     359            ptime = atoi(pj_optarg); 
     360            if (ptime < 10 || ptime > 2000) { 
     361                puts("ptime doesn't seem to be valid."); 
     362                return 1; 
     363            } 
     364            break; 
     365 
    352366#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    353367        case OPT_USE_SRTP: 
    354368            use_srtp = PJ_TRUE; 
     
    381395 
    382396    } 
    383397 
    384  
    385398    /* Verify arguments. */ 
    386399    if (dir & PJMEDIA_DIR_ENCODING) { 
    387400        if (remote_addr.sin_addr.s_addr == 0) { 
     
    448461                                          0, &codec_info); 
    449462    } 
    450463 
     464    /* Get codec default param for info */ 
     465    status = pjmedia_codec_mgr_get_default_param( 
     466                                    pjmedia_endpt_get_codec_mgr(med_endpt), 
     467                                    codec_info, 
     468                                    &codec_param); 
     469    /* Should be ok, as create_stream() above succeeded */ 
     470    pj_assert(status == PJ_SUCCESS); 
     471 
     472    /* Set frames per packet */ 
     473    if (ptime) { 
     474        codec_param.setting.frm_per_pkt = ptime / codec_param.info.frm_ptime; 
     475        PJ_LOG(4,(THIS_FILE, "Setting frm_per_pkt to %d", 
     476                  codec_param.setting.frm_per_pkt)); 
     477    } 
     478 
    451479    /* Create stream based on program arguments */ 
    452     status = create_stream(pool, med_endpt, codec_info, dir, local_port,  
     480    status = create_stream(pool, med_endpt, codec_info, &codec_param, 
     481                           dir, local_port, 
    453482                           &remote_addr,  
    454483#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    455484                           use_srtp, &srtp_crypto_suite,  
     
    459488    if (status != PJ_SUCCESS) 
    460489        goto on_exit; 
    461490 
    462     /* Get codec default param for info */ 
    463     status = pjmedia_codec_mgr_get_default_param( 
    464                                     pjmedia_endpt_get_codec_mgr(med_endpt),  
    465                                     codec_info,  
    466                                     &codec_param); 
    467     /* Should be ok, as create_stream() above succeeded */ 
    468     pj_assert(status == PJ_SUCCESS); 
    469  
    470491    /* Get the port interface of the stream */ 
    471492    status = pjmedia_stream_get_port( stream, &stream_port); 
    472493    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     
    589610        puts(""); 
    590611        puts("Commands:"); 
    591612        puts("  s     Display media statistics"); 
     613        puts("  0-9   Send this DTMF digit(s)"); 
    592614        puts("  q     Quit"); 
    593615        puts(""); 
    594616 
     
    603625            print_stream_stat(stream, &codec_param); 
    604626        else if (tmp[0] == 'q') 
    605627            break; 
     628        else if (pj_isdigit(tmp[0])) { 
     629            pj_str_t digits; 
     630            unsigned i; 
    606631 
     632            for (i=0; i<strlen(tmp); ) { 
     633                if (!pj_isdigit(tmp[i])) { 
     634                    pj_array_erase(tmp, sizeof(tmp[i]), strlen(tmp)+1, i); 
     635                } else { 
     636                    ++i; 
     637                } 
     638            } 
     639 
     640            digits = pj_str(tmp); 
     641            printf("Sending %d digit(s): %.*s\n", (int)digits.slen, 
     642                   (int)digits.slen, digits.ptr); 
     643            status = pjmedia_stream_dial_dtmf(stream, &digits); 
     644            if (status != PJ_SUCCESS) 
     645                PJ_PERROR(3,(THIS_FILE, status, "Error sending DTMF")); 
     646        } 
     647 
    607648    } 
    608649 
    609650 
  • pjmedia/include/pjmedia/codec.h

     
    301301        unsigned    cng:1;          /**< Comfort Noise Generator.       */ 
    302302        unsigned    penh:1;         /**< Perceptual Enhancement         */ 
    303303        unsigned    plc:1;          /**< Packet loss concealment        */ 
     304        unsigned    pack:1;         /**< Enable encode_single()&pack()  */ 
    304305        unsigned    reserved:1;     /**< Reserved, must be zero.        */ 
    305306        pjmedia_codec_fmtp enc_fmtp;/**< Encoder's fmtp params.         */ 
    306307        pjmedia_codec_fmtp dec_fmtp;/**< Decoder's fmtp params.         */ 
     
    308309} pjmedia_codec_param; 
    309310 
    310311 
     312/** 
     313 * Configuration settings for packing encoded audio frames into a packet or 
     314 * payload. 
     315 */ 
     316typedef struct pjmedia_codec_pack_cfg pjmedia_codec_pack_cfg; 
    311317 
     318 
    312319/* 
    313320 * Forward declaration for pjmedia_codec. 
    314321 */ 
     
    472479    pj_status_t (*recover)(pjmedia_codec *codec, 
    473480                           unsigned out_size, 
    474481                           struct pjmedia_frame *output); 
     482 
     483    /** 
     484     * Encode a single audio frame without performing any packing to 
     485     * the output. Normally the input frame should have exactly the same 
     486     * ptime as the codec frame time, however when the codec frame ptime 
     487     * is 10 ms, this may be called with input frame containing 20ms 
     488     * worth of samples. 
     489     * 
     490     * @param codec     The codec instance. 
     491     * @param input     Input audio frame. 
     492     * @param out_size  The length of buffer in the output frame. 
     493     * @param output    The output frame. 
     494     * 
     495     * @return          PJ_SUCCESS on success or the appropriate error code. 
     496     */ 
     497    pj_status_t (*encode_single)(pjmedia_codec *codec, 
     498                                 const struct pjmedia_frame *input, 
     499                                 unsigned out_size, 
     500                                 struct pjmedia_frame *output); 
     501 
     502    /** 
     503     * Pack one or more encoded audio frames into packet, suitable to be 
     504     * placed as payload of a transport such as RTP. 
     505     * 
     506     * @param codec     The codec instance. 
     507     * @param pack_cfg  Codec packing settings to specify how audio frames 
     508     *                  should be arranged in the output buffer. Use NULL 
     509     *                  to use codec's default packing setting. 
     510     * @param frame_cnt Number of input frames. 
     511     * @param inputs    Input frames, which is an array of encoded frames. 
     512     * @param out_size  Size of the output buffer. 
     513     * @param output    Frame buffer to receive the output. 
     514     * 
     515     * @return          PJ_SUCCESS on success. 
     516     */ 
     517    pj_status_t (*pack)(pjmedia_codec *codec, 
     518                        pjmedia_codec_pack_cfg *pack_cfg, 
     519                        unsigned frame_cnt, 
     520                        pjmedia_frame inputs[], 
     521                        unsigned out_size, 
     522                        struct pjmedia_frame *output); 
     523 
    475524} pjmedia_codec_op; 
    476525 
    477526 
     
    11031152 
    11041153 
    11051154/** 
     1155 * Encode a single audio frame without performing any packing to 
     1156 * the output. Normally the input frame should have exactly the same 
     1157 * ptime as the codec frame time, however when the codec frame ptime 
     1158 * is 10 ms, this may be called with input frame containing 20ms 
     1159 * worth of samples. 
     1160 * 
     1161 * @param codec         The codec instance. 
     1162 * @param inp           Input audio frame. 
     1163 * @param out_size      The length of buffer in the output frame. 
     1164 * @param out           The output frame. 
     1165 * 
     1166 * @return              PJ_SUCCESS on success or the appropriate error code. 
     1167 */ 
     1168PJ_INLINE(pj_status_t) pjmedia_codec_encode_single(pjmedia_codec *codec, 
     1169                                                   const pjmedia_frame *inp, 
     1170                                                   unsigned out_size, 
     1171                                                   struct pjmedia_frame *out) 
     1172{ 
     1173    if (codec->op && codec->op->encode_single) 
     1174        return (*codec->op->encode_single)(codec, inp, out_size, out); 
     1175    else 
     1176        return PJ_ENOTSUP; 
     1177 
     1178} 
     1179 
     1180 
     1181/** 
     1182 * Pack one or more encoded audio frames into packet, suitable to be 
     1183 * placed as payload of a transport such as RTP. 
     1184 * 
     1185 * @param codec The codec instance. 
     1186 * @param pack_cfg      Codec packing settings to specify how audio frames 
     1187 *                      should be arranged in the output buffer. Use NULL 
     1188 *                      to use codec's default packing setting. 
     1189 * @param frame_cnt     Number of input frames. 
     1190 * @param inputs        Input frames, which is an array of encoded frames. 
     1191 * @param out_size      Size of the output buffer. 
     1192 * @param output        Frame buffer to receive the output. 
     1193 * 
     1194 * @return              PJ_SUCCESS on success. 
     1195 */ 
     1196PJ_INLINE(pj_status_t) pjmedia_codec_pack(pjmedia_codec *codec, 
     1197                                          pjmedia_codec_pack_cfg *pack_cfg, 
     1198                                          unsigned frame_cnt, 
     1199                                          pjmedia_frame inputs[], 
     1200                                          unsigned out_size, 
     1201                                          struct pjmedia_frame *output) 
     1202{ 
     1203    if (codec->op && codec->op->pack) 
     1204        return (*codec->op->pack)(codec, pack_cfg, frame_cnt, inputs, 
     1205                                  out_size, output); 
     1206    else 
     1207        return PJ_ENOTSUP; 
     1208} 
     1209 
     1210 
     1211/** 
    11061212 * @} 
    11071213 */ 
    11081214 
  • pjmedia/include/pjmedia/rtp.h

     
    8383 * header in network byte order. 
    8484 */ 
    8585#pragma pack(1) 
    86 struct pjmedia_rtp_hdr 
     86typedef struct pjmedia_rtp_hdr 
    8787{ 
    8888#if defined(PJ_IS_BIG_ENDIAN) && (PJ_IS_BIG_ENDIAN!=0) 
    8989    pj_uint16_t v:2;            /**< packet type/version            */ 
     
    103103    pj_uint16_t seq;            /**< sequence number                */ 
    104104    pj_uint32_t ts;             /**< timestamp                      */ 
    105105    pj_uint32_t ssrc;           /**< synchronization source         */ 
    106 }; 
     106} pjmedia_rtp_hdr; 
    107107#pragma pack() 
    108108 
    109 /** 
    110  * @see pjmedia_rtp_hdr 
    111  */ 
    112 typedef struct pjmedia_rtp_hdr pjmedia_rtp_hdr; 
    113109 
    114  
    115110/** 
    116111 * RTP extendsion header. 
    117112 */ 
    118 struct pjmedia_rtp_ext_hdr 
     113typedef struct pjmedia_rtp_ext_hdr 
    119114{ 
    120115    pj_uint16_t profile_data;   /**< Profile data.          */ 
    121116    pj_uint16_t length;         /**< Length.                */ 
    122 }; 
     117} pjmedia_rtp_ext_hdr; 
    123118 
    124 /** 
    125  * @see pjmedia_rtp_ext_hdr 
    126  */ 
    127 typedef struct pjmedia_rtp_ext_hdr pjmedia_rtp_ext_hdr; 
    128  
    129  
    130119#pragma pack(1) 
    131120 
    132121/** 
    133122 * Declaration for DTMF telephony-events (RFC2833). 
    134123 */ 
    135 struct pjmedia_rtp_dtmf_event 
     124typedef struct pjmedia_rtp_dtmf_event 
    136125{ 
    137126    pj_uint8_t  event;      /**< Event type ID.     */ 
    138127    pj_uint8_t  e_vol;      /**< Event volume.      */ 
    139128    pj_uint16_t duration;   /**< Event duration.    */ 
    140 }; 
     129} pjmedia_rtp_dtmf_event; 
    141130 
    142 /** 
    143  * @see pjmedia_rtp_dtmf_event 
    144  */ 
    145 typedef struct pjmedia_rtp_dtmf_event pjmedia_rtp_dtmf_event; 
    146131 
    147132#pragma pack() 
    148133 
     
    150135/** 
    151136 * A generic sequence number management, used by both RTP and RTCP. 
    152137 */ 
    153 struct pjmedia_rtp_seq_session 
     138typedef struct pjmedia_rtp_seq_session 
    154139{ 
    155140    pj_uint16_t     max_seq;        /**< Highest sequence number heard      */ 
    156141    pj_uint32_t     cycles;         /**< Shifted count of seq number cycles */ 
    157142    pj_uint32_t     base_seq;       /**< Base seq number                    */ 
    158143    pj_uint32_t     bad_seq;        /**< Last 'bad' seq number + 1          */ 
    159144    pj_uint32_t     probation;      /**< Sequ. packets till source is valid */ 
    160 }; 
     145} pjmedia_rtp_seq_session; 
    161146 
    162 /** 
    163  * @see pjmedia_rtp_seq_session 
    164  */ 
    165 typedef struct pjmedia_rtp_seq_session pjmedia_rtp_seq_session; 
    166147 
    167  
    168148/** 
    169149 * RTP session descriptor. 
    170150 */ 
    171 struct pjmedia_rtp_session 
     151typedef struct pjmedia_rtp_session 
    172152{ 
    173153    pjmedia_rtp_hdr         out_hdr;    /**< Saved hdr for outgoing pkts.   */ 
     154    pj_timestamp            next_ts;    /**< Timestamp of next packet       */ 
    174155    pjmedia_rtp_seq_session seq_ctrl;   /**< Sequence number management.    */ 
    175156    pj_uint16_t             out_pt;     /**< Default outgoing payload type. */ 
    176157    pj_uint32_t             out_extseq; /**< Outgoing extended seq #.       */ 
    177158    pj_uint32_t             peer_ssrc;  /**< Peer SSRC.                     */ 
    178159    pj_uint32_t             received;   /**< Number of received packets.    */ 
    179 }; 
     160} pjmedia_rtp_session; 
    180161 
    181 /** 
    182  * @see pjmedia_rtp_session 
    183  */ 
    184 typedef struct pjmedia_rtp_session pjmedia_rtp_session; 
    185162 
    186  
    187163/** 
    188164 * This structure is used to receive additional information about the 
    189165 * state of incoming RTP packet. 
    190166 */ 
    191 struct pjmedia_rtp_status 
     167typedef struct pjmedia_rtp_status 
    192168{ 
    193169    union { 
    194170        struct flag { 
     
    219195                                 received, the value will be set to zero. 
    220196                                 If base sequence has been restarted, the 
    221197                                 value will be one.                         */ 
    222 }; 
     198} pjmedia_rtp_status; 
    223199 
    224200 
    225201/** 
     
    242218 
    243219 
    244220/** 
    245  * @see pjmedia_rtp_status 
    246  */ 
    247 typedef struct pjmedia_rtp_status pjmedia_rtp_status; 
    248  
    249  
    250 /** 
    251221 * This function will initialize the RTP session according to given parameters. 
    252222 * 
    253223 * @param ses           The session. 
  • pjmedia/src/pjmedia-codec/opencore_amrnb.c

     
    100100static pj_status_t  amr_codec_recover(pjmedia_codec *codec, 
    101101                                      unsigned output_buf_len, 
    102102                                      struct pjmedia_frame *output); 
     103static pj_status_t  amr_codec_encode_single(pjmedia_codec *codec, 
     104                                            const struct pjmedia_frame *input, 
     105                                            unsigned out_size, 
     106                                            struct pjmedia_frame *output); 
     107static pj_status_t  amr_codec_pack(pjmedia_codec *codec, 
     108                                   pjmedia_codec_pack_cfg *pack_cfg, 
     109                                   unsigned frame_cnt, 
     110                                   pjmedia_frame inputs[], 
     111                                   unsigned out_size, 
     112                                   struct pjmedia_frame *output); 
    103113 
    104114 
    105115 
     
    113123    &amr_codec_parse, 
    114124    &amr_codec_encode, 
    115125    &amr_codec_decode, 
    116     &amr_codec_recover 
     126    &amr_codec_recover, 
     127    &amr_codec_encode_single, 
     128    &amr_codec_pack 
    117129}; 
    118130 
    119131/* Definition for AMR-NB codec factory operations. */ 
     
    314326    attr->setting.frm_per_pkt = 2; 
    315327    attr->setting.vad = 1; 
    316328    attr->setting.plc = 1; 
     329    attr->setting.pack = 1; 
    317330 
    318331    if (def_config.octet_align) { 
    319332        attr->setting.dec_fmtp.cnt = 1; 
     
    623636    return PJ_SUCCESS; 
    624637} 
    625638 
     639/* 
     640 * Encode single frame 
     641 */ 
     642static pj_status_t  amr_codec_encode_single(pjmedia_codec *codec, 
     643                                            const struct pjmedia_frame *input, 
     644                                            unsigned out_size, 
     645                                            struct pjmedia_frame *output) 
     646{ 
     647    struct amr_data *amr_data = (struct amr_data*) codec->codec_data; 
     648    pjmedia_codec_amr_bit_info *bit_info; 
     649    pj_uint8_t *p; 
     650    int size; 
    626651 
     652    PJ_ASSERT_RETURN(input->size == 160*2, PJMEDIA_CODEC_EPCMFRMINLEN); 
     653 
     654    /* Encode */ 
     655    size = Encoder_Interface_Encode (amr_data->encoder, amr_data->enc_mode, 
     656                                     input->buf, output->buf, 0); 
     657    if (size <= 0) { 
     658        output->size = 0; 
     659        output->buf = NULL; 
     660        output->type = PJMEDIA_FRAME_TYPE_NONE; 
     661        TRACE_((THIS_FILE, "AMR-NB encode() failed")); 
     662        return PJMEDIA_CODEC_EFAILED; 
     663    } 
     664 
     665    output->size = size; 
     666 
     667    /* Move leading info to bit_info field */ 
     668    p = (pj_uint8_t*) output->buf; 
     669    bit_info = (pjmedia_codec_amr_bit_info*) &output->bit_info; 
     670    bit_info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F); 
     671    bit_info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01); 
     672    bit_info->mode = (pj_int8_t)amr_data->enc_mode; 
     673    bit_info->start_bit = 0; 
     674 
     675    /* Shift buffer due to byte removal */ 
     676    output->size = (bit_info->frame_type <= 8)? 
     677                     pjmedia_codec_amrnb_framelen[bit_info->frame_type] : 0; 
     678    pj_memmove(output->buf, (pj_uint8_t*)output->buf + 1, output->size); 
     679 
     680    /* It's possible that output->size may be zero now. Not sure if we should 
     681     * convert the frame to NONE in this case, so just leave this possibility 
     682     * for now. 
     683     */ 
     684 
     685    return PJ_SUCCESS; 
     686} 
     687 
    627688/* 
     689 * Pack frames 
     690 */ 
     691static pj_status_t  amr_codec_pack(pjmedia_codec *codec, 
     692                                   pjmedia_codec_pack_cfg *pack_cfg, 
     693                                   unsigned frame_cnt, 
     694                                   pjmedia_frame inputs[], 
     695                                   unsigned out_size, 
     696                                   struct pjmedia_frame *output) 
     697{ 
     698    struct amr_data *amr_data = (struct amr_data*) codec->codec_data; 
     699    unsigned dtx_cnt=0, sid_cnt=0, i; 
     700    pj_size_t payload_len; 
     701    pj_status_t status; 
     702 
     703    for (i = 0; i < frame_cnt; ++i) { 
     704        pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*) 
     705                                           &inputs[i].bit_info; 
     706 
     707        /* Count the number of SID and DTX frames */ 
     708        if (info->frame_type == 15) /* DTX*/ 
     709            ++dtx_cnt; 
     710        else if (info->frame_type == 8) /* SID */ 
     711            ++sid_cnt; 
     712    } 
     713 
     714    /* VA generates DTX frames as DTX+SID frames switching quickly and it 
     715     * seems that the SID frames occur too often (assuming the purpose is 
     716     * only for keeping NAT alive?). So let's modify the behavior a bit. 
     717     * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD 
     718     * milliseconds. 
     719     */ 
     720    if (sid_cnt + dtx_cnt == frame_cnt) { 
     721        pj_int32_t dtx_duration; 
     722 
     723        dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, 
     724                                           &inputs[0].timestamp); 
     725        if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || 
     726            dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000) 
     727        { 
     728            output->size = 0; 
     729            output->type = PJMEDIA_FRAME_TYPE_NONE; 
     730            output->timestamp = inputs[0].timestamp; 
     731            return PJ_SUCCESS; 
     732        } 
     733    } 
     734 
     735    payload_len = out_size; 
     736 
     737    status = pjmedia_codec_amr_pack(inputs, frame_cnt, &amr_data->enc_setting, 
     738                                    output->buf, &payload_len); 
     739    if (status != PJ_SUCCESS) { 
     740        output->size = 0; 
     741        output->buf = NULL; 
     742        output->type = PJMEDIA_FRAME_TYPE_NONE; 
     743        TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status)); 
     744        return status; 
     745    } 
     746 
     747    output->size = payload_len; 
     748    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     749    output->timestamp = inputs[0].timestamp; 
     750 
     751    amr_data->last_tx = output->timestamp; 
     752 
     753    return PJ_SUCCESS; 
     754} 
     755 
     756/* 
    628757 * Encode frame. 
    629758 */ 
    630759static pj_status_t amr_codec_encode( pjmedia_codec *codec,  
  • pjmedia/src/pjmedia/rtp.c

     
    6666    /* Initial sequence number SHOULD be random, according to RFC 3550. */ 
    6767    /* According to RFC 3711, it should be random within 2^15 bit */ 
    6868    ses->out_extseq = pj_rand() & 0x7FFF; 
    69     ses->peer_ssrc = 0; 
    7069     
    7170    /* Build default header for outgoing RTP packet. */ 
    7271    ses->out_hdr.v = RTP_VERSION; 
    73     ses->out_hdr.p = 0; 
    74     ses->out_hdr.x = 0; 
    75     ses->out_hdr.cc = 0; 
    76     ses->out_hdr.m = 0; 
    7772    ses->out_hdr.pt = (pj_uint8_t) default_pt; 
    7873    ses->out_hdr.seq = (pj_uint16_t) pj_htons( (pj_uint16_t)ses->out_extseq ); 
    79     ses->out_hdr.ts = 0; 
    8074    ses->out_hdr.ssrc = sender_ssrc; 
    8175 
    8276    /* Keep some arguments as session defaults. */ 
     
    121115    PJ_UNUSED_ARG(payload_len); 
    122116 
    123117    /* Update timestamp */ 
    124     ses->out_hdr.ts = pj_htonl(pj_ntohl(ses->out_hdr.ts)+ts_len); 
     118    ses->out_hdr.ts = pj_htonl(ses->next_ts.u32.lo); 
     119    ses->next_ts.u64 += ts_len; 
    125120 
    126121    /* If payload_len is zero, bail out. 
    127122     * This is a clock frame; we're not really transmitting anything. 
     
    129124    if (payload_len == 0) 
    130125        return PJ_SUCCESS; 
    131126 
    132     /* Update session. */ 
    133     ses->out_extseq++; 
    134  
    135127    /* Create outgoing header. */ 
    136128    ses->out_hdr.pt = (pj_uint8_t) ((pt == -1) ? ses->out_pt : pt); 
    137129    ses->out_hdr.m = (pj_uint16_t) m; 
    138130    ses->out_hdr.seq = pj_htons( (pj_uint16_t) ses->out_extseq); 
    139131 
     132    /* Update session. */ 
     133    ses->out_extseq++; 
     134 
    140135    /* Return values */ 
    141136    *rtphdr = &ses->out_hdr; 
    142137    *hdrlen = sizeof(pjmedia_rtp_hdr); 
  • pjmedia/src/pjmedia/wav_player.c

     
    591591 
    592592    /* Copy frame from buffer. */ 
    593593    frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    594     frame->timestamp.u64 = 0; 
    595594 
    596595    if ((fport->readpos + frame_size) <= (fport->buf + fport->bufsize)) 
    597596    { 
  • pjmedia/src/pjmedia/g711.c

     
    8686                                  unsigned output_buf_len, 
    8787                                  struct pjmedia_frame *output); 
    8888#endif 
     89static pj_status_t g711_encode_single(pjmedia_codec *codec, 
     90                                      const struct pjmedia_frame *input, 
     91                                      unsigned out_size, 
     92                                      struct pjmedia_frame *output); 
     93static pj_status_t g711_pack(pjmedia_codec *codec, 
     94                             pjmedia_codec_pack_cfg *pack_cfg, 
     95                             unsigned frame_cnt, 
     96                             pjmedia_frame inputs[], 
     97                             unsigned out_size, 
     98                             struct pjmedia_frame *output); 
    8999 
    90100/* Definition for G711 codec operations. */ 
    91101static pjmedia_codec_op g711_op =  
     
    98108    &g711_encode, 
    99109    &g711_decode, 
    100110#if !PLC_DISABLED 
    101     &g711_recover 
     111    &g711_recover, 
    102112#else 
    103     NULL 
     113    NULL, 
    104114#endif 
     115    g711_encode_single, 
     116    g711_pack 
    105117}; 
    106118 
    107119/* Definition for G711 codec factory operations. */ 
     
    268280    /* Enable VAD by default. */ 
    269281    attr->setting.vad = 1; 
    270282 
     283    /* encode_single() and pack() may be used */ 
     284    attr->setting.pack = 1; 
     285 
    271286    /* Default all other flag bits disabled. */ 
    272287 
    273288    return PJ_SUCCESS; 
     
    480495    return PJ_SUCCESS; 
    481496} 
    482497 
     498static pj_status_t g711_encode_single(pjmedia_codec *codec, 
     499                                      const struct pjmedia_frame *input, 
     500                                      unsigned output_buf_len, 
     501                                      struct pjmedia_frame *output) 
     502{ 
     503    return g711_encode(codec, input, output_buf_len, output); 
     504} 
     505 
     506static pj_status_t g711_pack(pjmedia_codec *codec, 
     507                             pjmedia_codec_pack_cfg *pack_cfg, 
     508                             unsigned frame_cnt, 
     509                             pjmedia_frame inputs[], 
     510                             unsigned out_size, 
     511                             struct pjmedia_frame *output) 
     512{ 
     513    unsigned i; 
     514 
     515    output->size = 0; 
     516 
     517    for (i=0; i<frame_cnt; ++i) { 
     518        if (out_size < inputs[i].size) 
     519            return PJMEDIA_CODEC_EFRMTOOSHORT; 
     520        pj_memcpy((pj_uint8_t*)output->buf + output->size, 
     521                  inputs[i].buf, inputs[i].size); 
     522        out_size -= inputs[i].size; 
     523        output->size += inputs[i].size; 
     524    } 
     525    return PJ_SUCCESS; 
     526} 
     527 
    483528static pj_status_t  g711_encode(pjmedia_codec *codec,  
    484529                                const struct pjmedia_frame *input, 
    485530                                unsigned output_buf_len,  
  • pjmedia/src/pjmedia/stream.c

     
    5151 */ 
    5252#define MAX_PLC_MSEC                    PJMEDIA_MAX_PLC_DURATION_MSEC 
    5353 
     54/* Maximum size of pack buffer */ 
     55#define PACK_BUF_MAX_SIZE               PJMEDIA_MAX_MTU 
    5456 
    5557/* Tracing jitter buffer operations in a stream session to a CSV file. 
    5658 * The trace will contain JB operation timestamp, frame info, RTP info, and 
     
    7375#   define PJMEDIA_STREAM_INC   1000 
    7476#endif 
    7577 
     78#ifndef PJMEDIA_STREAM_MAX_FRAMES_PER_PKT 
     79#   define PJMEDIA_STREAM_MAX_FRAMES_PER_PKT    32 
     80#endif 
    7681 
     82 
    7783/** 
    7884 * Media channel. 
    7985 */ 
     
    122128 
    123129    pjmedia_codec           *codec;         /**< Codec instance being used. */ 
    124130    pjmedia_codec_param      codec_param;   /**< Codec param.               */ 
     131 
    125132    pj_int16_t              *enc_buf;       /**< Encoding buffer, when enc's 
    126133                                                 ptime is different than dec. 
    127134                                                 Otherwise it's NULL.       */ 
    128  
    129135    unsigned                 enc_samples_per_pkt; 
    130136    unsigned                 enc_buf_size;  /**< Encoding buffer size, in 
    131137                                                 samples.                   */ 
     
    133139    unsigned                 enc_buf_count; /**< Number of samples in the 
    134140                                                 encoding buffer.           */ 
    135141 
     142    pj_uint8_t              *pack_buf;      /**< Buffer for packing encoded 
     143                                                 frames, experimental.      */ 
     144    unsigned                 pack_buf_size; /**< Current size of pack_buf   */ 
     145    unsigned                 pack_rtp_ts_len;/**< # of samples in pack buf  */ 
     146    unsigned                 pack_frm_cnt;  /**< Number of pack frm.        */ 
     147    pjmedia_frame           *pack_frm;      /**< Array of yet to be packed 
     148                                                 frames                     */ 
     149    unsigned                 pack_frm_per_pkt; /**< # of frames per packet. */ 
     150 
    136151    unsigned                 plc_cnt;       /**< # of consecutive PLC frames*/ 
    137152    unsigned                 max_plc_cnt;   /**< Max # of PLC frames        */ 
    138153 
    139154    unsigned                 vad_enabled;   /**< VAD enabled in param.      */ 
    140     unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
    141155    pj_bool_t                is_streaming;  /**< Currently streaming?. This 
    142156                                                 is used to put RTP marker 
    143157                                                 bit.                       */ 
     
    11371151    } 
    11381152} 
    11391153 
     1154/* Util */ 
     1155static void set_streaming_state(pjmedia_stream *stream, 
     1156                                pj_bool_t is_streaming, 
     1157                                const pj_timestamp *ts) 
     1158{ 
     1159    if (is_streaming) { 
     1160        PJ_LOG(5,(stream->port.info.name.ptr, "Start talksprut")); 
     1161    } else { 
     1162        PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence..")); 
     1163    } 
    11401164 
     1165    stream->is_streaming = is_streaming; 
     1166} 
     1167 
    11411168/** 
    11421169 * put_frame_imp() 
    11431170 */ 
     
    11521179    void *rtphdr; 
    11531180    int rtphdrlen; 
    11541181    int inc_timestamp = 0; 
     1182    pj_bool_t start_talksprut = PJ_FALSE; 
     1183    enum 
     1184    { 
     1185        DO_NOTHING,             /* No action (must be bug then!)        */ 
     1186        DO_SEND_DTMF,           /* Transmit RFC 2833 DTMF               */ 
     1187        DO_CHECK_SEND_SILENCE,  /* Check and TX silence periodically.   */ 
     1188        DO_UPDATE_TS_ONLY,      /* Just update RTP timestamp, no TX.    */ 
     1189        DO_WHOLE_ENCODE_AND_SEND,/* Encode audio and send immediately.  */ 
     1190        DO_ENCODE_AND_APPEND,   /* New: encode single frame and append 
     1191                                   to buffer                            */ 
     1192        DO_PACK_AND_SEND,       /* New: have enough frames in the buffer, 
     1193                                   so pack and send them.               */ 
     1194    } action = DO_NOTHING; 
    11551195 
    1156  
    11571196#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0 
    11581197    /* If the interval since last sending packet is greater than 
    11591198     * PJMEDIA_STREAM_KA_INTERVAL, send keep-alive packet. 
     
    11921231    stream->tx_duration += ts_len; 
    11931232 
    11941233#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) 
    1195     /* Handle special case for audio codec with RTP timestamp inconsistence  
     1234    /* Handle special case for audio codec with RTP timestamp inconsistency 
    11961235     * e.g: G722, MPEG audio. 
    11971236     */ 
    11981237    if (stream->has_g722_mpeg_bug) 
     
    12111250    samples_per_frame = stream->enc_samples_per_pkt; 
    12121251 
    12131252 
    1214     /* If we have DTMF digits in the queue, transmit the digits.  
    1215      * Otherwise encode the PCM buffer. 
    1216      */ 
    12171253    if (stream->tx_dtmf_count) { 
    1218         int first=0, last=0; 
    1219  
    1220         create_dtmf_payload(stream, &frame_out, &first, &last); 
    1221  
    1222         /* Encapsulate into RTP packet. Note that: 
    1223          *  - RTP marker should be set on the beginning of a new event 
    1224          *  - RTP timestamp is constant for the same packet.  
    1225          */ 
    1226         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    1227                                          stream->tx_event_pt, first,  
    1228                                          frame_out.size, 
    1229                                          (first ? rtp_ts_len : 0),  
    1230                                          (const void**)&rtphdr,  
    1231                                          &rtphdrlen); 
    1232  
    1233         if (last) { 
    1234             /* This is the last packet for the event.  
    1235              * Increment the RTP timestamp of the RTP session, for next 
    1236              * RTP packets. 
    1237              */ 
    1238             inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 
     1254        /* We have DTMF to send. If we currently have frames in the 
     1255         * pack buffer, flush them so that we can start sending DTMF 
     1256         * in the next cycle. 
     1257         */ 
     1258        if (stream->pack_frm_cnt) { 
     1259            action = DO_ENCODE_AND_APPEND; 
     1260        } else { 
     1261            action = DO_SEND_DTMF; 
    12391262        } 
    12401263 
    1241  
    1242     /* 
    1243      * Special treatment for FRAME_TYPE_AUDIO but with frame->buf==NULL. 
    1244      * This happens when stream input is disconnected from the bridge. 
    1245      * In this case we periodically transmit RTP frame to keep NAT binding 
    1246      * open, by giving zero PCM frame to the codec. 
    1247      * 
    1248      * This was originally done in http://trac.pjsip.org/repos/ticket/56, 
    1249      * but then disabled in http://trac.pjsip.org/repos/ticket/439, but 
    1250      * now it's enabled again. 
    1251      */ 
    12521264    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
    12531265               frame->buf == NULL && 
    12541266               stream->port.info.fmt.id == PJMEDIA_FORMAT_L16 && 
     
    12581270               stream->codec_param.info.clock_rate/1000 < 
    12591271                  PJ_ARRAY_SIZE(zero_frame))  
    12601272    { 
    1261         pjmedia_frame silence_frame; 
     1273        /* 
     1274         * Special treatment for FRAME_TYPE_AUDIO but with frame->buf==NULL. 
     1275         * This happens when stream input is disconnected from the bridge. 
     1276         * In this case we periodically transmit RTP frame to keep NAT binding 
     1277         * open, by giving zero PCM frame to the codec. 
     1278         * 
     1279         * This was originally done in http://trac.pjsip.org/repos/ticket/56, 
     1280         * but then disabled in http://trac.pjsip.org/repos/ticket/439, but 
     1281         * now it's enabled again. 
     1282         */ 
     1283        if (stream->pack_frm_cnt) { 
     1284            /* This is the first time we get silence. Check if we already 
     1285             * have frames in the buffer and flush them. 
     1286             */ 
     1287            action = DO_PACK_AND_SEND; 
     1288        } else { 
     1289            action = DO_CHECK_SEND_SILENCE; 
     1290        } 
    12621291 
    1263         pj_bzero(&silence_frame, sizeof(silence_frame)); 
    1264         silence_frame.buf = zero_frame; 
    1265         silence_frame.size = stream->codec_param.info.frm_ptime * 2 * 
    1266                              stream->codec_param.info.channel_cnt * 
    1267                              stream->codec_param.info.clock_rate / 1000; 
    1268         silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    1269         silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
    1270          
     1292    } else if ((frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
     1293                frame->buf != NULL) || 
     1294               (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED)) 
     1295    { 
     1296        /* Encode audio frame */ 
     1297        if (stream->pack_buf) { 
     1298            action = DO_ENCODE_AND_APPEND; 
     1299        } else { 
     1300            action = DO_WHOLE_ENCODE_AND_SEND; 
     1301        } 
     1302    } else { 
     1303        action = DO_UPDATE_TS_ONLY; 
     1304    } 
     1305 
     1306    /* 
     1307     * Perform action 
     1308     */ 
     1309    if (action == DO_WHOLE_ENCODE_AND_SEND) { 
    12711310        /* Encode! */ 
    1272         status = pjmedia_codec_encode( stream->codec, &silence_frame, 
     1311        status = pjmedia_codec_encode( stream->codec, frame,  
    12731312                                       channel->out_pkt_size -  
    12741313                                       sizeof(pjmedia_rtp_hdr), 
    12751314                                       &frame_out); 
     
    12771316            LOGERR_((stream->port.info.name.ptr,  
    12781317                    "Codec encode() error", status)); 
    12791318            return status; 
     1319        } else if (frame_out.size == 0) { 
     1320            if (stream->is_streaming) { 
     1321                set_streaming_state(stream, PJ_FALSE, &frame->timestamp); 
     1322            } 
     1323        } else { 
     1324            if (!stream->is_streaming) { 
     1325                set_streaming_state(stream, PJ_TRUE, &frame->timestamp); 
     1326                start_talksprut = PJ_TRUE; 
     1327            } 
    12801328        } 
    12811329 
    12821330        /* Encapsulate. */ 
     
    12861334                                         (const void**)&rtphdr,  
    12871335                                         &rtphdrlen); 
    12881336 
     1337    } else if (action == DO_ENCODE_AND_APPEND || 
     1338               action == DO_PACK_AND_SEND) 
     1339    { 
     1340        if (action == DO_ENCODE_AND_APPEND) { 
     1341            /* Encode 1 frame and append to buffer */ 
     1342            pjmedia_frame *ptr_frm; 
     1343            unsigned max_size; 
    12891344 
    1290     /* Encode audio frame */ 
    1291     } else if ((frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
    1292                 frame->buf != NULL) || 
    1293                (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED)) 
    1294     { 
     1345            ptr_frm = &stream->pack_frm[stream->pack_frm_cnt]; 
     1346            ptr_frm->buf = stream->pack_buf + stream->pack_buf_size; 
     1347            ptr_frm->size = 0; 
     1348            ptr_frm->timestamp = frame->timestamp; 
     1349            ptr_frm->bit_info = 0; 
     1350            max_size = PACK_BUF_MAX_SIZE - stream->pack_buf_size; 
     1351 
     1352            /* Encode! */ 
     1353            status = pjmedia_codec_encode_single(stream->codec, 
     1354                                                 frame, max_size, 
     1355                                                 ptr_frm); 
     1356            if (status != PJ_SUCCESS) { 
     1357                LOGERR_((stream->port.info.name.ptr, 
     1358                        "Codec encode_single() error", status)); 
     1359                stream->pack_rtp_ts_len += rtp_ts_len; 
     1360                action = DO_PACK_AND_SEND; 
     1361            } else if (ptr_frm->size == 0) { 
     1362                /* Got silence. Flush frames */ 
     1363                stream->pack_rtp_ts_len += rtp_ts_len; 
     1364                action = DO_PACK_AND_SEND; 
     1365            } else { 
     1366                unsigned pkt_ptime, target_pkt_ptime; 
     1367 
     1368                stream->pack_rtp_ts_len += rtp_ts_len; 
     1369                ++stream->pack_frm_cnt; 
     1370                stream->pack_buf_size += ptr_frm->size; 
     1371 
     1372                /* Check current buffer's length. It is possible that the 
     1373                 * duration has exceeded the target if put_frame() is called 
     1374                 * with input that contains multiple frames (sample case: 
     1375                 * pcmu and g719 due to it's 10ms frame_ptime) 
     1376                 */ 
     1377                pkt_ptime = stream->pack_rtp_ts_len * 1000 / 
     1378                            stream->port.info.fmt.det.aud.clock_rate; 
     1379                target_pkt_ptime = stream->pack_frm_per_pkt * 
     1380                                   stream->codec_param.info.frm_ptime; 
     1381 
     1382                if (stream->pack_frm_cnt >= stream->pack_frm_per_pkt || 
     1383                    pkt_ptime >= target_pkt_ptime || 
     1384                    stream->tx_dtmf_count) 
     1385                { 
     1386                    action = DO_PACK_AND_SEND; 
     1387                } 
     1388            } 
     1389        } 
     1390 
     1391        if (action == DO_PACK_AND_SEND) { 
     1392            /* Pack */ 
     1393            if (stream->pack_frm_cnt) { 
     1394                status = pjmedia_codec_pack(stream->codec, NULL, 
     1395                                            stream->pack_frm_cnt, 
     1396                                            stream->pack_frm, 
     1397                                            channel->out_pkt_size - 
     1398                                              sizeof(pjmedia_rtp_hdr), 
     1399                                            &frame_out); 
     1400                if (status != PJ_SUCCESS) { 
     1401                    LOGERR_((stream->port.info.name.ptr, 
     1402                            "Codec pack() error", status)); 
     1403                } else { 
     1404                    /* NOTE: frame_out->size may be zero on DTX */ 
     1405 
     1406                    if (frame_out.size && !stream->is_streaming) { 
     1407                        set_streaming_state(stream, PJ_TRUE, 
     1408                                            &frame->timestamp); 
     1409                        start_talksprut = PJ_TRUE; 
     1410                    } 
     1411 
     1412                    /* Encapsulate. */ 
     1413                    status = pjmedia_rtp_encode_rtp( &channel->rtp, 
     1414                                                     channel->pt, 0, 
     1415                                                     frame_out.size, 
     1416                                                     stream->pack_rtp_ts_len, 
     1417                                                     (const void**)&rtphdr, 
     1418                                                     &rtphdrlen); 
     1419                } 
     1420            } else { 
     1421                /* Update RTP session's timestamp. */ 
     1422                status = pjmedia_rtp_encode_rtp( &channel->rtp, 
     1423                                                 0, 0, 0, 
     1424                                                 stream->pack_rtp_ts_len, 
     1425                                                 (const void**)&rtphdr, 
     1426                                                 &rtphdrlen); 
     1427 
     1428                if (stream->is_streaming) { 
     1429                    set_streaming_state(stream, PJ_FALSE, &frame->timestamp); 
     1430                } 
     1431            } 
     1432 
     1433            /* Reset no matter what */ 
     1434            stream->pack_frm_cnt = 0; 
     1435            stream->pack_buf_size = 0; 
     1436            stream->pack_rtp_ts_len = 0; 
     1437        } 
     1438 
     1439    } else if (action == DO_SEND_DTMF) { 
     1440        int first=0, last=0; 
     1441 
     1442        create_dtmf_payload(stream, &frame_out, &first, &last); 
     1443 
     1444        /* Encapsulate into RTP packet. Note that: 
     1445         *  - RTP marker should be set on the beginning of a new event 
     1446         *  - RTP timestamp is constant for the same packet. 
     1447         */ 
     1448        status = pjmedia_rtp_encode_rtp( &channel->rtp, 
     1449                                         stream->tx_event_pt, first, 
     1450                                         frame_out.size, 
     1451                                         0, 
     1452                                         (const void**)&rtphdr, 
     1453                                         &rtphdrlen); 
     1454 
     1455        if (last) { 
     1456            /* This is the last packet for the event. 
     1457             * Increment the RTP timestamp of the RTP session, for next 
     1458             * RTP packets. 
     1459             */ 
     1460            inc_timestamp = PJMEDIA_DTMF_DURATION; 
     1461        } 
     1462    } else if (action == DO_CHECK_SEND_SILENCE) { 
     1463        pjmedia_frame silence_frame; 
     1464 
     1465        pj_bzero(&silence_frame, sizeof(silence_frame)); 
     1466        silence_frame.buf = zero_frame; 
     1467        silence_frame.size = stream->codec_param.info.frm_ptime * 2 * 
     1468                             stream->codec_param.info.channel_cnt * 
     1469                             stream->codec_param.info.clock_rate / 1000; 
     1470        silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     1471        silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
     1472 
    12951473        /* Encode! */ 
    1296         status = pjmedia_codec_encode( stream->codec, frame,  
    1297                                        channel->out_pkt_size -  
     1474        status = pjmedia_codec_encode( stream->codec, &silence_frame, 
     1475                                       channel->out_pkt_size - 
    12981476                                       sizeof(pjmedia_rtp_hdr), 
    12991477                                       &frame_out); 
    13001478        if (status != PJ_SUCCESS) { 
    1301             LOGERR_((stream->port.info.name.ptr,  
     1479            LOGERR_((stream->port.info.name.ptr, 
    13021480                    "Codec encode() error", status)); 
    13031481            return status; 
     1482        } else if (frame_out.size == 0) { 
     1483            if (stream->is_streaming) { 
     1484                set_streaming_state(stream, PJ_FALSE, &frame->timestamp); 
     1485            } 
     1486        } else { 
     1487            if (!stream->is_streaming) { 
     1488                set_streaming_state(stream, PJ_TRUE, &frame->timestamp); 
     1489                start_talksprut = PJ_TRUE; 
     1490            } 
    13041491        } 
    13051492 
    13061493        /* Encapsulate. */ 
    1307         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    1308                                          channel->pt, 0,  
    1309                                          frame_out.size, rtp_ts_len,  
    1310                                          (const void**)&rtphdr,  
     1494        status = pjmedia_rtp_encode_rtp( &channel->rtp, 
     1495                                         channel->pt, 0, 
     1496                                         frame_out.size, rtp_ts_len, 
     1497                                         (const void**)&rtphdr, 
    13111498                                         &rtphdrlen); 
    1312  
    1313     } else { 
    1314  
     1499    } else if (action == DO_UPDATE_TS_ONLY) { 
    13151500        /* Just update RTP session's timestamp. */ 
    1316         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    1317                                          0, 0,  
    1318                                          0, rtp_ts_len,  
    1319                                          (const void**)&rtphdr,  
     1501        status = pjmedia_rtp_encode_rtp( &channel->rtp, 
     1502                                         0, 0, 
     1503                                         0, rtp_ts_len, 
     1504                                         (const void**)&rtphdr, 
    13201505                                         &rtphdrlen); 
    1321  
     1506    } else { 
     1507        pj_assert(!"Unknown operation (bug)"); 
    13221508    } 
    13231509 
    13241510    if (status != PJ_SUCCESS) { 
     
    13371523 
    13381524    /* Do nothing if we have nothing to transmit */ 
    13391525    if (frame_out.size == 0) { 
    1340         if (stream->is_streaming) { 
    1341             PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence")); 
    1342             stream->is_streaming = PJ_FALSE; 
    1343         } 
    1344  
    13451526        return PJ_SUCCESS; 
    13461527    } 
    13471528 
     
    13591540    } 
    13601541 
    13611542    /* Set RTP marker bit if currently not streaming */ 
    1362     if (stream->is_streaming == PJ_FALSE) { 
     1543    if (start_talksprut) { 
    13631544        pjmedia_rtp_hdr *rtp = (pjmedia_rtp_hdr*) channel->out_pkt; 
    13641545 
    13651546        rtp->m = 1; 
    1366         PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut..")); 
    13671547    } 
    13681548 
    1369     stream->is_streaming = PJ_TRUE; 
    1370  
    13711549    /* Send the RTP packet to the transport. */ 
    13721550    status = pjmedia_transport_send_rtp(stream->transport, channel->out_pkt, 
    13731551                                        frame_out.size + 
     
    19642142    pjmedia_stream *stream; 
    19652143    pj_str_t name; 
    19662144    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; 
     2145    unsigned jb_frame_size; 
    19672146    pjmedia_audio_format_detail *afd; 
    19682147    pj_pool_t *own_pool = NULL; 
    19692148    char *p; 
     
    20822261 
    20832262    /* Set additional info and callbacks. */ 
    20842263    afd->bits_per_sample = 16; 
    2085     afd->frame_time_usec = stream->codec_param.info.frm_ptime * 
    2086                            stream->codec_param.setting.frm_per_pkt * 1000; 
     2264 
     2265    /* New and experimental: 
     2266     *  Encode and decode frame one by one (only if "pack" is enabled) 
     2267     */ 
     2268    if (stream->codec_param.setting.pack && 
     2269        stream->codec_param.info.frm_ptime * 
     2270          stream->codec_param.setting.frm_per_pkt >= 40) 
     2271    { 
     2272        PJ_ASSERT_RETURN(stream->codec->op->encode_single && 
     2273                         stream->codec->op->pack, PJ_EINVAL); 
     2274 
     2275        if (stream->codec_param.setting.frm_per_pkt > 
     2276                PJMEDIA_STREAM_MAX_FRAMES_PER_PKT) 
     2277        { 
     2278            status = PJ_ETOOMANY; 
     2279            goto err_cleanup; 
     2280        } 
     2281        stream->pack_frm = (pjmedia_frame*) 
     2282                           pj_pool_calloc(pool, 
     2283                                          PJMEDIA_STREAM_MAX_FRAMES_PER_PKT, 
     2284                                          sizeof(pjmedia_frame)); 
     2285        stream->pack_buf = (pj_uint8_t*) 
     2286                           pj_pool_alloc(pool, PACK_BUF_MAX_SIZE); 
     2287 
     2288        stream->pack_frm_per_pkt = stream->codec_param.setting.frm_per_pkt; 
     2289 
     2290        /* Set stream's ptime back to 20ms. We limit minimum stream's ptime 
     2291         * to 20ms, otherwise DTMF will be sent every 10ms which probably is 
     2292         * not good. 
     2293         */ 
     2294        if (stream->codec_param.info.frm_ptime < 20) { 
     2295            stream->codec_param.setting.frm_per_pkt = 2; 
     2296        } else { 
     2297            stream->codec_param.setting.frm_per_pkt = 1; 
     2298        } 
     2299        afd->frame_time_usec = stream->codec_param.info.frm_ptime * 
     2300                               stream->codec_param.setting.frm_per_pkt * 1000; 
     2301 
     2302        pjmedia_codec_modify(stream->codec, &stream->codec_param); 
     2303 
     2304        PJ_LOG(4,(stream->port.info.name.ptr, 
     2305                  "Using experimental single encoding/decoding, f/p=%d", 
     2306                  stream->pack_frm_per_pkt)); 
     2307 
     2308    } else { 
     2309        afd->frame_time_usec = stream->codec_param.info.frm_ptime * 
     2310                               stream->codec_param.setting.frm_per_pkt * 1000; 
     2311    } 
     2312 
    20872313    stream->port.info.fmt.id = stream->codec_param.info.fmt_id; 
    20882314    if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) { 
    20892315        /* Raw format */ 
     
    21592385    } 
    21602386 
    21612387    /* Get the frame size */ 
    2162     stream->frame_size = stream->codec_param.info.max_bps *  
    2163                         stream->codec_param.info.frm_ptime / 8 / 1000; 
     2388    jb_frame_size = stream->codec_param.info.max_bps * 
     2389                    stream->codec_param.info.frm_ptime / 8 / 1000; 
    21642390    if ((stream->codec_param.info.max_bps * stream->codec_param.info.frm_ptime)  
    21652391        % 8000 != 0) 
    21662392    { 
    2167         ++stream->frame_size; 
     2393        ++jb_frame_size; 
    21682394    } 
    21692395 
    21702396    /* How many consecutive PLC frames can be generated */ 
     
    22162442 
    22172443    /* Create jitter buffer */ 
    22182444    status = pjmedia_jbuf_create(pool, &stream->port.info.name, 
    2219                                  stream->frame_size,  
     2445                                 jb_frame_size, 
    22202446                                 stream->codec_param.info.frm_ptime, 
    22212447                                 jb_max, &stream->jb); 
    22222448    if (status != PJ_SUCCESS)