static void receiver_process(MSFilter * f) { ReceiverData *d = (ReceiverData *) f->data; mblk_t *m; uint32_t timestamp; if (d->session == NULL) return; if (d->reset_jb){ ms_message("Reseting jitter buffer"); rtp_session_resync(d->session); d->reset_jb=FALSE; } if (d->starting){ PayloadType *pt=rtp_profile_get_payload( rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session)); if (pt && pt->type!=PAYLOAD_VIDEO) rtp_session_flush_sockets(d->session); d->starting=FALSE; } timestamp = (uint32_t) (f->ticker->time * (d->rate/1000)); while ((m = rtp_session_recvm_with_ts(d->session, timestamp)) != NULL) { mblk_set_timestamp_info(m, rtp_get_timestamp(m)); mblk_set_marker_info(m, rtp_get_markbit(m)); mblk_set_cseq(m, rtp_get_seqnumber(m)); rtp_get_payload(m,&m->b_rptr); ms_queue_put(f->outputs[0], m); } }
/*this function must be called from the MSTicker thread: it replaces one filter by another one. This is a dirty hack that works anyway. It would be interesting to have something that does the job simplier within the MSTicker api */ void video_stream_change_decoder(VideoStream *stream, int payload){ RtpSession *session=stream->session; RtpProfile *prof=rtp_session_get_profile(session); PayloadType *pt=rtp_profile_get_payload(prof,payload); if (pt!=NULL){ MSFilter *dec=ms_filter_create_decoder(pt->mime_type); if (dec!=NULL){ ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0); ms_filter_unlink(stream->decoder,0,stream->output,0); ms_filter_postprocess(stream->decoder); ms_filter_destroy(stream->decoder); stream->decoder=dec; if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp); ms_filter_link (stream->rtprecv, 0, stream->decoder, 0); ms_filter_link (stream->decoder,0 , stream->output, 0); ms_filter_preprocess(stream->decoder,stream->ticker); }else{ ms_warning("No decoder found for %s",pt->mime_type); } }else{ ms_warning("No payload defined with number %i",payload); } }
static int get_receiver_output_fmt(MSFilter *f, void *arg) { ReceiverData *d = (ReceiverData *) f->data; MSPinFormat *pinFmt = (MSPinFormat *)arg; PayloadType *pt = rtp_profile_get_payload(rtp_session_get_profile(d->session), rtp_session_get_send_payload_type(d->session)); pinFmt->fmt = ms_factory_get_audio_format(f->factory, pt->mime_type, pt->clock_rate, pt->channels, NULL); return 0; }
/*returns TRUE if the packet is ok to be sent to output queue*/ static bool_t receiver_check_payload_type(MSFilter *f, ReceiverData *d, mblk_t *m){ int ptn=rtp_get_payload_type(m); PayloadType *pt; if (ptn==d->current_pt) return TRUE; pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), ptn); if (pt==NULL){ ms_warning("Discarding packet with unknown payload type %i",ptn); return FALSE; } if (strcasecmp(pt->mime_type,"CN")==0){ MSCngData cngdata; uint8_t *data=NULL; int datasize=rtp_get_payload(m, &data); if (data){ if (datasize<= sizeof(cngdata.data)){ memcpy(cngdata.data, data, datasize); cngdata.datasize=datasize; ms_filter_notify(f, MS_RTP_RECV_GENERIC_CN_RECEIVED, &cngdata); }else{ ms_warning("CN packet has unexpected size %i", datasize); } } return FALSE; } d->current_pt = ptn; return TRUE; }
bool myAudioStream::init_filters(const QString & payload) { /** Init filters **/ stream->soundwrite = ms_snd_card_create_writer(playcard); RtpProfile *profile = rtp_session_get_profile(stream->session); PayloadType *pt; /* List all available payloads */ QMap<QString,int> payloads; for (int i = 0; i < RTP_PROFILE_MAX_PAYLOADS; i++) { pt = rtp_profile_get_payload(profile,i); if (pt != 0) { QString payload(pt->mime_type); if (payloads.contains(payload)) { payload.append(" " + QString::number(pt->clock_rate)); } payloads.insert(payload,i); } } if (!payloads.contains(payload)) { ms_error("Could not find payload %s", payload.toStdString().c_str()); return false; } int payload_type_number = payloads.value(payload); /* Create filters */ pt = rtp_profile_get_payload(profile,payload_type_number); stream->decoder = ms_filter_create_decoder(pt->mime_type); stream->rtprecv = ms_filter_new(MS_RTP_RECV_ID); stream->dtmfgen = ms_filter_new(MS_DTMF_GEN_ID); /** Configure filter options **/ /* Set payload type to use when receiving */ rtp_session_set_payload_type(stream->session, payload_type_number); /* Set session used by rtprecv */ ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,stream->session); /* Setup soundwrite and decoder parameters */ int sr = pt->clock_rate; int chan = pt->channels; if (ms_filter_call_method(stream->soundwrite, MS_FILTER_SET_SAMPLE_RATE, &sr) !=0 ) { ms_error("Problem setting sample rate on soundwrite filter!"); return false; } if (ms_filter_call_method(stream->soundwrite, MS_FILTER_SET_NCHANNELS, &chan) != 0) { ms_error("Failed to set sample rate on soundwrite filter!"); return false; } if (ms_filter_call_method(stream->decoder, MS_FILTER_SET_SAMPLE_RATE, &sr) != 0) { ms_error("Problem setting sample rate on decoder filter!"); return false; } return true; }
static void receiver_preprocess(MSFilter * f){ ReceiverData *d = (ReceiverData *) f->data; if (d->session){ PayloadType *pt=rtp_profile_get_payload( rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session)); if (pt){ if (pt->type!=PAYLOAD_VIDEO) rtp_session_flush_sockets(d->session); } } }
static int receiver_get_ch(MSFilter *f, void *arg) { ReceiverData *d = (ReceiverData *)f->data; PayloadType *pt; if (d->session==NULL) { ms_warning("MSRtpRecv: Could not obtain sample rate, session is not set."); return -1; } pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session)); if (pt == NULL) { ms_warning("MSRtpRecv: could not obtain number of channels, payload type is unknown."); return -1; } *(int *)arg = pt->channels; return 0; }
static int sender_set_session(MSFilter * f, void *arg) { SenderData *d = (SenderData *) f->data; RtpSession *s = (RtpSession *) arg; PayloadType *pt = rtp_profile_get_payload(rtp_session_get_profile(s), rtp_session_get_send_payload_type(s)); if (pt != NULL) { d->rate = pt->clock_rate; } else { ms_warning("Sending undefined payload type ?"); } d->session = s; return 0; }
static int receiver_set_session(MSFilter * f, void *arg) { ReceiverData *d = (ReceiverData *) f->data; RtpSession *s = (RtpSession *) arg; PayloadType *pt; d->current_pt=rtp_session_get_recv_payload_type(s); pt = rtp_profile_get_payload(rtp_session_get_profile(s),d->current_pt); if (pt != NULL) { d->rate = pt->clock_rate; } else { ms_warning("receiver_set_session(): receiving undefined payload type %i ?", rtp_session_get_recv_payload_type(s)); } d->session = s; return 0; }
static int sender_set_session(MSFilter * f, void *arg) { SenderData *d = (SenderData *) f->data; RtpSession *s = (RtpSession *) arg; PayloadType *pt = rtp_profile_get_payload(rtp_session_get_profile(s), rtp_session_get_send_payload_type(s)); if (pt != NULL) { d->rate = pt->clock_rate; d->dtmf_duration=(default_dtmf_duration_ms*d->rate)/1000; d->dtmf_ts_step=(20*d->rate)/1000; send_stun_packet(s); } else { ms_warning("Sending undefined payload type ?"); } d->session = s; return 0; }
static int receiver_get_sr(MSFilter *f, void *arg){ ReceiverData *d = (ReceiverData *) f->data; PayloadType *pt; if (d->session==NULL) { ms_warning("Could not obtain sample rate, session is not set."); return -1; } pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session)); if (pt != NULL) { if (strcasecmp(pt->mime_type,"G722")==0) *(int*)arg=16000; else *(int*)arg=pt->clock_rate; }else{ ms_warning("Could not obtain sample rate, payload type is unknown."); return -1; } return 0; }
/** * This function must be called from the MSTicker thread: * it replaces one filter by another one. * This is a dirty hack that works anyway. * It would be interesting to have something that does the job * more easily within the MSTicker API. */ static void media_stream_change_decoder(MediaStream *stream, int payload) { RtpSession *session = stream->sessions.rtp_session; RtpProfile *prof = rtp_session_get_profile(session); PayloadType *pt = rtp_profile_get_payload(prof, payload); if (stream->decoder == NULL){ ms_message("media_stream_change_decoder(): ignored, no decoder."); return; } if (pt != NULL){ MSFilter *dec; if (stream->type == VideoStreamType){ /* Q: why only video ? this optimization seems relevant for audio too.*/ if ((stream->decoder != NULL) && (stream->decoder->desc->enc_fmt != NULL) && (strcasecmp(pt->mime_type, stream->decoder->desc->enc_fmt) == 0)) { /* Same formats behind different numbers, nothing to do. */ return; } } dec = ms_filter_create_decoder(pt->mime_type); if (dec != NULL) { MSFilter *nextFilter = stream->decoder->outputs[0]->next.filter; ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0); ms_filter_unlink(stream->decoder, 0, nextFilter, 0); ms_filter_postprocess(stream->decoder); ms_filter_destroy(stream->decoder); stream->decoder = dec; if (pt->recv_fmtp != NULL) ms_filter_call_method(stream->decoder, MS_FILTER_ADD_FMTP, (void *)pt->recv_fmtp); ms_filter_link(stream->rtprecv, 0, stream->decoder, 0); ms_filter_link(stream->decoder, 0, nextFilter, 0); ms_filter_preprocess(stream->decoder,stream->sessions.ticker); } else { ms_warning("No decoder found for %s", pt->mime_type); } } else { ms_warning("No payload defined with number %i", payload); } }
/*this function must be called from the MSTicker thread: it replaces one filter by another one. This is a dirty hack that works anyway. It would be interesting to have something that does the job simplier within the MSTicker api */ void video_stream_change_decoder(VideoStream *stream, int payload){ RtpSession *session=stream->session; RtpProfile *prof=rtp_session_get_profile(session); PayloadType *pt=rtp_profile_get_payload(prof,payload); if (pt!=NULL){ MSFilter *dec; if (stream->decoder!=NULL && stream->decoder->desc->enc_fmt!=NULL && strcasecmp(pt->mime_type,stream->decoder->desc->enc_fmt)==0){ /* same formats behind different numbers, nothing to do */ return; } dec=ms_filter_create_decoder(pt->mime_type); if (dec!=NULL){ ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0); if (stream->tee2) ms_filter_unlink(stream->decoder,0,stream->tee2,0); else if(stream->output) ms_filter_unlink(stream->decoder,0,stream->output,0); ms_filter_postprocess(stream->decoder); ms_filter_destroy(stream->decoder); stream->decoder=dec; if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp); ms_filter_link (stream->rtprecv, 0, stream->decoder, 0); if (stream->tee2) ms_filter_link(stream->decoder,0,stream->tee2,0); else if(stream->output) ms_filter_link (stream->decoder,0 , stream->output, 0); ms_filter_preprocess(stream->decoder,stream->ticker); ms_filter_set_notify_callback(dec, event_cb, stream); }else{ ms_warning("No decoder found for %s",pt->mime_type); } }else{ ms_warning("No payload defined with number %i",payload); } }