Changeset 5887


Ignore:
Timestamp:
Sep 19, 2018 8:26:41 AM (12 months ago)
Author:
nanang
Message:

Close #2152: Updated video stream to delay video frame decoding, the minimum delay is configurable via PJMEDIA_VID_STREAM_DECODE_MIN_DELAY_MSEC.

Location:
pjproject/trunk/pjmedia
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/config.h

    r5820 r5887  
    14941494#endif 
    14951495 
     1496 
    14961497/** 
    14971498 * Specify the number of keyframe needed to be sent after the stream is  
     
    15041505#endif 
    15051506 
     1507 
    15061508/** 
    15071509 * Specify the interval to send keyframe after the stream is created, in msec. 
     
    15151517 
    15161518/** 
     1519 * Specify minimum delay of video decoding, in milliseconds. Lower value may 
     1520 * degrade video quality significantly in a bad network environment (e.g: 
     1521 * with persistent late and out-of-order RTP packets). Note that the value 
     1522 * must be lower than jitter buffer maximum delay (configurable via 
     1523 * pjmedia_stream_info.jb_max or pjsua_media_config.jb_max). 
     1524 * 
     1525 * Default : 100 
     1526 */ 
     1527#ifndef PJMEDIA_VID_STREAM_DECODE_MIN_DELAY_MSEC 
     1528#   define PJMEDIA_VID_STREAM_DECODE_MIN_DELAY_MSEC         100 
     1529#endif 
     1530 
     1531 
     1532 
     1533/** 
    15171534 * @} 
    15181535 */ 
  • pjproject/trunk/pjmedia/include/pjmedia/jbuf.h

    r5803 r5887  
    103103    unsigned    min_prefetch;       /**< Minimum allowed prefetch, in frms. */ 
    104104    unsigned    max_prefetch;       /**< Maximum allowed prefetch, in frms. */ 
     105    unsigned    max_count;          /**< Jitter buffer capacity, in frames. */ 
    105106 
    106107    /* Status */ 
  • pjproject/trunk/pjmedia/src/pjmedia/jbuf.c

    r5803 r5887  
    11611161    state->min_prefetch = jb->jb_min_prefetch; 
    11621162    state->max_prefetch = jb->jb_max_prefetch; 
     1163    state->max_count = jb->jb_max_count; 
    11631164 
    11641165    state->burst = jb->jb_eff_level; 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r5788 r5887  
    140140    pjmedia_ratio            dec_max_fps;   /**< Max fps of decoding dir.   */ 
    141141    pjmedia_frame            dec_frame;     /**< Current decoded frame.     */ 
     142    unsigned                 dec_delay_cnt; /**< Decoding delay (in frames).*/ 
    142143    pjmedia_event            fmt_event;     /**< Buffered fmt_changed event 
    143144                                                 to avoid deadlock          */ 
     
    11281129{ 
    11291130    pjmedia_vid_channel *channel = stream->dec; 
    1130     pj_uint32_t last_ts = 0; 
     1131    pj_uint32_t last_ts = 0, frm_ts = 0; 
    11311132    int frm_first_seq = 0, frm_last_seq = 0; 
    11321133    pj_bool_t got_frame = PJ_FALSE; 
    1133     unsigned cnt; 
     1134    unsigned cnt, frm_pkt_cnt = 0, frm_cnt = 0; 
    11341135    pj_status_t status; 
    11351136 
     
    11391140 
    11401141    /* Check if we got a decodable frame */ 
    1141     for (cnt=0; ; ++cnt) { 
     1142    for (cnt=0; ; ) { 
    11421143        char ptype; 
    11431144        pj_uint32_t ts; 
     
    11481149                                &ptype, NULL, &ts, &seq); 
    11491150        if (ptype == PJMEDIA_JB_NORMAL_FRAME) { 
     1151            if (stream->last_dec_ts ==  ts) { 
     1152                /* Remove any late packet (the frame has been decoded) */ 
     1153                pjmedia_jbuf_remove_frame(stream->jb, 1); 
     1154                continue; 
     1155            } 
     1156 
    11501157            if (last_ts == 0) { 
    11511158                last_ts = ts; 
     1159 
     1160                /* Init timestamp and first seq of the first frame */ 
     1161                frm_ts = ts; 
    11521162                frm_first_seq = seq; 
    11531163            } 
    11541164            if (ts != last_ts) { 
    1155                 got_frame = PJ_TRUE; 
    1156                 break; 
     1165                last_ts = ts; 
     1166                if (frm_pkt_cnt == 0) 
     1167                    frm_pkt_cnt = cnt; 
     1168 
     1169                /* Is it time to decode? Check with minimum delay setting */ 
     1170                if (++frm_cnt == stream->dec_delay_cnt) { 
     1171                    got_frame = PJ_TRUE; 
     1172                    break; 
     1173                } 
    11571174            } 
    1158             frm_last_seq = seq; 
    11591175        } else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
    11601176            /* No more packet in the jitter buffer */ 
    11611177            break; 
    11621178        } 
     1179 
     1180        ++cnt; 
    11631181    } 
    11641182 
     
    11661184        unsigned i; 
    11671185 
    1168         /* Generate frame bitstream from the payload */ 
    1169         if (cnt > stream->rx_frame_cnt) { 
     1186        /* Exclude any MISSING frames in the end of the packets array, as 
     1187         * it may be part of the next video frame (late packets). 
     1188         */ 
     1189        for (; frm_pkt_cnt > 1; --frm_pkt_cnt) { 
     1190            char ptype; 
     1191            pjmedia_jbuf_peek_frame(stream->jb, frm_pkt_cnt, NULL, NULL, &ptype, 
     1192                                    NULL, NULL, NULL); 
     1193            if (ptype == PJMEDIA_JB_NORMAL_FRAME) 
     1194                break; 
     1195        } 
     1196 
     1197        /* Check if the packet count for this frame exceeds the limit */ 
     1198        if (frm_pkt_cnt > stream->rx_frame_cnt) { 
    11701199            PJ_LOG(1,(channel->port.info.name.ptr, 
    11711200                      "Discarding %u frames because array is full!", 
    1172                       cnt - stream->rx_frame_cnt)); 
    1173             pjmedia_jbuf_remove_frame(stream->jb, cnt - stream->rx_frame_cnt); 
    1174             cnt = stream->rx_frame_cnt; 
    1175         } 
    1176  
    1177         for (i = 0; i < cnt; ++i) { 
     1201                      frm_pkt_cnt - stream->rx_frame_cnt)); 
     1202            pjmedia_jbuf_remove_frame(stream->jb, 
     1203                                      frm_pkt_cnt - stream->rx_frame_cnt); 
     1204            frm_pkt_cnt = stream->rx_frame_cnt; 
     1205        } 
     1206 
     1207        /* Generate frame bitstream from the payload */ 
     1208        for (i = 0; i < frm_pkt_cnt; ++i) { 
    11781209            char ptype; 
    11791210 
    11801211            stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_VIDEO; 
    1181             stream->rx_frames[i].timestamp.u64 = last_ts; 
     1212            stream->rx_frames[i].timestamp.u64 = frm_ts; 
    11821213            stream->rx_frames[i].bit_info = 0; 
    11831214 
     
    11881219                                    (const void**)&stream->rx_frames[i].buf, 
    11891220                                    &stream->rx_frames[i].size, &ptype, 
    1190                                     NULL, NULL, NULL); 
     1221                                    NULL, NULL, &frm_last_seq); 
    11911222 
    11921223            if (ptype != PJMEDIA_JB_NORMAL_FRAME) { 
     
    12001231 
    12011232        /* Decode */ 
    1202         status = pjmedia_vid_codec_decode(stream->codec, cnt, 
     1233        status = pjmedia_vid_codec_decode(stream->codec, frm_pkt_cnt, 
    12031234                                          stream->rx_frames, 
    12041235                                          (unsigned)frame->size, frame); 
     
    12101241        } 
    12111242 
    1212         pjmedia_jbuf_remove_frame(stream->jb, cnt); 
     1243        pjmedia_jbuf_remove_frame(stream->jb, frm_pkt_cnt); 
    12131244    } 
    12141245 
    12151246    /* Learn remote frame rate after successful decoding */ 
    1216     if (frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size) 
     1247    if (got_frame && frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size) 
    12171248    { 
    12181249        /* Only check remote frame rate when timestamp is not wrapping and 
    12191250         * sequence is increased by 1. 
    12201251         */ 
    1221         if (last_ts > stream->last_dec_ts && 
     1252        if (frm_ts > stream->last_dec_ts && 
    12221253            frm_first_seq - stream->last_dec_seq == 1) 
    12231254        { 
     
    12251256            pjmedia_video_format_detail *vfd; 
    12261257 
    1227             ts_diff = last_ts - stream->last_dec_ts; 
     1258            ts_diff = frm_ts - stream->last_dec_ts; 
    12281259            vfd = pjmedia_format_get_video_format_detail( 
    12291260                                    &channel->port.info.fmt, PJ_TRUE); 
     
    12421273                /* Update stream info */ 
    12431274                stream->info.codec_param->dec_fmt.det.vid.fps = vfd->fps; 
     1275 
     1276                /* Update the decoding delay as FPS updated */ 
     1277                { 
     1278                    pjmedia_jb_state jb_state; 
     1279                    pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     1280 
     1281                    stream->dec_delay_cnt =  
     1282                                    ((PJMEDIA_VID_STREAM_DECODE_MIN_DELAY_MSEC * 
     1283                                      vfd->fps.num) + 
     1284                                     (1000 * vfd->fps.denum) - 1) / 
     1285                                    (1000 * vfd->fps.denum); 
     1286                    if (stream->dec_delay_cnt < 1) 
     1287                        stream->dec_delay_cnt = 1; 
     1288                    if (stream->dec_delay_cnt > jb_state.max_count * 4/5) 
     1289                        stream->dec_delay_cnt = jb_state.max_count * 4/5; 
     1290                } 
    12441291 
    12451292                /* Publish PJMEDIA_EVENT_FMT_CHANGED event if frame rate 
     
    12751322        /* Update last frame seq and timestamp */ 
    12761323        stream->last_dec_seq = frm_last_seq; 
    1277         stream->last_dec_ts = last_ts; 
     1324        stream->last_dec_ts = frm_ts; 
    12781325    } 
    12791326 
     
    16941741    else 
    16951742        jb_init  = 0; 
     1743 
     1744    /* Calculate the decoding delay (in number of frames) based on FPS */ 
     1745    stream->dec_delay_cnt = ((PJMEDIA_VID_STREAM_DECODE_MIN_DELAY_MSEC * 
     1746                              vfd_dec->fps.num) + 
     1747                             (1000 * vfd_dec->fps.denum) - 1) / 
     1748                            (1000 * vfd_dec->fps.denum); 
     1749    if (stream->dec_delay_cnt < 1) 
     1750        stream->dec_delay_cnt = 1; 
     1751    if (stream->dec_delay_cnt > jb_max * 4/5) 
     1752        stream->dec_delay_cnt = jb_max * 4/5; 
    16961753 
    16971754    /* Allocate array for temporary storage for assembly of incoming 
Note: See TracChangeset for help on using the changeset viewer.