在项目中用到了mediastream2,mediastream2是一个框架,引擎,它驱动系统的整个流程,从接收rtp媒体流并解析到媒体解码到显示到android手机屏幕上,都是由mediastream2来驱动完成的。

mediastream2是由一个个filter来完成,我们可以把filter当做一个单独的数据处理模块,它就像一个盒子,有输入和输出接口,数据从输入接口进来,处理完成后,再从输出接口出来进入到下一个filter中,多个filter连接在一起,就组成了一个系统循环。在我们的系统中,主要流程是ipcam发送rtp媒体流,系统接收rtp媒体流并解析,然后进行解码,再显示到android手机屏幕上,因此我们定义了三个filter,分别是:RTP Recv filter(RTP媒体流接收),Video Decoder filter(视频解码)和Android Display filter(视频输出显示),其基本流程如下:

RTP Recv----------------->Video Decoder------------------------------> Android Display

首先我们要调用ms_init()这个函数,这个函数初始化mediastream2。

void ms_init(){
int i;
MSSndCardManager *cm;

#if defined(ENABLE_NLS)
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
#endif

#if !defined(_WIN32_WCE)
if (getenv("MEDIASTREAMER_DEBUG")!=NULL){
ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
}
#endif
#ifdef ANDROID
ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
ortp_set_log_handler(ms_android_log_handler);
#endif
ms_message("Mediastreamer2 " MEDIASTREAMER_VERSION " (git: " GIT_VERSION ") starting.");
/* register builtin MSFilter's */
for (i=0;ms_filter_descs[i]!=NULL;i++){
ms_filter_register(ms_filter_descs[i]);
}
ms_message("Registering all soundcard handlers");
cm=ms_snd_card_manager_get();
for (i=0;ms_snd_card_descs[i]!=NULL;i++){
ms_snd_card_manager_register_desc(cm,ms_snd_card_descs[i]);
}

#ifdef VIDEO_ENABLED
ms_message("Registering all webcam handlers");
{
MSWebCamManager *wm;
wm=ms_web_cam_manager_get();
for (i=0;ms_web_cam_descs[i]!=NULL;i++){
ms_web_cam_manager_register_desc(wm,ms_web_cam_descs[i]);
}
}
#if !defined(NO_FFMPEG)
ms_ffmpeg_check_init();
__register_ffmpeg_encoders_if_possible();
#endif
#endif
#ifdef PACKAGE_PLUGINS_DIR
ms_message("Loading plugins");
ms_load_plugins(PACKAGE_PLUGINS_DIR);
#endif

#if defined(ANDROID) && defined (VIDEO_ENABLED)
if (1) {
libmsandroidopengldisplay_init();
} else {
if (!libmsandroiddisplay_init()) {
libmsandroiddisplaybad_init();
}
}
#endif
ms_message("ms_init() done");
}

在这个函数里面,ms_filter_descs定义了目前支持的所有的filter,进一步分析

MSFilterDesc * ms_filter_descs[]={
&ms_alaw_dec_desc,
&ms_alaw_enc_desc,
&ms_ulaw_dec_desc,
&ms_ulaw_enc_desc,
&ms_rtp_send_desc,
&ms_rtp_recv_desc,
&ms_dtmf_gen_desc,
&ms_ice_desc,
&ms_tee_desc,
&ms_conf_desc,
&ms_join_desc,
&ms_volume_desc,
&ms_void_sink_desc,
//&ms_speex_dec_desc,
//&ms_speex_enc_desc,
//&ms_speex_ec_desc,
&ms_file_player_desc,
&ms_file_rec_desc,
//&ms_resample_desc,
&ms_equalizer_desc,
//&ms_gsm_enc_desc,
//&ms_gsm_dec_desc,
&ms_tone_detector_desc,
&ms_audio_mixer_desc,
&ms_g722_dec_desc,
&ms_g722_enc_desc,
#ifdef VIDEO_ENABLED
&ms_mpeg4_enc_desc,
&ms_mpeg4_dec_desc,
&ms_h263_enc_desc,
&ms_h263_dec_desc,
&ms_h264_dec_desc,
&ms_pix_conv_desc,
&ms_size_conv_desc,
//&ms_vp8_enc_desc,
//&ms_vp8_dec_desc,
#endif
NULL
};

我们可以看到系统定义了很多filter,比如ms_rtp_recv_desc是RTP接收filter,ms_h264_dec_desc是H.264解码filter等等。

MSFilterDesc ms_h264_dec_desc={
.id=MS_H264_DEC_ID,
.name="MSH264Dec",
.text="A H264 decoder based on ffmpeg project.",
.category=MS_FILTER_DECODER,
.enc_fmt="H264",
.ninputs=1,
.noutputs=1,
.init=dec_init,
.process=dec_process,
.uninit=dec_uninit,
.methods=h264_dec_methods
};

