コード例 #1
0
ファイル: test.cpp プロジェクト: FihlaTV/conference
// 构造发送 source --> rtp session
static MSFilter *build_sender_chain(const char *ip, int port)
{
	MSFilter *f_source = ms_filter_new_from_name("ZonekeyH264Source");
	MSFilter *f_rtp = ms_filter_new(MS_RTP_SEND_ID);

	fprintf(stdout, "sendto %s:%d\n", ip, port);
	RtpSession *rtp = rtp_session_new(RTP_SESSION_SENDONLY);
	rtp_session_set_rtp_socket_send_buffer_size(rtp, 3*1024*1024);
	rtp_session_set_remote_addr_and_port(rtp, ip, port, port+1);
	rtp_session_set_payload_type(rtp, 100);
	//rtp_session_enable_jitter_buffer(rtp, 0);	// 禁用的

	JBParameters jb;
	jb.adaptive = 1;
	jb.max_packets = -1;
	jb.max_size = -1;
	jb.min_size = jb.nom_size = 300;
	rtp_session_set_jitter_buffer_params(rtp, &jb);

	ms_filter_call_method(f_rtp, MS_RTP_SEND_SET_SESSION, rtp);

	ms_filter_link(f_source, 0, f_rtp, 0);

	return f_source;
}
コード例 #2
0
ファイル: VodWnd.cpp プロジェクト: FihlaTV/conference
void VodWnd::vod(const char *ip, int rtp_port, int rtcp_port)
{
    server_ip_ = ip;
    server_rtp_port_ = rtp_port;
    server_rtcp_port_ = rtcp_port;

    rtp_ = rtp_session_new(RTP_SESSION_RECVONLY);
    rtp_session_set_payload_type(rtp_, 100);
    rtp_session_set_local_addr(rtp_, util_get_myip(), 0, 0);
    rtp_session_set_remote_addr_and_port(rtp_, ip, rtp_port, rtcp_port);

    JBParameters jb;
    jb.adaptive = 1;
    jb.max_packets = 3000;
    jb.max_size = -1;
    jb.min_size = jb.nom_size = 300;
    rtp_session_set_jitter_buffer_params(rtp_, &jb);

    rtp_session_enable_jitter_buffer(rtp_, 0);

    evq_ = ortp_ev_queue_new();
    rtp_session_register_event_queue(rtp_, evq_);

    ticker_ = ms_ticker_new();

    filter_rtp_ = ms_filter_new(MS_RTP_RECV_ID);
    ms_filter_call_method(filter_rtp_, MS_RTP_RECV_SET_SESSION, rtp_);

    filter_decoder_ = ms_filter_new(MS_H264_DEC_ID);

    ZonekeyYUVSinkCallbackParam cbp;
    cbp.ctx = this;
    cbp.push = cb_yuv;
    filter_sink_ = ms_filter_new_from_name("ZonekeyYUVSink");
    ms_filter_call_method(filter_sink_, ZONEKEY_METHOD_YUV_SINK_SET_CALLBACK_PARAM, &cbp);

    ms_filter_link(filter_rtp_, 0, filter_decoder_, 0);
    ms_filter_link(filter_decoder_, 0, filter_sink_, 0);

    ms_ticker_attach(ticker_, filter_rtp_);
}
コード例 #3
0
int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *rem_rtp_ip, int rem_rtp_port,
	const char *rem_rtcp_ip, int rem_rtcp_port, int payload, int jitt_comp, MSWebCam *cam){
	PayloadType *pt;
	RtpSession *rtps=stream->ms.session;
	MSPixFmt format;
	MSVideoSize disp_size;
	int tmp;
	JBParameters jbp;
	const int socket_buf_size=2000000;

	if (cam==NULL){
		cam=ms_web_cam_manager_get_default_cam (
		      ms_web_cam_manager_get());
	}

	pt=rtp_profile_get_payload(profile,payload);
	if (pt==NULL){
		ms_error("videostream.c: undefined payload type.");
		return -1;
	}

	if ((cam != NULL) && (cam->desc->encode_to_mime_type != NULL) && (cam->desc->encode_to_mime_type(cam, pt->mime_type) == TRUE)) {
		stream->source_performs_encoding = TRUE;
	}

	rtp_session_set_profile(rtps,profile);
	if (rem_rtp_port>0) rtp_session_set_remote_addr_full(rtps,rem_rtp_ip,rem_rtp_port,rem_rtcp_ip,rem_rtcp_port);
	rtp_session_set_payload_type(rtps,payload);
	rtp_session_set_jitter_compensation(rtps,jitt_comp);

	rtp_session_signal_connect(stream->ms.session,"payload_type_changed",
			(RtpCallback)mediastream_payload_type_changed,(unsigned long)&stream->ms);

	rtp_session_get_jitter_buffer_params(stream->ms.session,&jbp);
	jbp.max_packets=1000;//needed for high resolution video
	rtp_session_set_jitter_buffer_params(stream->ms.session,&jbp);
	rtp_session_set_rtp_socket_recv_buffer_size(stream->ms.session,socket_buf_size);
	rtp_session_set_rtp_socket_send_buffer_size(stream->ms.session,socket_buf_size);

	if (stream->dir==VideoStreamSendRecv || stream->dir==VideoStreamSendOnly){
		MSConnectionHelper ch;
		/*plumb the outgoing stream */

		if (rem_rtp_port>0) ms_filter_call_method(stream->ms.rtpsend,MS_RTP_SEND_SET_SESSION,stream->ms.session);
		if (stream->source_performs_encoding == FALSE) {
			stream->ms.encoder=ms_filter_create_encoder(pt->mime_type);
			if ((stream->ms.encoder==NULL) ){
				/* big problem: we don't have a registered codec for this payload...*/
				ms_error("videostream.c: No encoder available for payload %i:%s.",payload,pt->mime_type);
				return -1;
			}
		}
		/* creates the filters */
		stream->cam=cam;
		stream->source = ms_web_cam_create_reader(cam);
		stream->tee = ms_filter_new(MS_TEE_ID);
		if (stream->source_performs_encoding == TRUE) {
			stream->ms.encoder = stream->source;	/* Consider the encoder is the source */
		}

		if (pt->normal_bitrate>0){
			MSVideoConfiguration *vconf_list = NULL;
			ms_message("Limiting bitrate of video encoder to %i bits/s",pt->normal_bitrate);
			ms_filter_call_method(stream->ms.encoder, MS_VIDEO_ENCODER_GET_CONFIGURATION_LIST, &vconf_list);
			if (vconf_list != NULL) {
				MSVideoConfiguration vconf = ms_video_find_best_configuration_for_bitrate(vconf_list, pt->normal_bitrate);
				ms_filter_call_method(stream->ms.encoder, MS_VIDEO_ENCODER_SET_CONFIGURATION, &vconf);
			} else {
				ms_filter_call_method(stream->ms.encoder, MS_FILTER_SET_BITRATE, &pt->normal_bitrate);
			}
		}
		if (pt->send_fmtp){
			ms_filter_call_method(stream->ms.encoder,MS_FILTER_ADD_FMTP,pt->send_fmtp);
		}
		if (stream->use_preview_window){
			if (stream->rendercb==NULL){
				stream->output2=ms_filter_new_from_name (stream->display_name);
			}
		}

		configure_video_source (stream);
		/* and then connect all */
		ms_connection_helper_start(&ch);
		ms_connection_helper_link(&ch, stream->source, -1, 0);
		if (stream->pixconv) {
			ms_connection_helper_link(&ch, stream->pixconv, 0, 0);
		}
		if (stream->sizeconv) {
			ms_connection_helper_link(&ch, stream->sizeconv, 0, 0);
		}
		ms_connection_helper_link(&ch, stream->tee, 0, 0);
		if (stream->source_performs_encoding == FALSE) {
			ms_connection_helper_link(&ch, stream->ms.encoder, 0, 0);
		}
		ms_connection_helper_link(&ch, stream->ms.rtpsend, 0, -1);
		if (stream->output2){
			if (stream->preview_window_id!=0){
				ms_filter_call_method(stream->output2, MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID,&stream->preview_window_id);
			}
			ms_filter_link(stream->tee,1,stream->output2,0);
		}
	}
	if (stream->dir==VideoStreamSendRecv || stream->dir==VideoStreamRecvOnly){
		MSConnectionHelper ch;
		MSVideoDisplayDecodingSupport decoding_support;

		if (stream->rendercb!=NULL){
			stream->output=ms_filter_new(MS_EXT_DISPLAY_ID);
			ms_filter_set_notify_callback(stream->output,ext_display_cb,stream);
		}else{
			stream->output=ms_filter_new_from_name (stream->display_name);
		}

		/* Don't allow null output */
		if(stream->output == NULL) {
			ms_fatal("No video display filter could be instantiated. Please check build-time configuration");
		}

		/* Check if the output filter can perform the decoding process */
		decoding_support.mime_type = pt->mime_type;
		decoding_support.supported = FALSE;
		ms_filter_call_method(stream->output, MS_VIDEO_DISPLAY_SUPPORT_DECODING, &decoding_support);
		stream->output_performs_decoding = decoding_support.supported;

		/*plumb the incoming stream */
		if (stream->output_performs_decoding == TRUE) {
			stream->ms.decoder = stream->output;	/* Consider the decoder is the output */
		} else {
			stream->ms.decoder=ms_filter_create_decoder(pt->mime_type);
			if ((stream->ms.decoder==NULL) ){
				/* big problem: we don't have a registered decoderfor this payload...*/
				ms_error("videostream.c: No decoder available for payload %i:%s.",payload,pt->mime_type);
				ms_filter_destroy(stream->output);
				return -1;
			}
		}
		ms_filter_set_notify_callback(stream->ms.decoder, event_cb, stream);

		stream->ms.rtprecv = ms_filter_new (MS_RTP_RECV_ID);
		ms_filter_call_method(stream->ms.rtprecv,MS_RTP_RECV_SET_SESSION,stream->ms.session);

		if (stream->output_performs_decoding == FALSE) {
			stream->jpegwriter=ms_filter_new(MS_JPEG_WRITER_ID);
			if (stream->jpegwriter)
				stream->tee2=ms_filter_new(MS_TEE_ID);
		}

		/* set parameters to the decoder*/
		if (pt->send_fmtp){
			ms_filter_call_method(stream->ms.decoder,MS_FILTER_ADD_FMTP,pt->send_fmtp);
		}
		if (pt->recv_fmtp!=NULL)
			ms_filter_call_method(stream->ms.decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);

		/*force the decoder to output YUV420P */
		format=MS_YUV420P;
		ms_filter_call_method(stream->ms.decoder,MS_FILTER_SET_PIX_FMT,&format);

		/*configure the display window */
		if(stream->output != NULL) {
			disp_size.width=MS_VIDEO_SIZE_CIF_W;
			disp_size.height=MS_VIDEO_SIZE_CIF_H;
			tmp=1;
			ms_filter_call_method(stream->output,MS_FILTER_SET_VIDEO_SIZE,&disp_size);
			ms_filter_call_method(stream->output,MS_VIDEO_DISPLAY_ENABLE_AUTOFIT,&tmp);
			ms_filter_call_method(stream->output,MS_FILTER_SET_PIX_FMT,&format);
			ms_filter_call_method(stream->output,MS_VIDEO_DISPLAY_SET_LOCAL_VIEW_MODE,&stream->corner);
			if (stream->window_id!=0){
				ms_filter_call_method(stream->output, MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID,&stream->window_id);
			}
			if (stream->display_filter_auto_rotate_enabled) {
				ms_filter_call_method(stream->output,MS_VIDEO_DISPLAY_SET_DEVICE_ORIENTATION,&stream->device_orientation);
			}
		}
		/* and connect the filters */
		ms_connection_helper_start (&ch);
		ms_connection_helper_link (&ch,stream->ms.rtprecv,-1,0);
		if (stream->output_performs_decoding == FALSE) {
			ms_connection_helper_link (&ch,stream->ms.decoder,0,0);
		}
		if (stream->tee2){
			ms_connection_helper_link (&ch,stream->tee2,0,0);
			ms_filter_link(stream->tee2,1,stream->jpegwriter,0);
		}
		if (stream->output!=NULL)
			ms_connection_helper_link (&ch,stream->output,0,-1);
		/* the video source must be send for preview , if it exists*/
		if (stream->tee!=NULL && stream->output!=NULL && stream->output2==NULL)
			ms_filter_link(stream->tee,1,stream->output,1);
	}
	if (stream->dir == VideoStreamSendOnly) {
		stream->ms.rtprecv = ms_filter_new (MS_RTP_RECV_ID);
		ms_filter_call_method(stream->ms.rtprecv, MS_RTP_RECV_SET_SESSION, stream->ms.session);
		stream->ms.voidsink = ms_filter_new(MS_VOID_SINK_ID);
		ms_filter_link(stream->ms.rtprecv, 0, stream->ms.voidsink, 0);
	}

	/* create the ticker */
	if (stream->ms.ticker==NULL) start_ticker(&stream->ms);
	
	stream->ms.start_time=ms_time(NULL);
	stream->ms.is_beginning=TRUE;

	/* attach the graphs */
	if (stream->source)
		ms_ticker_attach (stream->ms.ticker, stream->source);
	if (stream->ms.rtprecv)
		ms_ticker_attach (stream->ms.ticker, stream->ms.rtprecv);
	return 0;
}
コード例 #4
0
ファイル: main.cpp プロジェクト: FihlaTV/conference
int main(int argc, char **argv)
{
	ortp_init();
	ms_init();
	zk_xmpp_uac_init();
	ortp_set_log_level_mask(ORTP_MESSAGE);

	if (argc < 2) {
		fprintf(stderr, "usage: %s <zqpkt src url> [s]\n", argv[0]);
		return -1;
	}

	bool stream_mode = false;
	if (argc == 3 && argv[2][0] == 's')
		stream_mode = true;

	_stream_mode = stream_mode;

	if (stream_mode)
		fprintf(stdout, "=== STREAMING MODE ===\n\n");
	else
		fprintf(stdout, "=== SOURCING MODE ===\n\n");

	_url = argv[1];
	_env = CreateEvent(0, 0, 0, 0);

	fprintf(stdout, "%s: using zqpkt src '%s', just wait mcu .....\n", argv[0], argv[1]);

	// 使用 normaluser 登录
	cb_xmpp_uac cbs = { 0, 0, 0, 0, cb_connect_notify };
	_uac = zk_xmpp_uac_log_in(get_user_jid(), "ddkk1212", &cbs, 0);

	WaitForSingleObject(_env, 10000);

	if (_sid == -1) {
		fprintf(stderr, ":( somthing err, exit!\n");
	}
	else {
		SetConsoleCtrlHandler(signal_ctrl_c, 1);
		
		const char *src_url = argv[1];
		const char *target_ip = _ip.c_str();
		int target_port = _rtp_port;
		int target_port2 = _rtcp_port;

		//fprintf(stdout, "target ip=%s\ntarget port=%d\n\n", target_ip, target_port);

		// only support h264
		rtp_profile_set_payload(&av_profile,100, &payload_type_h264);

		/// 使用 zonekey.h264.source filter
		zonekey_h264_source_register();
		MSFilterDesc *desc = ms_filter_lookup_by_name("ZonekeyH264Source");
		MSFilter *source = ms_filter_new_from_desc(desc);

		if (_stream_mode)
			zonekey_yuv_sink_register();

		// 获取 writer_params
		ZonekeyH264SourceWriterParam writer_param;
		ms_filter_call_method(source, ZONEKEY_METHOD_H264_SOURCE_GET_WRITER_PARAM, &writer_param);

		// RTP Session
		RtpSession *rtpsess = rtp_session_new(RTP_SESSION_SENDRECV);	// 
		rtp_session_set_local_addr(rtpsess, "0.0.0.0", -1, -1);	// 随机端口
		rtp_session_set_remote_addr_and_port(rtpsess, target_ip, target_port, target_port2);
		rtp_session_set_payload_type(rtpsess, 100);	// h264

		JBParameters jb;
		jb.adaptive = 1;
		jb.max_packets = 3000;
		jb.max_size = -1;
		jb.min_size = jb.nom_size = 300;
		rtp_session_set_jitter_buffer_params(rtpsess, &jb);
	
		// disable video jitter control
		rtp_session_enable_jitter_buffer(rtpsess, 0);

		/// rtp sender
		MSFilter *rtp_sender = ms_filter_new(MS_RTP_SEND_ID);
		ms_filter_call_method(rtp_sender, MS_RTP_SEND_SET_SESSION, rtpsess);

		// connect source --> rtp sender
		ms_filter_link(source, 0, rtp_sender, 0);

		// MSTicker
		MSTicker *ticker = ms_ticker_new();

		// attach ticker
		ms_ticker_attach(ticker, source);

		if (_stream_mode) {
			// FIXME: recv, but ....
			MSFilter *rtp_recver = ms_filter_new(MS_RTP_RECV_ID);
			ms_filter_call_method(rtp_recver, MS_RTP_RECV_SET_SESSION, rtpsess);

			MSFilter *decoder = ms_filter_new(MS_H264_DEC_ID);
			MSFilter *sink = ms_filter_new_from_name("ZonekeyYUVSink");

			ms_filter_link(rtp_recver, 0, decoder, 0);
			ms_filter_link(decoder, 0, sink, 0);

			MSTicker *tk = ms_ticker_new();
			//ms_ticker_attach(tk, rtp_recver);
		}

		// 利用 libzqpkt 接收 h264 数据,并且调用 zonekey h264 source 的 writer() 
		void *zqp = 0;
		if (zqpsrc_open(&zqp, src_url) < 0) {
			fprintf(stderr, "to open src err\n");
			return -1;
		}

		while (!_quit) {
			zq_pkt *pkt = zqpsrc_getpkt(zqp);
			if (pkt) {
				if (pkt->type == 1) {
					// h264
					writer_param.write(writer_param.ctx, pkt->ptr, pkt->len, pkt->pts / 45000.0);
				}

				zqpsrc_freepkt(zqp, pkt);
			}
			else
				break;
		}

		// 发送删除 sid 的命令
		char options[128], *cmd="test.fc.del_source";
		if (_stream_mode) {
			snprintf(options, sizeof(options), "streamid=%d", _sid);
			cmd = "test.dc.del_stream";
		}
		else
			snprintf(options, sizeof(options), "sid=%d", _sid);

		zk_xmpp_uac_send_cmd(_uac, get_mcu_jid(), cmd, options, 0, cb_response);
		fprintf(stderr, "\n\nen. to del sid=%d\n\n", _sid);

		zqpsrc_close(zqp);
		fprintf(stderr, "END!\n");

		WaitForSingleObject(_env, 3000);	// 等待 test.fc.de_source 发送成功
	}

	return 0;
}
コード例 #5
0
ファイル: CameraStream.cpp プロジェクト: FihlaTV/conference
void CameraStream::init()
{
	/** 获取第一帧图像,初始化 sws_,创建 h264 encoder ....
	 */
	IplImage *img = cvQueryFrame(cap_);
	// FIXME: 未必是 rgb24 吧???
	sws_ = sws_getContext(img->width, img->height, PIX_FMT_RGB24, WIDTH, HEIGHT, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0);

	x264_param_t param;
	x264_param_default_preset(&param, "veryfast", "zerolatency");
	param.i_threads = 0;
	param.i_width = WIDTH;
	param.i_height = HEIGHT;
	param.i_keyint_max = FPS * 2;
	param.i_fps_den = 1;
	param.i_fps_num = FPS;
	param.i_slice_max_size = 1300;
	param.b_repeat_headers = 1;
	param.b_annexb = 1;
	param.rc.i_rc_method = X264_RC_ABR;
	param.rc.i_bitrate = KBPS;
	param.rc.i_vbv_max_bitrate = KBPS*1.1;
		
	encoder_ = x264_encoder_open(&param);

	avpicture_alloc(&pic_, PIX_FMT_YUV420P, WIDTH, HEIGHT);

	rtp_ = rtp_session_new(RTP_SESSION_SENDRECV);
	rtp_session_set_payload_type(rtp_, 100);
	rtp_session_set_remote_addr_and_port(rtp_, server_ip_.c_str(), server_rtp_port_, server_rtcp_port_);
	rtp_session_set_local_addr(rtp_, util_get_myip(), 0, 0);
	JBParameters jb;
	jb.adaptive = 1;
	jb.max_packets = 500;
	jb.max_size = -1;
	jb.min_size = jb.nom_size = 300;
	rtp_session_set_jitter_buffer_params(rtp_, &jb);

	filter_rtp_sender_ = ms_filter_new(MS_RTP_SEND_ID);
	ms_filter_call_method(filter_rtp_sender_, MS_RTP_SEND_SET_SESSION, rtp_);

	filter_h264_sender_ = ms_filter_new_from_name("ZonekeyH264Source");
	ms_filter_call_method(filter_h264_sender_, ZONEKEY_METHOD_H264_SOURCE_GET_WRITER_PARAM, &sender_params_);

	filter_rtp_recver_ = ms_filter_new(MS_RTP_RECV_ID);
	ms_filter_call_method(filter_rtp_recver_, MS_RTP_RECV_SET_SESSION, rtp_);

	filter_decoder_ = ms_filter_new(MS_H264_DEC_ID);

	filter_yuv_sink_ = ms_filter_new_from_name("ZonekeyYUVSink");
	// TODO: 显示 ...

	ms_filter_link(filter_rtp_recver_, 0, filter_decoder_, 0);
	ms_filter_link(filter_decoder_, 0, filter_yuv_sink_, 0);

	ticker_recver_ = ms_ticker_new();
	ms_ticker_attach(ticker_recver_, filter_rtp_recver_);

	ms_filter_link(filter_h264_sender_, 0, filter_rtp_sender_, 0);

	ticker_sender_ = ms_ticker_new();
	ms_ticker_attach(ticker_sender_, filter_h264_sender_);
}
コード例 #6
0
int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *remip, int remport,
	int rem_rtcp_port, int payload, int jitt_comp, MSWebCam *cam){
	PayloadType *pt;
	RtpSession *rtps=stream->session;
	MSPixFmt format;
	MSVideoSize disp_size;
	int tmp;
	JBParameters jbp;
	const int socket_buf_size=2000000;

	if (cam==NULL){
		cam=ms_web_cam_manager_get_default_cam (
		      ms_web_cam_manager_get());                                
	}

	pt=rtp_profile_get_payload(profile,payload);
	if (pt==NULL){
		ms_error("videostream.c: undefined payload type.");
		return -1;
	}
	
	rtp_session_set_profile(rtps,profile);
	if (remport>0) rtp_session_set_remote_addr_full(rtps,remip,remport,rem_rtcp_port);
	rtp_session_set_payload_type(rtps,payload);
	rtp_session_set_jitter_compensation(rtps,jitt_comp);

	rtp_session_signal_connect(stream->session,"payload_type_changed",
			(RtpCallback)payload_type_changed,(unsigned long)stream);

	rtp_session_set_recv_buf_size(stream->session,MAX_RTP_SIZE);

	rtp_session_get_jitter_buffer_params(stream->session,&jbp);
	jbp.max_packets=1000;//needed for high resolution video
	rtp_session_set_jitter_buffer_params(stream->session,&jbp);
	rtp_session_set_rtp_socket_recv_buffer_size(stream->session,socket_buf_size);
	rtp_session_set_rtp_socket_send_buffer_size(stream->session,socket_buf_size);
	
	if (stream->dir==VideoStreamSendRecv || stream->dir==VideoStreamSendOnly){
		/*plumb the outgoing stream */

		if (remport>0) ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_SET_SESSION,stream->session);
		stream->encoder=ms_filter_create_encoder(pt->mime_type);
		if ((stream->encoder==NULL) ){
			/* big problem: we don't have a registered codec for this payload...*/
			ms_error("videostream.c: No encoder available for payload %i:%s.",payload,pt->mime_type);
			return -1;
		}
		/* creates the filters */
		stream->source = ms_web_cam_create_reader(cam);
		stream->tee = ms_filter_new(MS_TEE_ID);
		
		if (pt->normal_bitrate>0){
			ms_message("Limiting bitrate of video encoder to %i bits/s",pt->normal_bitrate);
			ms_filter_call_method(stream->encoder,MS_FILTER_SET_BITRATE,&pt->normal_bitrate);
		}
		if (pt->send_fmtp){
			ms_filter_call_method(stream->encoder,MS_FILTER_ADD_FMTP,pt->send_fmtp);
		}
		if (stream->use_preview_window){
			if (stream->rendercb==NULL){
				stream->output2=ms_filter_new_from_name (stream->display_name);
			}
		}
		
		configure_video_source (stream);
			/* and then connect all */
		ms_filter_link (stream->source, 0, stream->pixconv, 0);
		ms_filter_link (stream->pixconv, 0, stream->sizeconv, 0);
		ms_filter_link (stream->sizeconv, 0, stream->tee, 0);
		ms_filter_link (stream->tee, 0 ,stream->encoder, 0 );
		ms_filter_link (stream->encoder,0, stream->rtpsend,0);
		if (stream->output2){
			if (stream->window_id!=0){
				ms_filter_call_method(stream->output2, MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID,&stream->preview_window_id);
			}
			ms_filter_link(stream->tee,1,stream->output2,0);
		}

	}
	if (stream->dir==VideoStreamSendRecv || stream->dir==VideoStreamRecvOnly){
		MSConnectionHelper ch;
		/*plumb the incoming stream */
		stream->decoder=ms_filter_create_decoder(pt->mime_type);
		if ((stream->decoder==NULL) ){
			/* big problem: we don't have a registered decoderfor this payload...*/
			ms_error("videostream.c: No decoder available for payload %i:%s.",payload,pt->mime_type);
			return -1;
		}
		stream->rtprecv = ms_filter_new (MS_RTP_RECV_ID);
		ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,stream->session);
 

		if(stream->conf_mode==FALSE)
		{
			stream->tee2=ms_filter_new(MS_TEE_ID);
			stream->jpegwriter=ms_filter_new(MS_JPEG_WRITER_ID);
		}

		if (stream->rendercb!=NULL){
			stream->output=ms_filter_new(MS_EXT_DISPLAY_ID);
			ms_filter_set_notify_callback (stream->output,ext_display_cb,stream);
		}else{
			if(stream->conf_mode)
				stream->output=ms_filter_new(MS_VOID_SINK_ID);
			else
				stream->output=ms_filter_new_from_name (stream->display_name);
		}
		/* set parameters to the decoder*/
		if (pt->send_fmtp){
			ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,pt->send_fmtp);
		}
		if (pt->recv_fmtp!=NULL)
			ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);
	
		/*force the decoder to output YUV420P */
		format=MS_YUV420P;
		ms_filter_call_method(stream->decoder,MS_FILTER_SET_PIX_FMT,&format);

		/*configure the display window */
		disp_size.width=MS_VIDEO_SIZE_CIF_W;
		disp_size.height=MS_VIDEO_SIZE_CIF_H;
		tmp=1;
		ms_filter_call_method(stream->output,MS_FILTER_SET_VIDEO_SIZE,&disp_size);
		ms_filter_call_method(stream->output,MS_VIDEO_DISPLAY_ENABLE_AUTOFIT,&tmp);
		ms_filter_call_method(stream->output,MS_FILTER_SET_PIX_FMT,&format);
		ms_filter_call_method(stream->output,MS_VIDEO_DISPLAY_SET_LOCAL_VIEW_MODE,&stream->corner);
		if (stream->window_id!=0){
			ms_filter_call_method(stream->output, MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID,&stream->window_id);
		}

		/* and connect the filters */
		ms_connection_helper_start (&ch);
		ms_connection_helper_link (&ch,stream->rtprecv,-1,0);
		ms_connection_helper_link (&ch,stream->decoder,0,0);
		if (stream->tee2){
			ms_connection_helper_link (&ch,stream->tee2,0,0);
			ms_filter_link(stream->tee2,1,stream->jpegwriter,0);
			//Êä³öÊÓƵ¼ÖÆÖ¡.
			if(stream->video_record)
				ms_filter_link(stream->tee2,2,stream->video_record,0);
			
		}
		ms_connection_helper_link (&ch,stream->output,0,-1);
		/* the video source must be send for preview , if it exists*/
		if (stream->tee!=NULL && stream->output2==NULL)
			ms_filter_link(stream->tee,1,stream->output,1);
	}

	/* create the ticker */
	stream->ticker = ms_ticker_new();
	ms_ticker_set_name(stream->ticker,"Video MSTicker");

	//¼æÈÝPVX Ðëµ÷Õû±àÂë¼ä¸ô
	//stream->ticker->interval = 3;
#ifdef ENABLE_UDT
	if(stream->enable_udt){
		stream->udt = ms_filter_new(MS_UDT_TRANSPORT_ID);
		ms_filter_call_method(stream->udt,MS_UDT_SET_RTP_SESSION,stream->session);
	}
#endif //ENABLE_UDT
	/* attach the graphs */
	if (stream->source)
		ms_ticker_attach (stream->ticker, stream->source);
	if (stream->rtprecv)
		ms_ticker_attach (stream->ticker, stream->rtprecv);

#ifdef ENABLE_UDT //×îºóÔËÐУ¬±ÜÃâ×èÈûUI
	if (stream->udt) ms_ticker_attach (stream->ticker, stream->udt);
#endif // ENABLE_UDT

	return 0;
}