// 构造发送 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; }
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_); }
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; }
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; }
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(¶m, "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(¶m); 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_); }
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; }