- Timestamp:
- Dec 10, 2010 11:04:30 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/stream.c
r3387 r3392 78 78 unsigned out_pkt_size; /**< Size of output buffer. */ 79 79 void *out_pkt; /**< Output buffer. */ 80 unsigned out_pkt_len; /**< Length of data in buffer. */ 80 81 pjmedia_rtp_session rtp; /**< RTP session. */ 81 82 }; … … 178 179 received according to 179 180 'erroneous' definition */ 180 pj_uint32_t rtp_rx_last_ts;/**< Last received RTP timestamp181 for timestamp checking */182 181 unsigned rtp_rx_last_cnt;/**< Nb of frames in last pkt */ 183 182 unsigned rtp_rx_check_cnt; … … 209 208 char *trace_jb_buf; /**< Jitter tracing buffer. */ 210 209 #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 211 217 }; 212 218 … … 472 478 pj_mutex_lock( stream->jb_mutex ); 473 479 474 samples_required = stream->port.info.samples_per_frame;480 samples_required = PJMEDIA_PIA_SPF(&stream->port.info); 475 481 samples_per_frame = stream->codec_param.info.frm_ptime * 476 482 stream->codec_param.info.clock_rate * … … 726 732 */ 727 733 728 samples_required = stream->port.info.samples_per_frame;734 samples_required = PJMEDIA_PIA_SPF(&stream->port.info); 729 735 samples_per_frame = stream->codec_param.info.frm_ptime * 730 736 stream->codec_param.info.clock_rate * … … 877 883 } 878 884 879 digit->duration += stream->port.info.samples_per_frame;885 digit->duration += PJMEDIA_PIA_SPF(&stream->port.info); 880 886 881 887 event->event = (pj_uint8_t)digit->event; … … 1088 1094 /* How many samples are needed */ 1089 1095 count = stream->codec_param.info.enc_ptime * 1090 stream->port.info.clock_rate/ 1000;1096 PJMEDIA_PIA_SRATE(&stream->port.info) / 1000; 1091 1097 1092 1098 /* See if we have enough samples */ … … 1111 1117 */ 1112 1118 static pj_status_t put_frame_imp( pjmedia_port *port, 1113 constpjmedia_frame *frame )1119 pjmedia_frame *frame ) 1114 1120 { 1115 1121 pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; … … 1152 1158 ts_len = (frame->size >> 1) / stream->codec_param.info.channel_cnt; 1153 1159 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); 1156 1162 else 1157 1163 ts_len = 0; … … 1220 1226 } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 1221 1227 frame->buf == NULL && 1222 stream->port.info.f ormat.id == PJMEDIA_FORMAT_L16 &&1228 stream->port.info.fmt.id == PJMEDIA_FORMAT_L16 && 1223 1229 (stream->dir & PJMEDIA_DIR_ENCODING) && 1224 1230 stream->codec_param.info.frm_ptime * … … 1363 1369 */ 1364 1370 static pj_status_t put_frame( pjmedia_port *port, 1365 constpjmedia_frame *frame )1371 pjmedia_frame *frame ) 1366 1372 { 1367 1373 pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; … … 1411 1417 if (stream->vad_enabled != stream->codec_param.setting.vad && 1412 1418 (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) 1414 1421 { 1415 1422 stream->codec_param.setting.vad = stream->vad_enabled; … … 1574 1581 unsigned payloadlen; 1575 1582 pjmedia_rtp_status seq_st; 1576 pj_bool_t check_pt;1577 1583 pj_status_t status; 1578 1584 pj_bool_t pkt_discarded = PJ_FALSE; … … 1604 1610 * the incoming packet. 1605 1611 */ 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); 1615 1614 if (seq_st.status.value) { 1616 1615 TRC_ ((stream->port.info.name.ptr, … … 1673 1672 PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 1674 1673 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 1675 1731 } else { 1676 1732 /* … … 1727 1783 * to avoid wrong decision because of silence frames. 1728 1784 */ 1729 if 1730 (peer_frm_ts_diff==stream->port.info.samples_per_frame1785 if(stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 && 1786 (peer_frm_ts_diff==PJMEDIA_PIA_SPF(&stream->port.info) 1731 1787 || peer_frm_ts_diff == 1732 stream->port.info.samples_per_frame >>1))1788 PJMEDIA_PIA_SPF(&stream->port.info) >>1)) 1733 1789 { 1734 1790 if (peer_frm_ts_diff < stream->rtp_rx_ts_len_per_frame) … … 1883 1939 /* Allocate buffer for outgoing packet. */ 1884 1940 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 } 1892 1954 1893 1955 /* It should big enough to hold (minimally) RTCP SR with an SDES. */ … … 1927 1989 } 1928 1990 1991 1992 static 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); 1929 1998 1930 1999 /* … … 1943 2012 pj_str_t name; 1944 2013 unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 2014 pjmedia_audio_format_detail *afd; 1945 2015 char *p; 1946 2016 pj_status_t status; … … 1948 2018 PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); 1949 2019 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 } 1950 2030 1951 2031 /* Allocate the media stream: */ … … 1965 2045 info->fmt.clock_rate, info->fmt.channel_cnt, 1966 2046 16, 80); 2047 afd = pjmedia_format_get_audio_format_detail(&stream->port.info.fmt, 1); 1967 2048 1968 2049 /* Init port. */ 1969 2050 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; 1973 2055 stream->port.port_data.pdata = stream; 1974 2056 … … 2041 2123 2042 2124 /* 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; 2050 2129 if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) { 2051 2130 /* 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 2054 2134 2055 2135 stream->port.put_frame = &put_frame; … … 2057 2137 } else { 2058 2138 /* 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) 2065 2146 { 2066 2147 ++stream->port.info.bytes_per_frame; … … 2068 2149 stream->port.info.format.bitrate = stream->codec_param.info.avg_bps; 2069 2150 stream->port.info.format.vad = (stream->codec_param.setting.vad != 0); 2151 */ 2070 2152 2071 2153 stream->port.put_frame = &put_frame; … … 2084 2166 stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 2085 2167 stream->codec_param.info.channel_cnt * 2086 stream->port.info.clock_rate / 1000;2168 afd->clock_rate / 1000; 2087 2169 2088 2170 /* Set buffer size as twice the largest ptime value between … … 2090 2172 */ 2091 2173 2092 ptime = stream->port.info.samples_per_frame * 1000 / 2093 stream->port.info.clock_rate; 2174 ptime = afd->frame_time_usec / 1000; 2094 2175 2095 2176 if (stream->codec_param.info.enc_ptime > ptime) … … 2102 2183 2103 2184 /* Allocate buffer */ 2104 stream->enc_buf_size = stream->port.info.clock_rate * ptime / 1000;2185 stream->enc_buf_size = afd->clock_rate * ptime / 1000; 2105 2186 stream->enc_buf = (pj_int16_t*) 2106 2187 pj_pool_alloc(pool, stream->enc_buf_size * 2); 2107 2188 2108 2189 } else { 2109 stream->enc_samples_per_pkt = stream->port.info.samples_per_frame;2190 stream->enc_samples_per_pkt = PJMEDIA_AFD_SPF(afd); 2110 2191 } 2111 2192 … … 2140 2221 stream->rtp_tx_ts_len_per_pkt = stream->enc_samples_per_pkt / 2141 2222 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) / 2143 2224 stream->codec_param.info.channel_cnt; 2144 2225 … … 2213 2294 rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts); 2214 2295 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); 2216 2297 2217 2298 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) … … 2422 2503 pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); 2423 2504 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; 2424 2511 } 2425 2512 … … 2739 2826 } 2740 2827 2828 static 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 2973 static 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 3104 static 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.