Changeset 1779


Ignore:
Timestamp:
Feb 4, 2008 11:56:40 PM (12 years ago)
Author:
nanang
Message:

Ticket #461:
Initial integration of the new jitter buffer into stream

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/jbuf2/pjmedia/src/pjmedia/stream.c

    r1667 r1779  
    2121#include <pjmedia/rtp.h> 
    2222#include <pjmedia/rtcp.h> 
    23 #include <pjmedia/jbuf.h> 
     23#include <pjmedia/jbuf2.h> 
    2424#include <pj/array.h> 
    2525#include <pj/assert.h> 
     
    109109 
    110110    pj_mutex_t              *jb_mutex; 
    111     pjmedia_jbuf            *jb;            /**< Jitter buffer.             */ 
    112     char                     jb_last_frm;   /**< Last frame type from jb    */ 
     111    pjmedia_jb2_t           *jb;            /**< Jitter buffer.             */ 
    113112 
    114113    pjmedia_rtcp_session     rtcp;          /**< RTCP for incoming RTP.     */ 
     
    153152} 
    154153 
     154static pj_status_t jb_decode(pjmedia_jb2_frame *frame, void *userdata) 
     155{ 
     156    pjmedia_stream *stream = (pjmedia_stream*) userdata; 
     157    pj_status_t status = PJ_SUCCESS; 
     158    pjmedia_frame frame_in, frame_out; 
     159 
     160    pj_assert(frame && userdata); 
     161 
     162    /* Decode */ 
     163    frame_in.buf = stream->dec->out_pkt; 
     164    frame_in.size = frame->size; 
     165    frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     166    pj_memcpy(frame_in.buf, frame->buffer, frame->size); 
     167 
     168    frame_out.buf = frame->buffer; 
     169    frame_out.size = (stream->codec_param.info.clock_rate * 
     170                     stream->codec_param.info.frm_ptime / 1000)* 
     171                     (stream->codec_param.info.pcm_bits_per_sample/8); 
     172 
     173    status = stream->codec->op->decode( stream->codec, &frame_in, 
     174                                        frame_out.size, &frame_out); 
     175 
     176    /* NOTE: frame_out.size is not valid for speex/16000 */ 
     177    frame->size = frame_out.size; 
     178    if (status != PJ_SUCCESS) { 
     179        LOGERR_((stream->port.info.name.ptr, "codec decode() error",  
     180                 status)); 
     181 
     182        pj_bzero(frame->buffer, frame->size); 
     183    } 
     184 
     185    return status; 
     186} 
     187 
     188static pj_status_t jb_plc(pjmedia_jb2_frame *frame, void *userdata) 
     189{ 
     190    pjmedia_stream *stream = (pjmedia_stream*) userdata; 
     191    pj_status_t status = PJ_SUCCESS; 
     192 
     193    pj_assert(frame && stream); 
     194 
     195    /* Activate PLC */ 
     196    if (stream->codec->op->recover &&  
     197        stream->codec_param.setting.plc)  
     198    { 
     199        pjmedia_frame frame_out; 
     200 
     201        frame_out.buf = frame->buffer; 
     202        frame_out.size = frame->size; 
     203        status = (*stream->codec->op->recover)(stream->codec, 
     204                                               frame_out.size, 
     205                                               &frame_out); 
     206    } else { 
     207        status = PJ_EINVAL; 
     208    } 
     209 
     210    if (status != PJ_SUCCESS) { 
     211        /* Either PLC failed or PLC not supported/enabled */ 
     212        pj_bzero(frame->buffer, frame->size); 
     213        PJ_LOG(5,(stream->port.info.name.ptr,  "Frame lost!")); 
     214 
     215    } else { 
     216        PJ_LOG(5,(stream->port.info.name.ptr,  
     217                  "Lost frame recovered")); 
     218    } 
     219 
     220    return status; 
     221} 
     222 
     223static pj_status_t jb_cng(pjmedia_jb2_frame *frame, void *userdata) 
     224{ 
     225    pjmedia_stream *stream = (pjmedia_stream*) userdata; 
     226 
     227    pj_assert(frame && stream); 
     228 
     229    frame->size = (stream->codec_param.info.clock_rate * 
     230                   stream->codec_param.info.frm_ptime / 1000)* 
     231                  (stream->codec_param.info.pcm_bits_per_sample/8); 
     232    pj_bzero(frame->buffer, frame->size); 
     233 
     234    return PJ_SUCCESS; 
     235} 
     236 
    155237 
    156238/* 
     
    160242 * needs to feed the player with some frames. 
    161243 */ 
     244 
    162245static pj_status_t get_frame( pjmedia_port *port, pjmedia_frame *frame) 
    163246{ 
     
    167250    pj_int16_t *p_out_samp; 
    168251    pj_status_t status; 
    169  
     252    pjmedia_jb2_frame jb_frame; 
    170253 
    171254    /* Return no frame is channel is paused */ 
     
    192275         samples_count += samples_per_frame)  
    193276    { 
    194         char frame_type; 
    195  
    196277        /* Get frame from jitter buffer. */ 
    197         pjmedia_jbuf_get_frame(stream->jb, channel->out_pkt, &frame_type); 
    198          
    199         if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 
    200              
    201             /* Activate PLC */ 
    202             if (stream->codec->op->recover &&  
    203                 stream->codec_param.setting.plc)  
    204             { 
    205                 pjmedia_frame frame_out; 
    206  
    207                 frame_out.buf = p_out_samp + samples_count; 
    208                 frame_out.size = frame->size - samples_count*2; 
    209                 status = (*stream->codec->op->recover)(stream->codec, 
    210                                                        frame_out.size, 
    211                                                        &frame_out); 
    212  
    213             } else { 
    214                 status = -1; 
    215             } 
    216  
    217             if (status != PJ_SUCCESS) { 
    218                 /* Either PLC failed or PLC not supported/enabled */ 
    219                 pjmedia_zero_samples(p_out_samp + samples_count, 
    220                                      samples_required - samples_count); 
    221                 PJ_LOG(5,(stream->port.info.name.ptr,  "Frame lost!")); 
    222  
    223             } else { 
    224                 PJ_LOG(5,(stream->port.info.name.ptr,  
    225                           "Lost frame recovered")); 
    226             } 
    227              
    228         } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
    229  
    230             /* Jitter buffer is empty. If this is the first "empty" state, 
    231              * activate PLC to smoothen the fade-out, otherwise zero 
    232              * the frame.  
    233              */ 
    234             if (frame_type != stream->jb_last_frm) { 
    235                 pjmedia_jb_state jb_state; 
    236  
    237                 /* Activate PLC to smoothen the missing frame */ 
    238                 if (stream->codec->op->recover &&  
    239                     stream->codec_param.setting.plc)  
    240                 { 
    241                     pjmedia_frame frame_out; 
    242  
    243                     do { 
    244                         frame_out.buf = p_out_samp + samples_count; 
    245                         frame_out.size = frame->size - samples_count*2; 
    246                         status = (*stream->codec->op->recover)(stream->codec, 
    247                                                                frame_out.size, 
    248                                                                &frame_out); 
    249                         if (status != PJ_SUCCESS) 
    250                             break; 
    251                         samples_count += samples_per_frame; 
    252  
    253                     } while (samples_count < samples_required); 
    254  
    255                 }  
    256  
    257                 /* Report the state of jitter buffer */ 
    258                 pjmedia_jbuf_get_state(stream->jb, &jb_state); 
    259                 PJ_LOG(5,(stream->port.info.name.ptr,  
    260                           "Jitter buffer empty (prefetch=%d)",  
    261                           jb_state.prefetch)); 
    262  
    263             } 
    264  
    265             if (samples_count < samples_required) { 
    266                 pjmedia_zero_samples(p_out_samp + samples_count, 
    267                                      samples_required - samples_count); 
    268                 samples_count = samples_required; 
    269             } 
    270  
    271             stream->jb_last_frm = frame_type; 
    272             break; 
    273  
    274         } else if (frame_type != PJMEDIA_JB_NORMAL_FRAME) { 
    275  
    276             pjmedia_jb_state jb_state; 
    277  
    278             /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */ 
    279             pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME); 
    280  
    281             /* Get the state of jitter buffer */ 
    282             pjmedia_jbuf_get_state(stream->jb, &jb_state); 
    283  
    284             /* Always activate PLC when it's available.. */ 
    285             if (stream->codec->op->recover &&  
    286                 stream->codec_param.setting.plc)  
    287             { 
    288                 pjmedia_frame frame_out; 
    289  
    290                 do { 
    291                     frame_out.buf = p_out_samp + samples_count; 
    292                     frame_out.size = frame->size - samples_count*2; 
    293                     status = (*stream->codec->op->recover)(stream->codec, 
    294                                                            frame_out.size, 
    295                                                            &frame_out); 
    296                     if (status != PJ_SUCCESS) 
    297                         break; 
    298                     samples_count += samples_per_frame; 
    299  
    300                 } while (samples_count < samples_required); 
    301  
    302                 if (stream->jb_last_frm != frame_type) { 
    303                     PJ_LOG(5,(stream->port.info.name.ptr,  
    304                               "Jitter buffer is bufferring with plc (prefetch=%d)", 
    305                               jb_state.prefetch)); 
    306                 } 
    307  
    308             }  
    309  
    310             if (samples_count < samples_required) { 
    311                 pjmedia_zero_samples(p_out_samp + samples_count, 
    312                                      samples_required - samples_count); 
    313                 samples_count = samples_required; 
    314                 PJ_LOG(5,(stream->port.info.name.ptr,  
    315                           "Jitter buffer is bufferring (prefetch=%d)..",  
    316                           jb_state.prefetch)); 
    317             } 
    318  
    319             stream->jb_last_frm = frame_type; 
    320             break; 
    321  
    322         } else { 
    323             /* Got "NORMAL" frame from jitter buffer */ 
    324             pjmedia_frame frame_in, frame_out; 
    325  
    326             /* Decode */ 
    327             frame_in.buf = channel->out_pkt; 
    328             frame_in.size = stream->frame_size; 
    329             frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */ 
    330  
    331             frame_out.buf = p_out_samp + samples_count; 
    332             frame_out.size = frame->size - samples_count*BYTES_PER_SAMPLE; 
    333             status = stream->codec->op->decode( stream->codec, &frame_in, 
    334                                                 frame_out.size, &frame_out); 
    335             if (status != 0) { 
    336                 LOGERR_((port->info.name.ptr, "codec decode() error",  
    337                          status)); 
    338  
    339                 pjmedia_zero_samples(p_out_samp + samples_count,  
    340                                      samples_per_frame); 
    341             } 
    342         } 
    343  
    344         stream->jb_last_frm = frame_type; 
     278        jb_frame.buffer = p_out_samp + samples_count; 
     279        jb_frame.size = frame->size - samples_count*2; 
     280        status = pjmedia_jb2_get_frame(stream->jb, &jb_frame); 
    345281    } 
    346282 
     
    1000936    pj_mutex_lock( stream->jb_mutex ); 
    1001937    if (seq_st.status.flag.restart) { 
    1002         status = pjmedia_jbuf_reset(stream->jb); 
     938        status = pjmedia_jb2_reset(stream->jb); 
    1003939        PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 
    1004940 
     
    1014950        unsigned samples_per_frame; 
    1015951        pjmedia_frame frames[MAX]; 
     952        pjmedia_jb2_frame jb_frame; 
    1016953 
    1017954        /* Get the timestamp of the first sample */ 
     
    1039976                             
    1040977        for (i=0; i<count; ++i) { 
    1041             unsigned ext_seq; 
    1042  
    1043             ext_seq = (unsigned)(frames[i].timestamp.u64 / 
    1044                                  samples_per_frame); 
    1045             pjmedia_jbuf_put_frame(stream->jb, frames[i].buf,  
    1046                                    frames[i].size, ext_seq); 
    1047  
     978            jb_frame.buffer = frames[i].buf; 
     979            jb_frame.pt = (pj_uint8_t)hdr->pt; 
     980            jb_frame.seq = ntohs(hdr->seq); 
     981            jb_frame.size = frames[i].size; 
     982            jb_frame.ts = ntohl(hdr->ts) + samples_per_frame*i; 
     983            jb_frame.type = PJMEDIA_JB_FT_NORMAL_FRAME; 
     984             
     985            status = pjmedia_jb2_put_frame(stream->jb, &jb_frame); 
     986            if (status != PJ_SUCCESS) { 
     987                LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error",  
     988                        status)); 
     989            } 
    1048990        } 
    1049991    } 
     992 
    1050993    pj_mutex_unlock( stream->jb_mutex ); 
    1051  
    1052994 
    1053995    /* Check if now is the time to transmit RTCP SR/RR report. 
     
    1057999    if (stream->dir == PJMEDIA_DIR_DECODING) { 
    10581000        check_tx_rtcp(stream, pj_ntohl(hdr->ts)); 
    1059     } 
    1060  
    1061     if (status != 0) { 
    1062         LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error",  
    1063                 status)); 
    1064         return; 
    10651001    } 
    10661002} 
     
    11611097    pjmedia_stream *stream; 
    11621098    pj_str_t name; 
    1163     unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; 
    11641099    pj_status_t status; 
     1100    pjmedia_jb2_setting jb_setting; 
     1101    pjmedia_jb2_cb jb_cb; 
    11651102 
    11661103    PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); 
     
    13161253 
    13171254    /* Init jitter buffer parameters: */ 
    1318     if (info->jb_max > 0) 
    1319         jb_max = info->jb_max; 
    1320     else 
    1321         jb_max = 360 / stream->codec_param.info.frm_ptime; 
    1322  
    1323     if (info->jb_min_pre >= 0) 
    1324         jb_min_pre = info->jb_min_pre; 
    1325     else 
    1326         jb_min_pre = 60 / stream->codec_param.info.frm_ptime; 
    1327  
    1328     if (info->jb_max_pre > 0) 
    1329         jb_max_pre = info->jb_max_pre; 
    1330     else 
    1331         jb_max_pre = 240 / stream->codec_param.info.frm_ptime; 
    1332  
    1333     if (info->jb_init >= 0) 
    1334         jb_init = info->jb_init; 
    1335     else 
    1336         jb_init = (jb_min_pre + jb_max_pre) / 2; 
    1337  
     1255    pj_bzero(&jb_setting, sizeof(jb_setting)); 
     1256    jb_setting.samples_per_frame = info->fmt.clock_rate *  
     1257                                   stream->codec_param.info.frm_ptime / 
     1258                                   1000; 
     1259    jb_setting.frame_size = jb_setting.samples_per_frame *  
     1260                            stream->codec_param.info.pcm_bits_per_sample / 8; 
     1261    jb_setting.max_frames = 0; 
     1262 
     1263    pj_bzero(&jb_cb, sizeof(jb_cb)); 
     1264    jb_cb.decode = &jb_decode; 
     1265    jb_cb.plc = &jb_plc; 
     1266    jb_cb.cng = NULL; //&jb_cng; 
     1267    jb_cb.user_data = stream; 
    13381268 
    13391269    /* Create jitter buffer */ 
    1340     status = pjmedia_jbuf_create(pool, &stream->port.info.name, 
    1341                                  stream->frame_size,  
    1342                                  stream->codec_param.info.frm_ptime, 
    1343                                  jb_max, &stream->jb); 
     1270    status = pjmedia_jb2_create(pool, &stream->port.info.name, &jb_setting,  
     1271                                &jb_cb, &stream->jb); 
     1272 
    13441273    if (status != PJ_SUCCESS) 
    13451274        goto err_cleanup; 
    13461275 
    1347  
    1348     /* Set up jitter buffer */ 
    1349     pjmedia_jbuf_set_adaptive( stream->jb, jb_init, jb_min_pre, jb_max_pre); 
    13501276 
    13511277    /* Create decoder channel: */ 
     
    14171343    } 
    14181344 
     1345    /* Destroy JB */ 
     1346    if (stream->jb) { 
     1347        pjmedia_jb2_destroy(stream->jb); 
     1348        stream->jb = NULL; 
     1349    } 
     1350 
    14191351    /* Free mutex */ 
    14201352     
     
    15081440        /* Also reset jitter buffer */ 
    15091441        pj_mutex_lock( stream->jb_mutex ); 
    1510         pjmedia_jbuf_reset(stream->jb); 
     1442        pjmedia_jb2_reset(stream->jb); 
    15111443        pj_mutex_unlock( stream->jb_mutex ); 
    15121444 
Note: See TracChangeset for help on using the changeset viewer.