예제 #1
0
static void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp,
          int jitter, int bitrate, MSVideoSize vs, bool_t ec, bool_t agc, bool_t eq)
{
	AudioStream *audio=NULL;
#ifdef VIDEO_ENABLED
	VideoStream *video=NULL;
#endif
	RtpSession *session=NULL;
	PayloadType *pt;
	RtpProfile *profile=rtp_profile_clone_full(&av_profile);
	OrtpEvQueue *q=ortp_ev_queue_new();	

	ms_init();
	signal(SIGINT,stop_handler);
	pt=rtp_profile_get_payload(profile,payload);
	if (pt==NULL){
		printf("Error: no payload defined with number %i.",payload);
		exit(-1);
	}
	if (fmtp!=NULL) payload_type_set_send_fmtp(pt,fmtp);
	if (bitrate>0) pt->normal_bitrate=bitrate;

	if (pt->type!=PAYLOAD_VIDEO){
		MSSndCardManager *manager=ms_snd_card_manager_get();
		MSSndCard *capt= capture_card==NULL ? ms_snd_card_manager_get_default_capture_card(manager) :
				ms_snd_card_manager_get_card(manager,capture_card);
		MSSndCard *play= playback_card==NULL ? ms_snd_card_manager_get_default_playback_card(manager) :
				ms_snd_card_manager_get_card(manager,playback_card);
		audio=audio_stream_new(localport,ms_is_ipv6(remote_ip));
		audio_stream_enable_automatic_gain_control(audio,agc);
		audio_stream_enable_noise_gate(audio,use_ng);
		audio_stream_set_echo_canceller_params(audio,ec_len_ms,ec_delay_ms,ec_framesize);
		printf("Starting audio stream.\n");
	
		audio_stream_start_full(audio,profile,remote_ip,remoteport,remoteport+1, payload, jitter,infile,outfile,
		                        outfile==NULL ? play : NULL ,infile==NULL ? capt : NULL,infile!=NULL ? FALSE: ec);
		
		if (audio) {
			if (use_ng && ng_threshold!=-1)
				ms_filter_call_method(audio->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_threshold);
			session=audio->session;
		}
	}else{
#ifdef VIDEO_ENABLED
		if (eq){
			ms_fatal("Cannot put an audio equalizer in a video stream !");
			exit(-1);
		}
		printf("Starting video stream.\n");
		video=video_stream_new(localport, ms_is_ipv6(remote_ip));
		video_stream_set_sent_video_size(video,vs);
		video_stream_use_preview_video_window(video,two_windows);
		video_stream_start(video,profile,
					remote_ip,
					remoteport,remoteport+1,
					payload,
					jitter,
					ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get()));
		session=video->session;
#else
		printf("Error: video support not compiled.\n");
#endif
	}
  if (eq || ec){ /*read from stdin interactive commands */
    char commands[128];
    commands[127]='\0';
    ms_sleep(1);  /* ensure following text be printed after ortp messages */
    if (eq)
      printf("\nPlease enter equalizer requests, such as 'eq active 1', 'eq active 0', 'eq 1200 0.1 200'\n");
    if (ec)
      printf("\nPlease enter echo canceller requests: ec reset; ec <delay ms> <tail_length ms'\n");
    while(fgets(commands,sizeof(commands)-1,stdin)!=NULL){
      int active,freq,freq_width;
      int delay_ms, tail_ms;
      float gain;
      if (sscanf(commands,"eq active %i",&active)==1){
        audio_stream_enable_equalizer(audio,active);
        printf("OK\n");
      }else if (sscanf(commands,"eq %i %f %i",&freq,&gain,&freq_width)==3){
        audio_stream_equalizer_set_gain(audio,freq,gain,freq_width);
        printf("OK\n");
      }else if (sscanf(commands,"eq %i %f",&freq,&gain)==2){
        audio_stream_equalizer_set_gain(audio,freq,gain,0);
        printf("OK\n");
      }else if (strstr(commands,"dump")){
        int n=0,i;
        float *t;
        ms_filter_call_method(audio->equalizer,MS_EQUALIZER_GET_NUM_FREQUENCIES,&n);
        t=(float*)alloca(sizeof(float)*n);
        ms_filter_call_method(audio->equalizer,MS_EQUALIZER_DUMP_STATE,t);
        for(i=0;i<n;++i){
          if (fabs(t[i]-1)>0.01){
            printf("%i:%f:0 ",(i*pt->clock_rate)/(2*n),t[i]);
          }
        }
        printf("\nOK\n");
      }else if (sscanf(commands,"ec reset %i",&active)==1){
          //audio_stream_enable_equalizer(audio,active);
          //printf("OK\n");
      }else if (sscanf(commands,"ec active %i",&active)==1){
          //audio_stream_enable_equalizer(audio,active);
          //printf("OK\n");
      }else if (sscanf(commands,"ec %i %i",&delay_ms,&tail_ms)==2){
        audio_stream_set_echo_canceller_params(audio,tail_ms,delay_ms,128);
        // revisit: workaround with old method call to force echo reset
        delay_ms*=8;
        ms_filter_call_method(audio->ec,MS_FILTER_SET_PLAYBACKDELAY,&delay_ms);
        printf("OK\n");
      }else if (strstr(commands,"quit")){
        break;
      }else printf("Cannot understand this.\n");
    }
	}else{  /* no interactive stuff - continuous debug output */
		rtp_session_register_event_queue(session,q);
		while(cond)
		{
			int n;
			for(n=0;n<100;++n){
	#ifdef WIN32
				MSG msg;
				Sleep(10);
				while (PeekMessage(&msg, NULL, 0, 0,1)){
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
	#else
				struct timespec ts;
				ts.tv_sec=0;
				ts.tv_nsec=10000000;
				nanosleep(&ts,NULL);
	#endif
	#if defined(VIDEO_ENABLED)
				if (video) video_stream_iterate(video);
	#endif
			}
			ortp_global_stats_display();
			if (session){
				printf("Bandwidth usage: download=%f kbits/sec, upload=%f kbits/sec\n",
					rtp_session_compute_recv_bandwidth(session)*1e-3,
					rtp_session_compute_send_bandwidth(session)*1e-3);
				parse_events(q);
			}
		}
					}
	
	printf("stopping all...\n");
	
	if (audio) audio_stream_stop(audio);
#ifdef VIDEO_ENABLED
	if (video) video_stream_stop(video);
#endif
	ortp_ev_queue_destroy(q);
	rtp_profile_destroy(profile);
}
예제 #2
0
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){
	LinphoneCore *lc=call->core;
	LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
	const char *tool="linphone-" LINPHONE_VERSION;
	char *cname;
	int used_pt=-1;
#ifdef VIDEO_ENABLED
	const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
		    					SalProtoRtpAvp,SalVideo);
