Changeset 3835


Ignore:
Timestamp:
Oct 23, 2011 5:23:55 AM (13 years ago)
Author:
bennylp
Message:

Fixed #1392: Immediately decode incoming frames to avoid loosing key frames when the jbuf is full and improve latency

Location:
pjproject/trunk/pjmedia
Files:
4 edited

Legend:

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

    r3671 r3835  
    10461046 
    10471047/** 
     1048 * Video stream will discard old picture from the jitter buffer as soon as 
     1049 * new picture is received, to reduce latency. 
     1050 * 
     1051 * Default: 0 
     1052 */ 
     1053#ifndef PJMEDIA_VID_STREAM_SKIP_PACKETS_TO_REDUCE_LATENCY 
     1054#   define PJMEDIA_VID_STREAM_SKIP_PACKETS_TO_REDUCE_LATENCY    0 
     1055#endif 
     1056 
     1057/** 
    10481058 * @} 
    10491059 */ 
  • pjproject/trunk/pjmedia/include/pjmedia/jbuf.h

    r3664 r3835  
    390390                                            unsigned frame_cnt); 
    391391 
     392/** 
     393 * Check if the jitter buffer is full. 
     394 * 
     395 * @param jb            The jitter buffer. 
     396 * 
     397 * @return              PJ_TRUE if it is full. 
     398 */ 
     399PJ_DECL(pj_bool_t) pjmedia_jbuf_is_full(const pjmedia_jbuf *jb); 
     400 
    392401 
    393402/** 
  • pjproject/trunk/pjmedia/src/pjmedia/jbuf.c

    r3664 r3835  
    636636} 
    637637 
     638PJ_DEF(pj_bool_t) pjmedia_jbuf_is_full(const pjmedia_jbuf *jb) 
     639{ 
     640    return jb->jb_framelist.size == jb->jb_framelist.max_count; 
     641} 
    638642 
    639643static void jbuf_calculate_jitter(pjmedia_jbuf *jb) 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r3802 r3835  
    6969#endif 
    7070 
    71  
    7271/** 
    7372 * Media channel. 
     
    8281    void                   *buf;            /**< Output buffer.             */ 
    8382    unsigned                buf_size;       /**< Size of output buffer.     */ 
    84     unsigned                buf_len;        /**< Length of data in buffer.  */ 
    8583    pjmedia_rtp_session     rtp;            /**< RTP session.               */ 
    8684} pjmedia_vid_channel; 
     
    121119    pj_uint32_t              rtcp_interval; /**< Interval, in timestamp.    */ 
    122120    pj_bool_t                initial_rr;    /**< Initial RTCP RR sent       */ 
     121 
     122    unsigned                 dec_max_size;  /**< Size of decoded/raw picture*/ 
     123    pjmedia_frame            dec_frame;     /**< Current decoded frame.     */ 
    123124 
    124125    unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
     
    150151}; 
    151152 
     153/* Prototypes */ 
     154static pj_status_t decode_frame(pjmedia_vid_stream *stream, 
     155                                pjmedia_frame *frame); 
    152156 
    153157/* 
     
    636640    } 
    637641 
     642    pj_mutex_lock( stream->jb_mutex ); 
     643 
     644    /* Quickly see if there may be a full picture in the jitter buffer, and 
     645     * decode them if so. More thorough check will be done in decode_frame(). 
     646     */ 
     647    if ((pj_ntohl(hdr->ts) != stream->dec_frame.timestamp.u32.lo) || hdr->m) { 
     648        if (PJMEDIA_VID_STREAM_SKIP_PACKETS_TO_REDUCE_LATENCY) { 
     649            /* Always decode whenever we have picture in jb and 
     650             * overwrite already decoded picture if necessary 
     651             */ 
     652            pj_size_t old_size = stream->dec_frame.size; 
     653 
     654            stream->dec_frame.size = stream->dec_max_size; 
     655            if (decode_frame(stream, &stream->dec_frame) != PJ_SUCCESS) { 
     656                stream->dec_frame.size = old_size; 
     657            } 
     658        } else { 
     659            /* Only decode if we don't already have decoded one, 
     660             * unless the jb is full. 
     661             */ 
     662            pj_bool_t can_decode = PJ_FALSE; 
     663 
     664            if (pjmedia_jbuf_is_full(stream->jb)) { 
     665                can_decode = PJ_TRUE; 
     666            } 
     667            else if (stream->dec_frame.size == 0) { 
     668                can_decode = PJ_TRUE; 
     669            } 
     670 
     671            if (can_decode) { 
     672                stream->dec_frame.size = stream->dec_max_size; 
     673                if (decode_frame(stream, &stream->dec_frame) != PJ_SUCCESS) { 
     674                    stream->dec_frame.size = 0; 
     675                } 
     676            } 
     677        } 
     678    } 
    638679 
    639680    /* Put "good" packet to jitter buffer, or reset the jitter buffer 
    640681     * when RTP session is restarted. 
    641682     */ 
    642     pj_mutex_lock( stream->jb_mutex ); 
    643683    if (seq_st.status.flag.restart) { 
    644684        status = pjmedia_jbuf_reset(stream->jb); 
     
    816856            if (stream->send_err_cnt++ == 0) { 
    817857                LOGERR_((channel->port.info.name.ptr, 
    818                          "Transport send_rtp() error (repeated %d times)", 
     858                         "Transport send_rtp() error", 
    819859                         status)); 
    820                 if (stream->send_err_cnt > COUNT_TO_REPORT) 
    821                     stream->send_err_cnt = 0; 
    822860            } 
     861            if (stream->send_err_cnt > COUNT_TO_REPORT) 
     862                stream->send_err_cnt = 0; 
    823863            /* Ignore this error */ 
    824864        } 
     
    874914} 
    875915 
    876 static pj_status_t get_frame(pjmedia_port *port, 
    877                              pjmedia_frame *frame) 
    878 { 
    879     pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata; 
     916/* Decode one image from jitter buffer */ 
     917static pj_status_t decode_frame(pjmedia_vid_stream *stream, 
     918                                pjmedia_frame *frame) 
     919{ 
    880920    pjmedia_vid_channel *channel = stream->dec; 
    881921    pj_uint32_t last_ts = 0; 
     
    885925    pj_status_t status; 
    886926 
    887     /* Return no frame is channel is paused */ 
    888     if (channel->paused) { 
    889         frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    890         return PJ_SUCCESS; 
    891     } 
    892  
    893927    /* Repeat get payload from the jitter buffer until all payloads with same 
    894928     * timestamp are collected. 
    895929     */ 
    896     channel->buf_len = 0; 
    897  
    898     /* Lock jitter buffer mutex first */ 
    899     pj_mutex_lock( stream->jb_mutex ); 
    900930 
    901931    /* Check if we got a decodable frame */ 
     
    928958 
    929959        /* Generate frame bitstream from the payload */ 
    930         channel->buf_len = 0; 
    931  
    932960        if (cnt > stream->rx_frame_cnt) { 
    933             PJ_LOG(1,(port->info.name.ptr, 
     961            PJ_LOG(1,(channel->port.info.name.ptr, 
    934962                      "Discarding %u frames because array is full!", 
    935963                      cnt - stream->rx_frame_cnt)); 
     
    967995                                          frame->size, frame); 
    968996        if (status != PJ_SUCCESS) { 
    969             LOGERR_((port->info.name.ptr, "codec decode() error", 
     997            LOGERR_((channel->port.info.name.ptr, "codec decode() error", 
    970998                     status)); 
    971999            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     
    9751003        pjmedia_jbuf_remove_frame(stream->jb, cnt); 
    9761004    } 
    977  
    978     /* Unlock jitter buffer mutex. */ 
    979     pj_mutex_unlock( stream->jb_mutex ); 
    9801005 
    9811006    /* Learn remote frame rate after successful decoding */ 
     
    10311056    } 
    10321057 
     1058    return got_frame ? PJ_SUCCESS : PJ_ENOTFOUND; 
     1059} 
     1060 
     1061 
     1062static pj_status_t get_frame(pjmedia_port *port, 
     1063                             pjmedia_frame *frame) 
     1064{ 
     1065    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata; 
     1066    pjmedia_vid_channel *channel = stream->dec; 
     1067 
     1068    /* Return no frame is channel is paused */ 
     1069    if (channel->paused) { 
     1070        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     1071        frame->size = 0; 
     1072        return PJ_SUCCESS; 
     1073    } 
     1074 
     1075    pj_mutex_lock( stream->jb_mutex ); 
     1076 
     1077    if (stream->dec_frame.size == 0) { 
     1078        /* Don't have frame in buffer, try to decode one */ 
     1079        if (decode_frame(stream, frame) != PJ_SUCCESS) { 
     1080            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     1081            frame->size = 0; 
     1082        } 
     1083    } else { 
     1084        if (frame->size < stream->dec_frame.size) { 
     1085            PJ_LOG(4,(stream->dec->port.info.name.ptr, 
     1086                      "Error: not enough buffer for decoded frame " 
     1087                      "(supplied=%d, required=%d)", 
     1088                      (int)frame->size, (int)stream->dec_frame.size)); 
     1089            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     1090            frame->size = 0; 
     1091        } else { 
     1092            frame->type = stream->dec_frame.type; 
     1093            frame->timestamp = stream->dec_frame.timestamp; 
     1094            frame->size = stream->dec_frame.size; 
     1095            pj_memcpy(frame->buf, stream->dec_frame.buf, frame->size); 
     1096        } 
     1097 
     1098        stream->dec_frame.size = 0; 
     1099    } 
     1100 
     1101    pj_mutex_unlock( stream->jb_mutex ); 
     1102 
    10331103    return PJ_SUCCESS; 
    10341104} 
    1035  
    10361105 
    10371106/* 
     
    10811150     
    10821151    /* Allocate buffer for outgoing packet. */ 
    1083     channel->buf_size = sizeof(pjmedia_rtp_hdr) + stream->frame_size; 
    1084  
    1085     /* It should big enough to hold (minimally) RTCP SR with an SDES. */ 
    1086     min_out_pkt_size =  sizeof(pjmedia_rtcp_sr_pkt) + 
    1087                         sizeof(pjmedia_rtcp_common) + 
    1088                         (4 + stream->cname.slen) + 
    1089                         32; 
    1090  
    1091     if (channel->buf_size < min_out_pkt_size) 
    1092         channel->buf_size = min_out_pkt_size; 
    1093  
    1094     channel->buf = pj_pool_alloc(pool, channel->buf_size); 
    1095     PJ_ASSERT_RETURN(channel->buf != NULL, PJ_ENOMEM); 
     1152    if (dir == PJMEDIA_DIR_ENCODING) { 
     1153        channel->buf_size = sizeof(pjmedia_rtp_hdr) + stream->frame_size; 
     1154 
     1155        /* It should big enough to hold (minimally) RTCP SR with an SDES. */ 
     1156        min_out_pkt_size =  sizeof(pjmedia_rtcp_sr_pkt) + 
     1157                            sizeof(pjmedia_rtcp_common) + 
     1158                            (4 + stream->cname.slen) + 
     1159                            32; 
     1160 
     1161        if (channel->buf_size < min_out_pkt_size) 
     1162            channel->buf_size = min_out_pkt_size; 
     1163 
     1164        channel->buf = pj_pool_alloc(pool, channel->buf_size); 
     1165        PJ_ASSERT_RETURN(channel->buf != NULL, PJ_ENOMEM); 
     1166    } 
    10961167 
    10971168    /* Create RTP and RTCP sessions: */ 
     
    11571228    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 
    11581229    int frm_ptime, chunks_per_frm; 
    1159     pjmedia_video_format_detail *vfd_enc; 
     1230    pjmedia_video_format_detail *vfd_enc, *vfd_dec; 
    11601231    char *p; 
    11611232    unsigned mtu; 
     
    12151286    vfd_enc = pjmedia_format_get_video_format_detail( 
    12161287                                        &info->codec_param->enc_fmt, PJ_TRUE); 
     1288    vfd_dec = pjmedia_format_get_video_format_detail( 
     1289                                        &info->codec_param->dec_fmt, PJ_TRUE); 
    12171290 
    12181291    /* Init stream: */ 
     
    12971370    if (status != PJ_SUCCESS) 
    12981371        return status; 
     1372 
     1373    /* Create temporary buffer for immediate decoding */ 
     1374    stream->dec_max_size = vfd_dec->size.w * vfd_dec->size.h * 4; 
     1375    stream->dec_frame.buf = pj_pool_alloc(pool, stream->dec_max_size); 
    12991376 
    13001377    /* Init jitter buffer parameters: */ 
Note: See TracChangeset for help on using the changeset viewer.