Ignore:
Timestamp:
Dec 10, 2010 11:04:30 AM (13 years ago)
Author:
bennylp
Message:

Migration of current video works from private repository to this repository. This closed #1176

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/stream.c

    r3387 r3392  
    7878    unsigned                out_pkt_size;   /**< Size of output buffer.     */ 
    7979    void                   *out_pkt;        /**< Output buffer.             */ 
     80    unsigned                out_pkt_len;    /**< Length of data in buffer.  */ 
    8081    pjmedia_rtp_session     rtp;            /**< RTP session.               */ 
    8182}; 
     
    178179                                                 received according to  
    179180                                                 'erroneous' definition     */ 
    180     pj_uint32_t              rtp_rx_last_ts;/**< Last received RTP timestamp 
    181                                                  for timestamp checking     */ 
    182181    unsigned                 rtp_rx_last_cnt;/**< Nb of frames in last pkt  */ 
    183182    unsigned                 rtp_rx_check_cnt; 
     
    209208    char                   *trace_jb_buf;           /**< Jitter tracing buffer.     */ 
    210209#endif 
     210 
     211    pj_uint32_t              rtp_rx_last_ts;        /**< Last received RTP timestamp*/ 
     212 
     213    pjmedia_vid_codec       *vcodec;                /**< Codec instance being used. */ 
     214    pjmedia_vid_codec_info   vcodec_info;           /**< Codec param.               */ 
     215    pjmedia_vid_codec_param  vcodec_param;          /**< Codec param.               */ 
     216 
    211217}; 
    212218 
     
    472478    pj_mutex_lock( stream->jb_mutex ); 
    473479 
    474     samples_required = stream->port.info.samples_per_frame; 
     480    samples_required = PJMEDIA_PIA_SPF(&stream->port.info); 
    475481    samples_per_frame = stream->codec_param.info.frm_ptime * 
    476482                        stream->codec_param.info.clock_rate * 
     
    726732     */ 
    727733 
    728     samples_required = stream->port.info.samples_per_frame; 
     734    samples_required = PJMEDIA_PIA_SPF(&stream->port.info); 
    729735    samples_per_frame = stream->codec_param.info.frm_ptime * 
    730736                        stream->codec_param.info.clock_rate * 
     
    877883    } 
    878884 
    879     digit->duration += stream->port.info.samples_per_frame; 
     885    digit->duration += PJMEDIA_PIA_SPF(&stream->port.info); 
    880886 
    881887    event->event = (pj_uint8_t)digit->event; 
     
    10881094    /* How many samples are needed */ 
    10891095    count = stream->codec_param.info.enc_ptime *  
    1090                 stream->port.info.clock_rate / 1000; 
     1096            PJMEDIA_PIA_SRATE(&stream->port.info) / 1000; 
    10911097 
    10921098    /* See if we have enough samples */ 
     
    11111117 */ 
    11121118static pj_status_t put_frame_imp( pjmedia_port *port,  
    1113                                   const pjmedia_frame *frame ) 
     1119                                  pjmedia_frame *frame ) 
    11141120{ 
    11151121    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     
    11521158        ts_len = (frame->size >> 1) / stream->codec_param.info.channel_cnt; 
    11531159    else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) 
    1154         ts_len = stream->port.info.samples_per_frame /  
    1155                  stream->port.info.channel_count; 
     1160        ts_len = PJMEDIA_PIA_SPF(&stream->port.info) / 
     1161                 PJMEDIA_PIA_CCNT(&stream->port.info); 
    11561162    else 
    11571163        ts_len = 0; 
     
    12201226    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
    12211227               frame->buf == NULL && 
    1222                stream->port.info.format.id == PJMEDIA_FORMAT_L16 && 
     1228               stream->port.info.fmt.id == PJMEDIA_FORMAT_L16 && 
    12231229               (stream->dir & PJMEDIA_DIR_ENCODING) && 
    12241230               stream->codec_param.info.frm_ptime * 
     
    13631369 */ 
    13641370static pj_status_t put_frame( pjmedia_port *port,  
    1365                               const pjmedia_frame *frame ) 
     1371                              pjmedia_frame *frame ) 
    13661372{ 
    13671373    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     
    14111417    if (stream->vad_enabled != stream->codec_param.setting.vad && 
    14121418        (stream->tx_duration - stream->ts_vad_disabled) >  
    1413         stream->port.info.clock_rate * PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) 
     1419           PJMEDIA_PIA_SRATE(&stream->port.info) * 
     1420          PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) 
    14141421    { 
    14151422        stream->codec_param.setting.vad = stream->vad_enabled; 
     
    15741581    unsigned payloadlen; 
    15751582    pjmedia_rtp_status seq_st; 
    1576     pj_bool_t check_pt; 
    15771583    pj_status_t status; 
    15781584    pj_bool_t pkt_discarded = PJ_FALSE; 
     
    16041610     * the incoming packet. 
    16051611     */ 
    1606     check_pt = (hdr->pt != stream->rx_event_pt) && PJMEDIA_STREAM_CHECK_RTP_PT; 
    1607     pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, check_pt); 
    1608 #if !PJMEDIA_STREAM_CHECK_RTP_PT 
    1609     if (!check_pt && hdr->pt != channel->rtp.out_pt && 
    1610         hdr->pt != stream->rx_event_pt) 
    1611     { 
    1612         seq_st.status.flag.badpt = 1; 
    1613     } 
    1614 #endif 
     1612    pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, 
     1613                                hdr->pt != stream->rx_event_pt); 
    16151614    if (seq_st.status.value) { 
    16161615        TRC_  ((stream->port.info.name.ptr,  
     
    16731672        PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 
    16741673 
     1674    } else if (stream->vcodec) { 
     1675        pj_timestamp ts; 
     1676        pj_uint8_t *p; 
     1677        pj_size_t p_len; 
     1678 
     1679        /* Video stream */ 
     1680 
     1681        ts.u64 = pj_ntohl(hdr->ts); 
     1682 
     1683        /* Put any buffered bitstream if timestamp is changed, 
     1684         * in case of RTP packet lost. 
     1685         */ 
     1686        if (stream->rtp_rx_last_ts != ts.u64 && channel->out_pkt_len) 
     1687        { 
     1688            int seq; 
     1689 
     1690            seq = stream->rtp_rx_last_ts/stream->rtp_rx_ts_len_per_frame; 
     1691            pjmedia_jbuf_put_frame(stream->jb, channel->out_pkt, 
     1692                                   channel->out_pkt_len, seq); 
     1693            channel->out_pkt_len = 0; 
     1694        } 
     1695 
     1696        p = (pj_uint8_t*)channel->out_pkt + channel->out_pkt_len; 
     1697        p_len = channel->out_pkt_size - channel->out_pkt_len; 
     1698 
     1699        /* Parse the payload. */ 
     1700        status = (*stream->vcodec->op->unpacketize)( 
     1701                                            stream->vcodec, 
     1702                                            payload, payloadlen, 
     1703                                            p, &p_len); 
     1704        if (status != PJ_SUCCESS) { 
     1705            LOGERR_((stream->port.info.name.ptr,  
     1706                     "Codec parse() error",  
     1707                     status)); 
     1708            channel->out_pkt_len = 0; 
     1709        } else { 
     1710            channel->out_pkt_len += p_len; 
     1711            if (channel->out_pkt_len > channel->out_pkt_size) { 
     1712                channel->out_pkt_len = channel->out_pkt_size; 
     1713                PJ_LOG(3, (THIS_FILE, "Video bitstream trucated because of" 
     1714                           "not enough buffer")); 
     1715            } 
     1716 
     1717            /* Check if RTP header specifies end of frame mark */ 
     1718            PJ_TODO(find_better_way_to_find_out_end_of_frame_mark); 
     1719            if (hdr->m) { 
     1720                int seq; 
     1721 
     1722                seq = (int)(ts.u64/stream->rtp_rx_ts_len_per_frame); 
     1723                pjmedia_jbuf_put_frame(stream->jb, channel->out_pkt, 
     1724                                       channel->out_pkt_len, seq); 
     1725                channel->out_pkt_len = 0; 
     1726            } 
     1727        } 
     1728 
     1729        stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 
     1730         
    16751731    } else { 
    16761732        /* 
     
    17271783                     * to avoid wrong decision because of silence frames. 
    17281784                     */ 
    1729                     if (stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 && 
    1730                         (peer_frm_ts_diff==stream->port.info.samples_per_frame 
     1785                    if(stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 && 
     1786                       (peer_frm_ts_diff==PJMEDIA_PIA_SPF(&stream->port.info) 
    17311787                         || peer_frm_ts_diff ==  
    1732                                     stream->port.info.samples_per_frame >> 1)) 
     1788                                    PJMEDIA_PIA_SPF(&stream->port.info) >>1)) 
    17331789                    { 
    17341790                        if (peer_frm_ts_diff < stream->rtp_rx_ts_len_per_frame) 
     
    18831939    /* Allocate buffer for outgoing packet. */ 
    18841940 
    1885     channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +  
    1886                             stream->codec_param.info.max_bps *  
    1887                             PJMEDIA_MAX_FRAME_DURATION_MS /  
    1888                             8 / 1000; 
    1889  
    1890     if (channel->out_pkt_size > PJMEDIA_MAX_MTU) 
    1891         channel->out_pkt_size = PJMEDIA_MAX_MTU; 
     1941    if (param->type == PJMEDIA_TYPE_VIDEO) { 
     1942        channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +  
     1943                                stream->frame_size; 
     1944    } else if (param->type == PJMEDIA_TYPE_AUDIO) { 
     1945        channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +  
     1946                                stream->codec_param.info.max_bps *  
     1947                                PJMEDIA_MAX_FRAME_DURATION_MS /  
     1948                                8 / 1000; 
     1949        if (channel->out_pkt_size > PJMEDIA_MAX_MTU) 
     1950            channel->out_pkt_size = PJMEDIA_MAX_MTU; 
     1951    } else { 
     1952        return PJ_ENOTSUP; 
     1953    } 
    18921954 
    18931955    /* It should big enough to hold (minimally) RTCP SR with an SDES. */ 
     
    19271989} 
    19281990 
     1991 
     1992static pj_status_t video_stream_create(pjmedia_endpt *endpt, 
     1993                                       pj_pool_t *pool, 
     1994                                       const pjmedia_stream_info *info, 
     1995                                       pjmedia_transport *tp, 
     1996                                       void *user_data, 
     1997                                       pjmedia_stream **p_stream); 
    19291998 
    19301999/* 
     
    19432012    pj_str_t name; 
    19442013    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 
     2014    pjmedia_audio_format_detail *afd; 
    19452015    char *p; 
    19462016    pj_status_t status; 
     
    19482018    PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); 
    19492019 
     2020 
     2021    if (info->type == PJMEDIA_TYPE_VIDEO) { 
     2022        status = video_stream_create(endpt, pool, info, tp,  
     2023                                     user_data, &stream); 
     2024        if (status != PJ_SUCCESS) 
     2025            goto err_cleanup; 
     2026 
     2027        *p_stream = stream; 
     2028        return PJ_SUCCESS; 
     2029    } 
    19502030 
    19512031    /* Allocate the media stream: */ 
     
    19652045                           info->fmt.clock_rate, info->fmt.channel_cnt, 
    19662046                           16, 80); 
     2047    afd = pjmedia_format_get_audio_format_detail(&stream->port.info.fmt, 1); 
    19672048 
    19682049    /* Init port. */ 
    19692050 
    1970     pj_strdup(pool, &stream->port.info.encoding_name, &info->fmt.encoding_name); 
    1971     stream->port.info.clock_rate = info->fmt.clock_rate; 
    1972     stream->port.info.channel_count = info->fmt.channel_cnt; 
     2051    //No longer there in 2.0 
     2052    //pj_strdup(pool, &stream->port.info.encoding_name, &info->fmt.encoding_name); 
     2053    afd->clock_rate = info->fmt.clock_rate; 
     2054    afd->channel_count = info->fmt.channel_cnt; 
    19732055    stream->port.port_data.pdata = stream; 
    19742056 
     
    20412123 
    20422124    /* Set additional info and callbacks. */ 
    2043     stream->port.info.bits_per_sample = 16; 
    2044     stream->port.info.samples_per_frame = info->fmt.clock_rate *  
    2045                                           stream->codec_param.info.channel_cnt * 
    2046                                           stream->codec_param.info.frm_ptime * 
    2047                                           stream->codec_param.setting.frm_per_pkt / 
    2048                                           1000; 
    2049     stream->port.info.format.id = stream->codec_param.info.fmt_id; 
     2125    afd->bits_per_sample = 16; 
     2126    afd->frame_time_usec = stream->codec_param.info.frm_ptime * 
     2127                           stream->codec_param.setting.frm_per_pkt * 1000; 
     2128    stream->port.info.fmt.id = stream->codec_param.info.fmt_id; 
    20502129    if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) { 
    20512130        /* Raw format */ 
    2052         stream->port.info.bytes_per_frame = stream->port.info.samples_per_frame * 
    2053                                             stream->port.info.bits_per_sample / 8; 
     2131        afd->avg_bps = afd->max_bps = afd->clock_rate * 
     2132                                      afd->bits_per_sample / 8; 
     2133 
    20542134 
    20552135        stream->port.put_frame = &put_frame; 
     
    20572137    } else { 
    20582138        /* Encoded format */ 
    2059         stream->port.info.bytes_per_frame = stream->codec_param.info.max_bps *  
    2060                                             stream->codec_param.info.frm_ptime * 
    2061                                             stream->codec_param.setting.frm_per_pkt / 
    2062                                             8 / 1000; 
    2063         if ((stream->codec_param.info.max_bps * stream->codec_param.info.frm_ptime * 
    2064             stream->codec_param.setting.frm_per_pkt) % 8000 != 0) 
     2139        afd->avg_bps = stream->codec_param.info.avg_bps; 
     2140        afd->max_bps = stream->codec_param.info.max_bps; 
     2141 
     2142        /* Not applicable for 2.0 
     2143        if ((stream->codec_param.info.max_bps * 
     2144             stream->codec_param.info.frm_ptime * 
     2145             stream->codec_param.setting.frm_per_pkt) % 8000 != 0) 
    20652146        { 
    20662147            ++stream->port.info.bytes_per_frame; 
     
    20682149        stream->port.info.format.bitrate = stream->codec_param.info.avg_bps; 
    20692150        stream->port.info.format.vad = (stream->codec_param.setting.vad != 0); 
     2151        */ 
    20702152 
    20712153        stream->port.put_frame = &put_frame; 
     
    20842166        stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 
    20852167                                      stream->codec_param.info.channel_cnt * 
    2086                                       stream->port.info.clock_rate / 1000; 
     2168                                      afd->clock_rate / 1000; 
    20872169 
    20882170        /* Set buffer size as twice the largest ptime value between 
     
    20902172         */ 
    20912173 
    2092         ptime = stream->port.info.samples_per_frame * 1000 / 
    2093                 stream->port.info.clock_rate; 
     2174        ptime = afd->frame_time_usec / 1000; 
    20942175 
    20952176        if (stream->codec_param.info.enc_ptime > ptime) 
     
    21022183 
    21032184        /* Allocate buffer */ 
    2104         stream->enc_buf_size = stream->port.info.clock_rate * ptime / 1000; 
     2185        stream->enc_buf_size = afd->clock_rate * ptime / 1000; 
    21052186        stream->enc_buf = (pj_int16_t*) 
    21062187                          pj_pool_alloc(pool, stream->enc_buf_size * 2); 
    21072188 
    21082189    } else { 
    2109         stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 
     2190        stream->enc_samples_per_pkt = PJMEDIA_AFD_SPF(afd); 
    21102191    } 
    21112192 
     
    21402221    stream->rtp_tx_ts_len_per_pkt = stream->enc_samples_per_pkt / 
    21412222                                     stream->codec_param.info.channel_cnt; 
    2142     stream->rtp_rx_ts_len_per_frame = stream->port.info.samples_per_frame /  
     2223    stream->rtp_rx_ts_len_per_frame = PJMEDIA_AFD_SPF(afd) / 
    21432224                                       stream->codec_param.info.channel_cnt; 
    21442225 
     
    22132294        rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
    22142295        rtcp_setting.clock_rate = info->fmt.clock_rate; 
    2215         rtcp_setting.samples_per_frame = stream->port.info.samples_per_frame; 
     2296        rtcp_setting.samples_per_frame = PJMEDIA_AFD_SPF(afd); 
    22162297 
    22172298#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) 
     
    24222503        pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); 
    24232504        stream->codec = NULL; 
     2505    } 
     2506 
     2507    if (stream->vcodec) { 
     2508        stream->vcodec->op->close(stream->vcodec); 
     2509        pjmedia_vid_codec_mgr_dealloc_codec(NULL, stream->vcodec); 
     2510        stream->vcodec = NULL; 
    24242511    } 
    24252512 
     
    27392826} 
    27402827 
     2828static pj_status_t put_vid_frame(pjmedia_port *port, 
     2829                                 pjmedia_frame *frame) 
     2830{ 
     2831    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     2832    pjmedia_channel *channel = stream->enc; 
     2833    pj_status_t status = 0; 
     2834    pjmedia_frame frame_out; 
     2835    unsigned rtp_ts_len; 
     2836    void *rtphdr; 
     2837    int rtphdrlen; 
     2838    unsigned processed = 0; 
     2839 
     2840 
     2841#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0 
     2842    /* If the interval since last sending packet is greater than 
     2843     * PJMEDIA_STREAM_KA_INTERVAL, send keep-alive packet. 
     2844     */ 
     2845    if (stream->use_ka) 
     2846    { 
     2847        pj_uint32_t dtx_duration; 
     2848 
     2849        dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent,  
     2850                                           &frame->timestamp); 
     2851        if (dtx_duration > 
     2852            PJMEDIA_STREAM_KA_INTERVAL * stream->port.info.clock_rate) 
     2853        { 
     2854            send_keep_alive_packet(stream); 
     2855            stream->last_frm_ts_sent = frame->timestamp; 
     2856        } 
     2857    } 
     2858#endif 
     2859 
     2860    /* Don't do anything if stream is paused */ 
     2861    if (channel->paused) { 
     2862        stream->enc_buf_pos = stream->enc_buf_count = 0; 
     2863        return PJ_SUCCESS; 
     2864    } 
     2865 
     2866    /* Increment transmit duration */ 
     2867    rtp_ts_len = stream->rtp_tx_ts_len_per_pkt; 
     2868    stream->tx_duration += rtp_ts_len; 
     2869 
     2870    /* Init frame_out buffer. */ 
     2871    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
     2872    frame_out.size = 0; 
     2873 
     2874    /* Encode! */ 
     2875    status = (*stream->vcodec->op->encode)(stream->vcodec, frame,  
     2876                                           channel->out_pkt_size -  
     2877                                           sizeof(pjmedia_rtp_hdr), 
     2878                                           &frame_out); 
     2879    if (status != PJ_SUCCESS) { 
     2880        LOGERR_((stream->port.info.name.ptr,  
     2881                "Codec encode() error", status)); 
     2882        return status; 
     2883    } 
     2884 
     2885 
     2886    while (processed < frame_out.size) { 
     2887        pj_uint8_t *payload, *rtp_pkt; 
     2888        pj_size_t payload_len; 
     2889 
     2890        /* Generate RTP payload */ 
     2891        status = (*stream->vcodec->op->packetize)( 
     2892                                           stream->vcodec, 
     2893                                           (pj_uint8_t*)frame_out.buf, 
     2894                                           frame_out.size, 
     2895                                           &processed, 
     2896                                           &payload, &payload_len); 
     2897        if (status != PJ_SUCCESS) { 
     2898            LOGERR_((stream->port.info.name.ptr,  
     2899                    "Codec pack() error", status)); 
     2900            return status; 
     2901        } 
     2902 
     2903        /* Encapsulate. */ 
     2904        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
     2905                                         channel->pt, 
     2906                                         (processed==frame_out.size?1:0), 
     2907                                         payload_len, 
     2908                                         rtp_ts_len,  
     2909                                         (const void**)&rtphdr,  
     2910                                         &rtphdrlen); 
     2911 
     2912        if (status != PJ_SUCCESS) { 
     2913            LOGERR_((stream->port.info.name.ptr,  
     2914                    "RTP encode_rtp() error", status)); 
     2915            return status; 
     2916        } 
     2917 
     2918        /* Next packets use same timestamp */ 
     2919        rtp_ts_len = 0; 
     2920 
     2921        rtp_pkt = payload - sizeof(pjmedia_rtp_hdr); 
     2922 
     2923        /* Copy RTP header to the beginning of packet */ 
     2924        pj_memcpy(rtp_pkt, rtphdr, sizeof(pjmedia_rtp_hdr)); 
     2925 
     2926        /* Send the RTP packet to the transport. */ 
     2927        pjmedia_transport_send_rtp(stream->transport, rtp_pkt,  
     2928                                   payload_len + sizeof(pjmedia_rtp_hdr)); 
     2929    } 
     2930 
     2931    /* Check if now is the time to transmit RTCP SR/RR report.  
     2932     * We only do this when stream direction is not "decoding only", because 
     2933     * when it is, check_tx_rtcp() will be handled by get_frame(). 
     2934     */ 
     2935    if (stream->dir != PJMEDIA_DIR_DECODING) { 
     2936        check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts)); 
     2937    } 
     2938 
     2939    /* Do nothing if we have nothing to transmit */ 
     2940    if (frame_out.size == 0) { 
     2941        if (stream->is_streaming) { 
     2942            PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence")); 
     2943            stream->is_streaming = PJ_FALSE; 
     2944        } 
     2945 
     2946        return PJ_SUCCESS; 
     2947    } 
     2948 
     2949 
     2950    /* Set RTP marker bit if currently not streaming */ 
     2951    if (stream->is_streaming == PJ_FALSE) { 
     2952        // RTP header M in video packet is usually for end of frame flag. 
     2953        //pjmedia_rtp_hdr *rtp = (pjmedia_rtp_hdr*) channel->out_pkt; 
     2954        //rtp->m = 1; 
     2955        PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut..")); 
     2956    } 
     2957 
     2958    stream->is_streaming = PJ_TRUE; 
     2959 
     2960    /* Update stat */ 
     2961    pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 
     2962    stream->rtcp.stat.rtp_tx_last_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
     2963    stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq); 
     2964 
     2965#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 
     2966    /* Update timestamp of last sending packet. */ 
     2967    stream->last_frm_ts_sent = frame->timestamp; 
     2968#endif 
     2969 
     2970    return PJ_SUCCESS; 
     2971} 
     2972 
     2973static pj_status_t get_vid_frame(pjmedia_port *port, 
     2974                                 pjmedia_frame *frame) 
     2975{ 
     2976    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     2977    pjmedia_channel *channel = stream->dec; 
     2978    pj_uint8_t *p_out_samp; 
     2979    pj_status_t status; 
     2980 
     2981 
     2982    /* Return no frame is channel is paused */ 
     2983    if (channel->paused) { 
     2984        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     2985        return PJ_SUCCESS; 
     2986    } 
     2987 
     2988    /* Repeat get frame from the jitter buffer and decode the frame 
     2989     * until we have enough frames according to codec's ptime. 
     2990     */ 
     2991 
     2992    /* Lock jitter buffer mutex first */ 
     2993    pj_mutex_lock( stream->jb_mutex ); 
     2994 
     2995    p_out_samp = (pj_uint8_t*) frame->buf; 
     2996    { 
     2997        char frame_type; 
     2998        pj_size_t frame_size; 
     2999        pj_uint32_t bit_info; 
     3000 
     3001        /* Get frame from jitter buffer. */ 
     3002        pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size, 
     3003                                &frame_type, &bit_info); 
     3004 
     3005#if TRACE_JB 
     3006        trace_jb_get(stream, frame_type, frame_size); 
     3007#endif 
     3008 
     3009        if (frame_type != PJMEDIA_JB_NORMAL_FRAME) { 
     3010            const char *with_plc = ""; 
     3011             
     3012            /* Activate PLC */ 
     3013            if (stream->vcodec->op->recover &&  
     3014                //stream->codec_param.setting.plc && 
     3015                stream->plc_cnt < stream->max_plc_cnt)  
     3016            { 
     3017                status = (*stream->codec->op->recover)(stream->codec, 
     3018                                                       frame->size, 
     3019                                                       frame); 
     3020 
     3021                ++stream->plc_cnt; 
     3022                with_plc = ", plc invoked"; 
     3023            } else { 
     3024                status = -1; 
     3025            } 
     3026 
     3027            if (status != PJ_SUCCESS) { 
     3028                /* Either PLC failed or PLC not supported/enabled */ 
     3029                //pjmedia_zero_samples(p_out_samp + samples_count, 
     3030                //                   samples_required - samples_count); 
     3031                frame->size = 0; 
     3032            } 
     3033 
     3034            if (frame_type != stream->jb_last_frm) { 
     3035                if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 
     3036                    pjmedia_jb_state jb_state; 
     3037 
     3038                    /* Report changing frame type event */ 
     3039                    pjmedia_jbuf_get_state(stream->jb, &jb_state); 
     3040                    PJ_LOG(5,(stream->port.info.name.ptr,  
     3041                              "Jitter buffer empty (prefetch=%d)%s",  
     3042                              jb_state.prefetch, with_plc)); 
     3043                } else { 
     3044                    /* Report changing frame type event */ 
     3045                    PJ_LOG(5,(stream->port.info.name.ptr, "Frame lost%s!", 
     3046                              (status == PJ_SUCCESS? ", recovered":""))); 
     3047                } 
     3048 
     3049                stream->jb_last_frm = frame_type; 
     3050                stream->jb_last_frm_cnt = 1; 
     3051            } else { 
     3052                stream->jb_last_frm_cnt++; 
     3053            } 
     3054 
     3055        } else { 
     3056            /* Got "NORMAL" frame from jitter buffer */ 
     3057            pjmedia_frame frame_in, frame_out; 
     3058 
     3059            stream->plc_cnt = 0; 
     3060 
     3061            /* Decode */ 
     3062            frame_in.buf = channel->out_pkt; 
     3063            frame_in.size = frame_size; 
     3064            frame_in.bit_info = bit_info; 
     3065            frame_in.type = PJMEDIA_FRAME_TYPE_VIDEO;  /* ignored */ 
     3066 
     3067            frame_out.buf = p_out_samp; 
     3068            frame_out.size = frame->size; 
     3069            status = stream->vcodec->op->decode(stream->vcodec, &frame_in, 
     3070                                                frame_out.size, &frame_out); 
     3071            if (status != 0) { 
     3072                LOGERR_((port->info.name.ptr, "codec decode() error",  
     3073                         status)); 
     3074 
     3075                //pjmedia_zero_samples(p_out_samp + samples_count,  
     3076                //                   samples_per_frame); 
     3077                frame_out.size = 0; 
     3078            } 
     3079 
     3080            if (stream->jb_last_frm != frame_type) { 
     3081                /* Report changing frame type event */ 
     3082                PJ_LOG(5,(stream->port.info.name.ptr,  
     3083                          "Jitter buffer starts returning normal frames " 
     3084                          "(after %d empty/lost)", 
     3085                          stream->jb_last_frm_cnt, stream->jb_last_frm)); 
     3086 
     3087                stream->jb_last_frm = frame_type; 
     3088                stream->jb_last_frm_cnt = 1; 
     3089            } else { 
     3090                stream->jb_last_frm_cnt++; 
     3091            } 
     3092 
     3093            frame->size = frame_out.size; 
     3094        } 
     3095    } 
     3096 
     3097 
     3098    /* Unlock jitter buffer mutex. */ 
     3099    pj_mutex_unlock( stream->jb_mutex ); 
     3100 
     3101    return PJ_SUCCESS; 
     3102} 
     3103 
     3104static pj_status_t video_stream_create(pjmedia_endpt *endpt, 
     3105                                       pj_pool_t *pool, 
     3106                                       const pjmedia_stream_info *info, 
     3107                                       pjmedia_transport *tp, 
     3108                                       void *user_data, 
     3109                                       pjmedia_stream **p_stream) 
     3110{ 
     3111    enum { M = 32 }; 
     3112    pjmedia_stream *stream; 
     3113    pj_str_t name; 
     3114    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 
     3115    pjmedia_video_format_detail *vfd_enc; 
     3116    char *p; 
     3117    pj_status_t status; 
     3118 
     3119    stream = PJ_POOL_ZALLOC_T(pool, pjmedia_stream); 
     3120    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 
     3121    PJ_ASSERT_RETURN(pjmedia_vid_codec_mgr_instance(), PJMEDIA_CODEC_EFAILED); 
     3122 
     3123    /* Init stream/port name */ 
     3124    name.ptr = (char*) pj_pool_alloc(pool, M); 
     3125    name.slen = pj_ansi_snprintf(name.ptr, M, "vstrm%p", stream); 
     3126 
     3127    /* Create and initialize codec: */ 
     3128    stream->vcodec_info = info->vid_codec_info; 
     3129    status = pjmedia_vid_codec_mgr_alloc_codec(NULL, &info->vid_codec_info, 
     3130                                               &stream->vcodec); 
     3131    if (status != PJ_SUCCESS) 
     3132        return status; 
     3133 
     3134 
     3135    /* Get codec param: */ 
     3136    if (info->vid_codec_param) 
     3137        stream->vcodec_param = *info->vid_codec_param; 
     3138    else { 
     3139        status = pjmedia_vid_codec_mgr_get_default_param(NULL,  
     3140                                                         &info->vid_codec_info, 
     3141                                                         &stream->vcodec_param); 
     3142        if (status != PJ_SUCCESS) 
     3143            return status; 
     3144    } 
     3145 
     3146    vfd_enc = pjmedia_format_get_video_format_detail( 
     3147                                            &stream->vcodec_param.enc_fmt, 1); 
     3148 
     3149    /* Init stream: */ 
     3150    stream->endpt = endpt; 
     3151    stream->dir = info->dir; 
     3152    stream->user_data = user_data; 
     3153    stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) * 
     3154                            info->vid_codec_info.clock_rate / 1000; 
     3155 
     3156    stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME; 
     3157    stream->tx_event_pt = -1; 
     3158    stream->rx_event_pt = -1; 
     3159 
     3160#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 
     3161    stream->use_ka = info->use_ka; 
     3162#endif 
     3163 
     3164    /* Build random RTCP CNAME. CNAME has user@host format */ 
     3165    stream->cname.ptr = p = (char*) pj_pool_alloc(pool, 20); 
     3166    pj_create_random_string(p, 5); 
     3167    p += 5; 
     3168    *p++ = '@'; *p++ = 'p'; *p++ = 'j'; 
     3169    pj_create_random_string(p, 6); 
     3170    p += 6; 
     3171    *p++ = '.'; *p++ = 'o'; *p++ = 'r'; *p++ = 'g'; 
     3172    stream->cname.slen = p - stream->cname.ptr; 
     3173 
     3174 
     3175    /* Create mutex to protect jitter buffer: */ 
     3176 
     3177    status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex); 
     3178    if (status != PJ_SUCCESS) 
     3179        return status; 
     3180 
     3181    /* Check for invalid max_bps. */ 
     3182 //   if (stream->codec_param.info.max_bps < stream->codec_param.info.avg_bps) 
     3183        //stream->codec_param.info.max_bps = stream->codec_param.info.avg_bps; 
     3184 
     3185    /* Check for invalid frame per packet. */ 
     3186 //   if (stream->codec_param.setting.frm_per_pkt < 1) 
     3187        //stream->codec_param.setting.frm_per_pkt = 1; 
     3188 
     3189    /* Open the codec. */ 
     3190    stream->vcodec_param.dir = info->dir; 
     3191    stream->vcodec_param.enc_mtu = PJMEDIA_MAX_MTU - 40; 
     3192    status = stream->vcodec->op->init(stream->vcodec, pool); 
     3193    if (status != PJ_SUCCESS) 
     3194        return status; 
     3195    status = stream->vcodec->op->open(stream->vcodec, &stream->vcodec_param); 
     3196    if (status != PJ_SUCCESS) 
     3197        return status; 
     3198 
     3199    /* Set additional info and callbacks. */ 
     3200    stream->port.put_frame = &put_vid_frame; 
     3201    stream->port.get_frame = &get_vid_frame; 
     3202 
     3203    /* Get the frame size */ 
     3204    //stream->frame_size = vfd_enc->max_bps * 
     3205    //                     vfd_enc->fps.denum / vfd_enc->fps.num; 
     3206    stream->frame_size = 128000; 
     3207 
     3208    /* How many consecutive PLC frames can be generated */ 
     3209    stream->max_plc_cnt = MAX_PLC_MSEC * 
     3210                          vfd_enc->fps.num / vfd_enc->fps.denum / 1000; 
     3211 
     3212    stream->rtp_rx_check_cnt = 5; 
     3213    stream->rtp_rx_last_ts = 0; 
     3214    stream->rtp_rx_last_cnt = 0; 
     3215    stream->rtp_tx_ts_len_per_pkt =  
     3216                            info->vid_codec_info.clock_rate * 
     3217                            vfd_enc->fps.denum / vfd_enc->fps.num; 
     3218    stream->rtp_rx_ts_len_per_frame = stream->rtp_tx_ts_len_per_pkt; 
     3219 
     3220    /* Init jitter buffer parameters: */ 
     3221    jb_max     = info->jb_max * 
     3222                 vfd_enc->fps.num / vfd_enc->fps.denum / 1000; 
     3223    jb_min_pre = info->jb_min_pre * 
     3224                 vfd_enc->fps.num / vfd_enc->fps.denum / 1000; 
     3225    jb_max_pre = info->jb_max_pre * 
     3226                 vfd_enc->fps.num / vfd_enc->fps.denum / 1000; 
     3227    jb_init    = info->jb_init * 
     3228                 vfd_enc->fps.num / vfd_enc->fps.denum / 1000; 
     3229 
     3230    /* When JB max frame count==0, set to 0.5s */ 
     3231    if (jb_max == 0) 
     3232        jb_max = (vfd_enc->fps.num + vfd_enc->fps.denum/2) / 
     3233                  vfd_enc->fps.denum / 2; 
     3234     
     3235    /* When JB max prefetch==0, set to (4/5 * jb_max) */ 
     3236    if (jb_max_pre == 0) 
     3237        jb_max_pre = jb_max * 4 / 5; 
     3238 
     3239    /* Create jitter buffer */ 
     3240    status = pjmedia_jbuf_create(pool, &stream->port.info.name, 
     3241                                 stream->frame_size,  
     3242                                 1000 * vfd_enc->fps.denum / vfd_enc->fps.num, 
     3243                                 jb_max, &stream->jb); 
     3244    if (status != PJ_SUCCESS) 
     3245        return status; 
     3246 
     3247 
     3248    /* Set up jitter buffer */ 
     3249    pjmedia_jbuf_set_adaptive( stream->jb, jb_init, jb_min_pre, jb_max_pre); 
     3250 
     3251    /* Create decoder channel: */ 
     3252 
     3253    status = create_channel( pool, stream, PJMEDIA_DIR_DECODING,  
     3254                             stream->vcodec_param.pt, info, &stream->dec); 
     3255    if (status != PJ_SUCCESS) 
     3256        return status; 
     3257 
     3258 
     3259    /* Create encoder channel: */ 
     3260 
     3261    status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING,  
     3262                             info->tx_pt, info, &stream->enc); 
     3263    if (status != PJ_SUCCESS) 
     3264        return status; 
     3265 
     3266 
     3267    /* Init RTCP session: */ 
     3268 
     3269    { 
     3270        pjmedia_rtcp_session_setting rtcp_setting; 
     3271 
     3272        pjmedia_rtcp_session_setting_default(&rtcp_setting); 
     3273        rtcp_setting.name = stream->port.info.name.ptr; 
     3274        rtcp_setting.ssrc = info->ssrc; 
     3275        rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
     3276        rtcp_setting.clock_rate = info->vid_codec_info.clock_rate; 
     3277        rtcp_setting.samples_per_frame = stream->rtp_tx_ts_len_per_pkt; 
     3278 
     3279        pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting); 
     3280    } 
     3281 
     3282    /* Only attach transport when stream is ready. */ 
     3283    status = pjmedia_transport_attach(tp, stream, &info->rem_addr,  
     3284                                      &info->rem_rtcp,  
     3285                                      pj_sockaddr_get_len(&info->rem_addr),  
     3286                                      &on_rx_rtp, &on_rx_rtcp); 
     3287    if (status != PJ_SUCCESS) 
     3288        return status; 
     3289 
     3290    stream->transport = tp; 
     3291 
     3292    /* Send RTCP SDES */ 
     3293    len = create_rtcp_sdes(stream, (pj_uint8_t*)stream->enc->out_pkt,  
     3294                           stream->enc->out_pkt_size); 
     3295    if (len != 0) { 
     3296        pjmedia_transport_send_rtcp(stream->transport,  
     3297                                    stream->enc->out_pkt, len); 
     3298    } 
     3299 
     3300#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 
     3301    /* NAT hole punching by sending KA packet via RTP transport. */ 
     3302    if (stream->use_ka) 
     3303        send_keep_alive_packet(stream); 
     3304#endif 
     3305 
     3306#if TRACE_JB 
     3307    { 
     3308        char trace_name[PJ_MAXPATH]; 
     3309        pj_ssize_t len; 
     3310 
     3311        pj_ansi_snprintf(trace_name, sizeof(trace_name),  
     3312                         TRACE_JB_PATH_PREFIX "%s.csv", 
     3313                         stream->port.info.name.ptr); 
     3314        status = pj_file_open(pool, trace_name, PJ_O_RDWR, &stream->trace_jb_fd); 
     3315        if (status != PJ_SUCCESS) { 
     3316            stream->trace_jb_fd = TRACE_JB_INVALID_FD; 
     3317            PJ_LOG(3,(THIS_FILE, "Failed creating RTP trace file '%s'",  
     3318                      trace_name)); 
     3319        } else { 
     3320            stream->trace_jb_buf = (char*)pj_pool_alloc(pool, PJ_LOG_MAX_SIZE); 
     3321 
     3322            /* Print column header */ 
     3323            len = pj_ansi_snprintf(stream->trace_jb_buf, PJ_LOG_MAX_SIZE, 
     3324                                   "Time, Operation, Size, Frame Count, " 
     3325                                   "Frame type, RTP Seq, RTP TS, RTP M, " 
     3326                                   "JB size, JB burst level, JB prefetch\n"); 
     3327            pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len); 
     3328            pj_file_flush(stream->trace_jb_fd); 
     3329        } 
     3330    } 
     3331#endif 
     3332 
     3333    /* Init some port-info. Some parts of the info will be set later 
     3334     * once we have more info about the codec. 
     3335     */ 
     3336    pjmedia_port_info_init2(&stream->port.info, &name, 
     3337                            PJMEDIA_PORT_SIGNATURE('S', 'T', 'R', 'M'), 
     3338                            info->dir, &stream->vcodec_param.dec_fmt); 
     3339 
     3340    /* Init port. */ 
     3341    stream->port.port_data.pdata = stream; 
     3342 
     3343    /* Success! */ 
     3344    *p_stream = stream; 
     3345 
     3346    PJ_LOG(5,(THIS_FILE, "Stream %s created", stream->port.info.name.ptr)); 
     3347 
     3348    return PJ_SUCCESS; 
     3349} 
Note: See TracChangeset for help on using the changeset viewer.