#endif
	bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
	
	if(call->audiostream == NULL)
	{
		ms_fatal("start_media_stream() called without prior init !");
		return;
	}
	call->current_params = call->params;
	/* adjust rtp jitter compensation. It must be at least the latency of the sound card */
	int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp);

	if (call->media_start_time==0) call->media_start_time=time(NULL);

	cname=linphone_address_as_string_uri_only(me);
	{
		const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
		    					SalProtoRtpAvp,SalAudio);
		if (stream && stream->dir!=SalStreamInactive && stream->port!=0){
			MSSndCard *playcard=lc->sound_conf.lsd_card ? 
				lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
			MSSndCard *captcard=lc->sound_conf.capt_sndcard;
			const char *playfile=lc->play_file;
			const char *recfile=lc->rec_file;
			call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
			bool_t use_ec,use_arc_audio=use_arc;

			if (used_pt!=-1){
				if (playcard==NULL) {
					ms_warning("No card defined for playback !");
				}
				if (captcard==NULL) {
					ms_warning("No card defined for capture !");
				}
				/*Replace soundcard filters by inactive file players or recorders
				 when placed in recvonly or sendonly mode*/
				if (stream->port==0 || stream->dir==SalStreamRecvOnly){
					captcard=NULL;
					playfile=NULL;
				}else if (stream->dir==SalStreamSendOnly){
					playcard=NULL;
					captcard=NULL;
					recfile=NULL;
					/*And we will eventually play "playfile" if set by the user*/
					/*playfile=NULL;*/
				}
				if (send_ringbacktone){
					captcard=NULL;
					playfile=NULL;/* it is setup later*/
				}
				/*if playfile are supplied don't use soundcards*/
				if (lc->use_files) {
					captcard=NULL;
					playcard=NULL;
				}
				use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc);
#if defined(VIDEO_ENABLED)
				if (vstream && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){
					/*when video is used, do not make adaptive rate control on audio, it is stupid.*/
					use_arc_audio=FALSE;
	#if defined(ANDROID)
					/*On android we have to disable the echo canceller to preserve CPU for video codecs */
					use_ec=FALSE;
	#endif
				}
#endif
				audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc_audio);
				audio_stream_start_full(
					call->audiostream,
					call->audio_profile,
					stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
					stream->port,
					stream->port+1,
					used_pt,
					jitt_comp,
					playfile,
					recfile,
					playcard,
					captcard,
					use_ec
					);
				post_configure_audio_streams(call);
				if (all_inputs_muted && !send_ringbacktone){
					audio_stream_set_mic_gain(call->audiostream,0);
				}
				if (stream->dir==SalStreamSendOnly && playfile!=NULL){
					int pause_time=500;
					ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
				}
				if (send_ringbacktone){
					setup_ring_player(lc,call);
				}
				audio_stream_set_rtcp_information(call->audiostream, cname, tool);
			}else ms_warning("No audio stream accepted ?");
		}
	}