在filter定义里面,id是用来标示每个filter的唯一标示符;name是起得一个名称;text是描述,上面就表示该filter是基于ffmpeg的H.264解码;category是分类,有解码器,编码器和其它三种类型;enc_fmt表示媒体类型;ninputs表示input个数,可能每个filter有多个输入接口;noutputs表示输出接口;init定义初始化函数,在调用filter之前必须 调用;process是最核心的处理函数,filter从input端接收数据就调用该函数进行数据处理;uninit定义退出函数;methods表示额外定义的一些函数,使用这个接口可以对filter进行一些参数设置工作,比如在上面的h.264解码filter中定义了专门的函数用来设置h.264解码所需要的fmtp信息。除了mediastream2自带的这些filter以外,我们还可以自己定义filter,按照上面的格式来定义,然后通过ms_filter_register函数注册进来就可以使用了。在我们系统中我们使用ms_rtp_recv_desc来完成rtp的接收解析,使用ms_h264_dec_desc来完成视频解码,使用ms_android_opengl_display_desc来完成在android上的显示。

定义完成了3个filter,接收流,解码并显示,这三个filter是如何创建并连接在一起并工作起来呢?见下面的代码注释

MSConnectionHelper ch;
    /*根据ipcam video的codec来创建相应的解码器filter,创建失败,则退出,在我们系统里面一般是h.264,但我们可以根据rtp媒体类型在自适应选择对应的解码filter*/
    stream->decoder=ms_filter_create_decoder(ipcam_get_codec("video")); // 创建解码filter
    if (stream->decoder==NULL)
    {
        /* big problem: we don't have a registered decoderfor this payload...*/
        ms_error("videostream.c: No decoder available  ");
        return -1;
    }

/*创建rtp接受filter*/
    stream->rtprecv = ms_filter_new (MS_RTP_RECV_ID);//创建RTP接收filter,通过MS_RTP_RECV_ID找到ms_rtp_recv_desc这个filter

/*创建rtp接收filter,需要设置rtp接收filter的会话,会话主要是接收媒体流的socket,告诉filter再哪个socket上接收rtp数据,并限制接收什么样的rtp数据,通过payload type*/

/*stream->session这个是_RtpSession*, 是mediastream2定义的结构体*/
    ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,stream->session);
    ms_message("ssap_ipcam_client_open:session rtpsocket=%d,rtcpsocket=%d",stream->session->rtp.socket,stream->session->rtcp.socket);

/*创建output filter,默认是MSAndroidDisplay,表示输出到android上,通过MSAndroidDisplay找到ms_android_opengl_display_desc*/
    displayName = ms_strdup("MSAndroidDisplay");
    stream->output=ms_filter_new_from_name(displayName);

/*以下是设置fmtp,非常重要,如果不添加fmtp,将会解码失败,mpeg4需要的fmtp在rtsp中是在sdp中
    带过来的,因此要获取fmtp*/
    char fmtp[1000];
    memset(fmtp,0,sizeof(fmtp));
    sprintf(fmtp,"config=%s",ipcam_get_fmtp("video"));
    ms_message("ipcam fmtp=%s",fmtp);
    ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)fmtp);
    format=MS_YUV420P;
    ms_filter_call_method(stream->decoder,MS_FILTER_SET_PIX_FMT,&format);

int tmp;
    /*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_message("v2 sam display windows id=%d,stream=%p",stream->window_id,stream);
        /*设置显示的窗口id,在哪个窗口上显示video*/
        ms_filter_call_method(stream->output, MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID,stream->window_id);
    }

/*以上完成了3个filter的创建,接下来将3个filter串联起来*/
    /* 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);

ms_connection_helper_link (&ch,stream->output,0,-1);

/*filter串联起来了以后,开始启动定时器,整个系统流程开始运转起来*/
    /* create the ticker */
    stream->ticker = ms_ticker_new();
    ms_ticker_set_name(stream->ticker,"Video MSTicker");
    /* attach the graphs */
    if (stream->source)
        ms_ticker_attach (stream->ticker, stream->source);
    if (stream->rtprecv)
        ms_ticker_attach (stream->ticker, stream->rtprecv);

至此,mediastream2就开始运转起来了

