Changeset 1779
- Timestamp:
- Feb 4, 2008 11:56:40 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/jbuf2/pjmedia/src/pjmedia/stream.c
r1667 r1779 21 21 #include <pjmedia/rtp.h> 22 22 #include <pjmedia/rtcp.h> 23 #include <pjmedia/jbuf .h>23 #include <pjmedia/jbuf2.h> 24 24 #include <pj/array.h> 25 25 #include <pj/assert.h> … … 109 109 110 110 pj_mutex_t *jb_mutex; 111 pjmedia_jbuf *jb; /**< Jitter buffer. */ 112 char jb_last_frm; /**< Last frame type from jb */ 111 pjmedia_jb2_t *jb; /**< Jitter buffer. */ 113 112 114 113 pjmedia_rtcp_session rtcp; /**< RTCP for incoming RTP. */ … … 153 152 } 154 153 154 static pj_status_t jb_decode(pjmedia_jb2_frame *frame, void *userdata) 155 { 156 pjmedia_stream *stream = (pjmedia_stream*) userdata; 157 pj_status_t status = PJ_SUCCESS; 158 pjmedia_frame frame_in, frame_out; 159 160 pj_assert(frame && userdata); 161 162 /* Decode */ 163 frame_in.buf = stream->dec->out_pkt; 164 frame_in.size = frame->size; 165 frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; 166 pj_memcpy(frame_in.buf, frame->buffer, frame->size); 167 168 frame_out.buf = frame->buffer; 169 frame_out.size = (stream->codec_param.info.clock_rate * 170 stream->codec_param.info.frm_ptime / 1000)* 171 (stream->codec_param.info.pcm_bits_per_sample/8); 172 173 status = stream->codec->op->decode( stream->codec, &frame_in, 174 frame_out.size, &frame_out); 175 176 /* NOTE: frame_out.size is not valid for speex/16000 */ 177 frame->size = frame_out.size; 178 if (status != PJ_SUCCESS) { 179 LOGERR_((stream->port.info.name.ptr, "codec decode() error", 180 status)); 181 182 pj_bzero(frame->buffer, frame->size); 183 } 184 185 return status; 186 } 187 188 static pj_status_t jb_plc(pjmedia_jb2_frame *frame, void *userdata) 189 { 190 pjmedia_stream *stream = (pjmedia_stream*) userdata; 191 pj_status_t status = PJ_SUCCESS; 192 193 pj_assert(frame && stream); 194 195 /* Activate PLC */ 196 if (stream->codec->op->recover && 197 stream->codec_param.setting.plc) 198 { 199 pjmedia_frame frame_out; 200 201 frame_out.buf = frame->buffer; 202 frame_out.size = frame->size; 203 status = (*stream->codec->op->recover)(stream->codec, 204 frame_out.size, 205 &frame_out); 206 } else { 207 status = PJ_EINVAL; 208 } 209 210 if (status != PJ_SUCCESS) { 211 /* Either PLC failed or PLC not supported/enabled */ 212 pj_bzero(frame->buffer, frame->size); 213 PJ_LOG(5,(stream->port.info.name.ptr, "Frame lost!")); 214 215 } else { 216 PJ_LOG(5,(stream->port.info.name.ptr, 217 "Lost frame recovered")); 218 } 219 220 return status; 221 } 222 223 static pj_status_t jb_cng(pjmedia_jb2_frame *frame, void *userdata) 224 { 225 pjmedia_stream *stream = (pjmedia_stream*) userdata; 226 227 pj_assert(frame && stream); 228 229 frame->size = (stream->codec_param.info.clock_rate * 230 stream->codec_param.info.frm_ptime / 1000)* 231 (stream->codec_param.info.pcm_bits_per_sample/8); 232 pj_bzero(frame->buffer, frame->size); 233 234 return PJ_SUCCESS; 235 } 236 155 237 156 238 /* … … 160 242 * needs to feed the player with some frames. 161 243 */ 244 162 245 static pj_status_t get_frame( pjmedia_port *port, pjmedia_frame *frame) 163 246 { … … 167 250 pj_int16_t *p_out_samp; 168 251 pj_status_t status; 169 252 pjmedia_jb2_frame jb_frame; 170 253 171 254 /* Return no frame is channel is paused */ … … 192 275 samples_count += samples_per_frame) 193 276 { 194 char frame_type;195 196 277 /* Get frame from jitter buffer. */ 197 pjmedia_jbuf_get_frame(stream->jb, channel->out_pkt, &frame_type); 198 199 if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 200 201 /* Activate PLC */ 202 if (stream->codec->op->recover && 203 stream->codec_param.setting.plc) 204 { 205 pjmedia_frame frame_out; 206 207 frame_out.buf = p_out_samp + samples_count; 208 frame_out.size = frame->size - samples_count*2; 209 status = (*stream->codec->op->recover)(stream->codec, 210 frame_out.size, 211 &frame_out); 212 213 } else { 214 status = -1; 215 } 216 217 if (status != PJ_SUCCESS) { 218 /* Either PLC failed or PLC not supported/enabled */ 219 pjmedia_zero_samples(p_out_samp + samples_count, 220 samples_required - samples_count); 221 PJ_LOG(5,(stream->port.info.name.ptr, "Frame lost!")); 222 223 } else { 224 PJ_LOG(5,(stream->port.info.name.ptr, 225 "Lost frame recovered")); 226 } 227 228 } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 229 230 /* Jitter buffer is empty. If this is the first "empty" state, 231 * activate PLC to smoothen the fade-out, otherwise zero 232 * the frame. 233 */ 234 if (frame_type != stream->jb_last_frm) { 235 pjmedia_jb_state jb_state; 236 237 /* Activate PLC to smoothen the missing frame */ 238 if (stream->codec->op->recover && 239 stream->codec_param.setting.plc) 240 { 241 pjmedia_frame frame_out; 242 243 do { 244 frame_out.buf = p_out_samp + samples_count; 245 frame_out.size = frame->size - samples_count*2; 246 status = (*stream->codec->op->recover)(stream->codec, 247 frame_out.size, 248 &frame_out); 249 if (status != PJ_SUCCESS) 250 break; 251 samples_count += samples_per_frame; 252 253 } while (samples_count < samples_required); 254 255 } 256 257 /* Report the state of jitter buffer */ 258 pjmedia_jbuf_get_state(stream->jb, &jb_state); 259 PJ_LOG(5,(stream->port.info.name.ptr, 260 "Jitter buffer empty (prefetch=%d)", 261 jb_state.prefetch)); 262 263 } 264 265 if (samples_count < samples_required) { 266 pjmedia_zero_samples(p_out_samp + samples_count, 267 samples_required - samples_count); 268 samples_count = samples_required; 269 } 270 271 stream->jb_last_frm = frame_type; 272 break; 273 274 } else if (frame_type != PJMEDIA_JB_NORMAL_FRAME) { 275 276 pjmedia_jb_state jb_state; 277 278 /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */ 279 pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME); 280 281 /* Get the state of jitter buffer */ 282 pjmedia_jbuf_get_state(stream->jb, &jb_state); 283 284 /* Always activate PLC when it's available.. */ 285 if (stream->codec->op->recover && 286 stream->codec_param.setting.plc) 287 { 288 pjmedia_frame frame_out; 289 290 do { 291 frame_out.buf = p_out_samp + samples_count; 292 frame_out.size = frame->size - samples_count*2; 293 status = (*stream->codec->op->recover)(stream->codec, 294 frame_out.size, 295 &frame_out); 296 if (status != PJ_SUCCESS) 297 break; 298 samples_count += samples_per_frame; 299 300 } while (samples_count < samples_required); 301 302 if (stream->jb_last_frm != frame_type) { 303 PJ_LOG(5,(stream->port.info.name.ptr, 304 "Jitter buffer is bufferring with plc (prefetch=%d)", 305 jb_state.prefetch)); 306 } 307 308 } 309 310 if (samples_count < samples_required) { 311 pjmedia_zero_samples(p_out_samp + samples_count, 312 samples_required - samples_count); 313 samples_count = samples_required; 314 PJ_LOG(5,(stream->port.info.name.ptr, 315 "Jitter buffer is bufferring (prefetch=%d)..", 316 jb_state.prefetch)); 317 } 318 319 stream->jb_last_frm = frame_type; 320 break; 321 322 } else { 323 /* Got "NORMAL" frame from jitter buffer */ 324 pjmedia_frame frame_in, frame_out; 325 326 /* Decode */ 327 frame_in.buf = channel->out_pkt; 328 frame_in.size = stream->frame_size; 329 frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; /* ignored */ 330 331 frame_out.buf = p_out_samp + samples_count; 332 frame_out.size = frame->size - samples_count*BYTES_PER_SAMPLE; 333 status = stream->codec->op->decode( stream->codec, &frame_in, 334 frame_out.size, &frame_out); 335 if (status != 0) { 336 LOGERR_((port->info.name.ptr, "codec decode() error", 337 status)); 338 339 pjmedia_zero_samples(p_out_samp + samples_count, 340 samples_per_frame); 341 } 342 } 343 344 stream->jb_last_frm = frame_type; 278 jb_frame.buffer = p_out_samp + samples_count; 279 jb_frame.size = frame->size - samples_count*2; 280 status = pjmedia_jb2_get_frame(stream->jb, &jb_frame); 345 281 } 346 282 … … 1000 936 pj_mutex_lock( stream->jb_mutex ); 1001 937 if (seq_st.status.flag.restart) { 1002 status = pjmedia_jb uf_reset(stream->jb);938 status = pjmedia_jb2_reset(stream->jb); 1003 939 PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 1004 940 … … 1014 950 unsigned samples_per_frame; 1015 951 pjmedia_frame frames[MAX]; 952 pjmedia_jb2_frame jb_frame; 1016 953 1017 954 /* Get the timestamp of the first sample */ … … 1039 976 1040 977 for (i=0; i<count; ++i) { 1041 unsigned ext_seq; 1042 1043 ext_seq = (unsigned)(frames[i].timestamp.u64 / 1044 samples_per_frame); 1045 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 1046 frames[i].size, ext_seq); 1047 978 jb_frame.buffer = frames[i].buf; 979 jb_frame.pt = (pj_uint8_t)hdr->pt; 980 jb_frame.seq = ntohs(hdr->seq); 981 jb_frame.size = frames[i].size; 982 jb_frame.ts = ntohl(hdr->ts) + samples_per_frame*i; 983 jb_frame.type = PJMEDIA_JB_FT_NORMAL_FRAME; 984 985 status = pjmedia_jb2_put_frame(stream->jb, &jb_frame); 986 if (status != PJ_SUCCESS) { 987 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 988 status)); 989 } 1048 990 } 1049 991 } 992 1050 993 pj_mutex_unlock( stream->jb_mutex ); 1051 1052 994 1053 995 /* Check if now is the time to transmit RTCP SR/RR report. … … 1057 999 if (stream->dir == PJMEDIA_DIR_DECODING) { 1058 1000 check_tx_rtcp(stream, pj_ntohl(hdr->ts)); 1059 }1060 1061 if (status != 0) {1062 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error",1063 status));1064 return;1065 1001 } 1066 1002 } … … 1161 1097 pjmedia_stream *stream; 1162 1098 pj_str_t name; 1163 unsigned jb_init, jb_max, jb_min_pre, jb_max_pre;1164 1099 pj_status_t status; 1100 pjmedia_jb2_setting jb_setting; 1101 pjmedia_jb2_cb jb_cb; 1165 1102 1166 1103 PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); … … 1316 1253 1317 1254 /* Init jitter buffer parameters: */ 1318 if (info->jb_max > 0) 1319 jb_max = info->jb_max; 1320 else 1321 jb_max = 360 / stream->codec_param.info.frm_ptime; 1322 1323 if (info->jb_min_pre >= 0) 1324 jb_min_pre = info->jb_min_pre; 1325 else 1326 jb_min_pre = 60 / stream->codec_param.info.frm_ptime; 1327 1328 if (info->jb_max_pre > 0) 1329 jb_max_pre = info->jb_max_pre; 1330 else 1331 jb_max_pre = 240 / stream->codec_param.info.frm_ptime; 1332 1333 if (info->jb_init >= 0) 1334 jb_init = info->jb_init; 1335 else 1336 jb_init = (jb_min_pre + jb_max_pre) / 2; 1337 1255 pj_bzero(&jb_setting, sizeof(jb_setting)); 1256 jb_setting.samples_per_frame = info->fmt.clock_rate * 1257 stream->codec_param.info.frm_ptime / 1258 1000; 1259 jb_setting.frame_size = jb_setting.samples_per_frame * 1260 stream->codec_param.info.pcm_bits_per_sample / 8; 1261 jb_setting.max_frames = 0; 1262 1263 pj_bzero(&jb_cb, sizeof(jb_cb)); 1264 jb_cb.decode = &jb_decode; 1265 jb_cb.plc = &jb_plc; 1266 jb_cb.cng = NULL; //&jb_cng; 1267 jb_cb.user_data = stream; 1338 1268 1339 1269 /* Create jitter buffer */ 1340 status = pjmedia_jbuf_create(pool, &stream->port.info.name, 1341 stream->frame_size, 1342 stream->codec_param.info.frm_ptime, 1343 jb_max, &stream->jb); 1270 status = pjmedia_jb2_create(pool, &stream->port.info.name, &jb_setting, 1271 &jb_cb, &stream->jb); 1272 1344 1273 if (status != PJ_SUCCESS) 1345 1274 goto err_cleanup; 1346 1275 1347 1348 /* Set up jitter buffer */1349 pjmedia_jbuf_set_adaptive( stream->jb, jb_init, jb_min_pre, jb_max_pre);1350 1276 1351 1277 /* Create decoder channel: */ … … 1417 1343 } 1418 1344 1345 /* Destroy JB */ 1346 if (stream->jb) { 1347 pjmedia_jb2_destroy(stream->jb); 1348 stream->jb = NULL; 1349 } 1350 1419 1351 /* Free mutex */ 1420 1352 … … 1508 1440 /* Also reset jitter buffer */ 1509 1441 pj_mutex_lock( stream->jb_mutex ); 1510 pjmedia_jb uf_reset(stream->jb);1442 pjmedia_jb2_reset(stream->jb); 1511 1443 pj_mutex_unlock( stream->jb_mutex ); 1512 1444
Note: See TracChangeset
for help on using the changeset viewer.