#ifdef VIDEO_ENABLED
	{
		
		used_pt=-1;
		/* shutdown preview */
		if (lc->previewstream!=NULL) {
			video_preview_stop(lc->previewstream);
			lc->previewstream=NULL;
		}
		call->current_params.has_video=FALSE;
		if (vstream && vstream->dir!=SalStreamInactive && vstream->port!=0) {
			const char *addr=vstream->addr[0]!='\0' ? vstream->addr : call->resultdesc->addr;
			call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
			if (used_pt!=-1){
				VideoStreamDir dir=VideoStreamSendRecv;
				MSWebCam *cam=lc->video_conf.device;
				bool_t is_inactive=FALSE;

				call->current_params.has_video=TRUE;
				
				video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
				video_stream_enable_self_view(call->videostream,lc->video_conf.selfview);
				if (lc->video_window_id!=0)
					video_stream_set_native_window_id(call->videostream,lc->video_window_id);
				if (lc->preview_window_id!=0)
					video_stream_set_native_preview_window_id (call->videostream,lc->preview_window_id);
				video_stream_use_preview_video_window (call->videostream,lc->use_preview_window);
				
				if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
					cam=get_nowebcam_device();
					dir=VideoStreamSendOnly;
				}else if (vstream->dir==SalStreamRecvOnly && lc->video_conf.display ){
					dir=VideoStreamRecvOnly;
				}else if (vstream->dir==SalStreamSendRecv){
					if (lc->video_conf.display && lc->video_conf.capture)
						dir=VideoStreamSendRecv;
					else if (lc->video_conf.display)
						dir=VideoStreamRecvOnly;
					else
						dir=VideoStreamSendOnly;
				}else{
					ms_warning("video stream is inactive.");
					/*either inactive or incompatible with local capabilities*/
					is_inactive=TRUE;
				}
				if (call->camera_active==FALSE || all_inputs_muted){
					cam=get_nowebcam_device();
				}
				if (!is_inactive){
					video_stream_set_direction (call->videostream, dir);
					video_stream_start(call->videostream,
						call->video_profile, addr, vstream->port,
						vstream->port+1,
						used_pt, jitt_comp, cam);
					video_stream_set_rtcp_information(call->videostream, cname,tool);
				}
			}else ms_warning("No video stream accepted.");
		}else{
			ms_warning("No valid video stream defined.");
		}
	}
#endif
	call->all_muted=all_inputs_muted;
	call->playing_ringbacktone=send_ringbacktone;
	call->up_bw=linphone_core_get_upload_bandwidth(lc);
	
	if (ortp_zrtp_available()) {
		OrtpZrtpParams params;
		params.zid=get_hexa_zrtp_identifier(lc);
		params.zid_file=lc->zrtp_secrets_cache;
		audio_stream_enable_zrtp(call->audiostream,&params);
	}

	goto end;
	end:
		ms_free(cname);
		linphone_address_destroy(me);
}