基于android手机实时监控ipcam视频之二:mediastream2相关推荐

  1. 基于android手机实时监控ipcam视频之一:RTSP

    我以前做过一个这样的项目,基于android实现手机实时监控ipcam,ipcam厂商提供控件,该控件安装以后,在IE上面输入ipcam的ip地址,就可以实时查看ipcam的图像,这实时视频是通过HT ...

  2. 基于android手机实时监控ipcam视频之三:H.264的RTP打包解析

    因为项目中,ipcam的视频编码方式主要是基于H.264,因此ipcam出来的H.264码流会按照协议rfc3984来打包,mediastream2中收到rtp recv filter的数据后,必须先 ...

  3. 基于android的条码识别技术,基于Android手机的条码识别系统研究

    摘要: 当前,条码技术在商品管理.生产自动化.邮政系统.交通运输等领域得到了广泛的应用.与此同时,随着网络信息技术的发展,尤其是近几年以智能手机为代表的智能终端设备的兴起,移动互联网获得了蓬勃发展,为 ...

  4. 基于android公交车线路查询论文文献,基于Android手机的实时公交查询系统设计与实现...

    龙源期刊网 http://doc.xuehai.net 基于Android手机的实时公交查询系统设计与实现 作者:郭宏昌 来源:<物联网技术>2015年第11期 摘要:为了提高城市公交的智 ...

  5. Android手机实时视频监控

    最近手机安装了一个"千里眼"和千里眼家居远程监控的应用,对里面的实时监控交通路口的状态有点好奇.以是使用相应的方法反编译看看她的原理. 对于软件"千里眼",经过 ...

  6. C++基于OpenCV实现实时监控和运动检测记录

    基于OpenCV实现实时监控并通过运动检测记录视频 一.课程介绍 1. 课程来源 课程使用的操作系统为 Ubuntu 14.04,OpenCV 版本为OpenCV 2.4.13.1,你可以在这里查看该 ...

  7. 基于Android 移动端的网络视频探索系统【100010403】

    基于移动端的网络视频探索系统 1 引言 1.1 研究背景 智能手机用户在 2015 年占全:人数比例超过百分之十,在 2016 年的时候手机用户超过 20 亿,中国占百分之三十左右.现如今,全:的智能 ...

  8. 安卓设备门禁识别开发_基于android手机的视频通话门禁控制系统

    龙源期刊网 http://www.qikan.com.cn 基于 android 手机的视频通话门禁控制系统 作者:陆海 李登辉 来源:<科教导刊 · 电子版> 2017 年第 34 期 ...

  9. 基于android的检测心率,基于android手机的血氧饱和度检测

    67 基于 android手机的血氧饱和度检测 许方成,赵曙光,杨 峰,黄佳佳 (东华大学信息科学与技术学院,上海 201620) 摘要:血氧饱和度是人体健康状况的标准指标,连续记录血氧饱和度可以预测 ...

最新文章

  1. 使用C/C++发展Web系统开源
  2. iot架构 mqtt netty_Netty实现高性能IOT服务器(Groza)之手撕MQTT协议篇上
  3. Word2007 设置Tab键的默认缩进距离
  4. Leetcode 104. 二叉树的最大深度 解题思路及C++实现
  5. 外网win10 64位环境下 为内网win7 32位安装三方包的最靠谱手段:python64位、32位全安装。...
  6. 复数矩阵QR分解算法的C++实现
  7. 【计算机图形学课程】一.MFC基本绘图函数使用方法
  8. IO系统性能之二:缓存和RAID如何提高IO
  9. 一个长方体玻璃容器从里面量长宽_泰来包装分享:如何设计钢边箱里面中型木包装箱...
  10. 进入实现类快捷键_实测30个自带快捷键,原来键盘也这么好用!
  11. 学C语言好,还是学C++好呢?这两个专业在哪些领域用得最多?
  12. php排序条件两个,php – 在两个条件下排序数组
  13. 实验三 lr分析器的设计与实现_实验室规划设计趋势之一灵活性|无风管通风柜的灵活性是如何实现的?...
  14. 好用的android剪辑软件,最好用的视频剪辑app软件有哪些?自媒体人都在用的六款app软件...
  15. 2022-2027年中国小麦加工行业市场深度分析及投资战略规划报告
  16. win10家庭版调出组策略_正版Win10免费送!支持无限次数重装
  17. 有了域名,怎么搭建自己的网站?
  18. JAVA-仿微信九宫格头像
  19. 昌平北七家空调移机-空调安装电话
  20. 最新仿猪八戒威客系统源码网整站源码下载

热门文章

  1. 西工大java高级网络编程_西工大16春《JAVA高级网络编程》平时作业
  2. 飞控中的IIR二阶滤波器
  3. java graphics 渐变色_使用BufferedImage进行渐变色操作
  4. win10系统C盘突然红了爆满占了170G找了几天怎么也找不到哪个文件占用这么多磁盘空间
  5. 会声会影2022版新版新增蓝光功能
  6. 微信开发者工具配置服务器信息,微信开发者中心如何配置
  7. 程序员怎么从中国直接去美国工作?
  8. 几种常用的差异分析方法简介
  9. 全面替代Microsoft Office、Microsoft visio和WPS的优秀开源文档编辑器LibreOffice
  10. 实战无成本搭建php社工库,简单、高效、几T数据随便查,高效社工库搭建与数据库整理–深夜福利...