mediastreamer使用教程

1.各个函数功能简介

ms_filter_destroy 释放filter资源

ms_ticker_destroy释放ticker

说明:ticker为定时器线程,每隔10ms执行一次

ms_filter_new创建filter,传进参数为filter的ID

ms_connection_helper_start拿到filter链接起始位置

ms_connection_helper_link链接filter

ms_filter_link链接filter

ms_ticker_new创建ticker

ticker说明:

ticker是属于一个线程不能够运行两个阻塞式的过程,比如socks的发送与接收,必须将

发送和接收放在filter线程里面。

ms_ticker_set_name设置ticker名称

ms_ticker_attach将ticker附加到线程中

ms_ticker_detach去掉ticker

ms_connection_helper_unlink去掉filter链接

ms_filter_unlink 去掉filter链接

ms_new filter数据结构创建

ms_free 数据结构数据释放

ms_queue_get(f->inpputs[0])获取filter数据

msgdsize获取filter里面数据长度

ms_queue_put(f->outputs[0],om)往filter里面塞数据

freemsg释放filter数据

ms_thread_join在filter里面创建线程

ms_filter_call_method往filter里面发送数据

2.创建filter过程

2.1在Allfilters.h里面添加filter的ID

2.2在Alldescs.h里面添加filter结构体变量

2.3在实现filter的源文件里面添加相关头文件

#include "msfilter.h"
#include "msticker.h"

2.4.一个标准的filter过程

#include "msfilter.h"
#include "msticker.h" static void enc_init(MSFilter *f){ } static void enc_uninit(MSFilter *f){ } static void enc_preprocess(MSFilter *f)
{
} static void enc_process(MSFilter *f){ } static void enc_postprocess(MSFilter *f){
} static MSFilterMethod enc_methods[]={
{0,NULL}
}; MSFilterDesc ms_amr_enc_desc={
MS_AMR_ENCODER_ID, //filter ID
"amrEnc", //filter名称
"amr encoder",
MS_FILTER_ENCODER, //filter类型MS_FILTER_OTHER 其他,
//MS_FILTER_ENCODER 编码器,
//MS_FILTER_DECODER 解码器
"amr",
1,
1,
enc_init, //初始化操作
enc_preprocess, //预初始化操作
enc_process, //处理过程
enc_postprocess, //预结束操作
enc_uninit, //结束操作
enc_methods //程序模块方法,用于参数传递
}; static void dec_init(MSFilter *f){ } static void dec_uninit(MSFilter *f){ } static void dec_preprocess(MSFilter *f){
} static void dec_postprocess(MSFilter *f){
} static void dec_process(MSFilter *f){ } static MSFilterMethod dec_methods[]={
{0,NULL}
}; MSFilterDesc ms_amr_dec_desc={
MS_AMR_DECODER_ID,
"amrDec",
"amr decoder",
MS_FILTER_DECODER,
"amr",
1,
1,
dec_init,
dec_preprocess,
dec_process,
dec_postprocess,
dec_uninit,
dec_methods
}; MS_FILTER_DESC_EXPORT(ms_amr_dec_desc)
MS_FILTER_DESC_EXPORT(ms_amr_enc_desc)

3.替换编码器

将原来silk编码器换为amr编码器

3.1创建amr的filter

stream->decoder=ms_filter_new(MS_AMR_DECODER_ID);

3.2链接编码filter

ms_filter_link(stream->tcpRecv,0,stream->decoder,0);

4.filter创建注意事项

4.1 filter里面数据流要对应

MSFilterDesc ms_amr_dec_desc={
MS_AMR_DECODER_ID,
"amrDec",
"amr decoder",
MS_FILTER_DECODER,
"amr",
1, //进
1, //出
dec_init,
dec_preprocess,
dec_process,
dec_postprocess,
dec_uninit,
dec_methods
};

以上是编码器filter,是一进一出,原始数据进去出来编码后的数据。

MSFilterDesc ms_tcpclient_send_desc={
MS_TCP_SEND_ID,
"TcpClientSend",
"TcpClient_Send",
MS_FILTER_OTHER,
"tcpclient",
1, //进
0, //出
tcp_send_init,
tcp_send_preprocess,
tcp_send_process,
tcp_send_postprocess,
tcp_send_uninit,
tcpclient_send_methods
};

以上是TCP数据发送filter,只有进没有出,数据进来之后都发送数据都发送出去了

4.2 filter里面new的结构体数据要记得free

5.例子:一个音频流启动过程

#include "mediastreamer/audiostream.h"
#include "rtpsession.h"
#include "mediastreamer/msrtp.h"
#include "mediastreamer/mssndcard.h"
#include "mediastreamer/msvolume.h"
#include"mediastreamer/TcpClientFilter.h"
#include <signal.h>
#include <stdio.h> static ms_mutex_t stream_mutex; //初始化结构体数据
AudioStream* audio_stream_new() {
AudioStream *stream = (AudioStream *)ms_new0 (AudioStream, 1);
return stream;
}
//释放音频流
void audio_stream_free(AudioStream *stream) { if(stream->source!=NULL)
ms_filter_destroy(stream->source);
if(stream->encoder!=NULL)
ms_filter_destroy(stream->encoder); if(stream->tcpSend!=NULL)
ms_filter_destroy(stream->tcpSend);
if(stream->tcpRecv!=NULL)
ms_filter_destroy(stream->tcpRecv);
if(stream->dest!=NULL)
ms_filter_destroy(stream->dest); if(stream->ticker!=NULL)
{
printf("ms_ticker_destroy begin r 41\n");
ms_ticker_destroy(stream->ticker);
printf("ms_ticker_destroy end r43 audiostream.c \n");
} ms_free(stream);
ms_mutex_destroy(&stream_mutex);
printf("ms_free(stream) end \n");
} #define payload_type_set_number2(pt,n) (pt)->user_data=(void*)((long)n);
static void dp_set_payload_type(PayloadType *const_pt, int number, const char *recv_fmtp)
{
payload_type_set_number2(const_pt, number); rtp_profile_set_payload(&av_profile,number,const_pt);
}
//启动音频流
int audio_stream_start(AudioStream *stream,char* SeverIp, int SeverPort, char (*localSessionID)[4], char (*remoteSessioID)[4]){ ms_mutex_init(&stream_mutex,NULL);
ms_mutex_lock(&stream_mutex);
if(stream==NULL)
{
ms_mutex_unlock(&stream_mutex);
return -1;
} stream->decoder=ms_filter_new(MS_AMR_DECODER_ID);
if(stream->decoder==NULL){
return -1;
} stream->encoder=ms_filter_new(MS_AMR_ENCODER_ID);
if(stream->encoder==NULL){
return -2;
} stream->tcpSend=ms_filter_new(MS_TCP_SEND_ID);
if(stream->tcpSend==NULL){
ms_mutex_unlock(&stream_mutex);
return -9;
} ms_filter_call_method(stream->tcpSend,MS_TCP_SEND_SET_LOCAL_FRAG,localSessionID[0]);
ms_filter_call_method(stream->tcpSend,MS_TCP_SEND_SET_REMOTE_FRAG,remoteSessioID[0]);
if(ms_filter_call_method(stream->tcpSend,MS_TCP_SEND_LOGIN,0)!=0){
printf("audiostream.c::audio_stream_start_call - TcpSendFilter fail to login\n");
ms_mutex_unlock(&stream_mutex);
return -19;
} stream->tcpRecv=ms_filter_new(MS_TCP_READ_ID);
if(stream->tcpRecv==NULL){
ms_mutex_unlock(&stream_mutex);
return -10;
}
printf("audiostream.c::audio_stream_start_call - local:%02x%02x%02x%02x remote:%02x%02x%02x%02x",localSessionID[1][0]&0xff,localSessionID[1][1]&0xff,localSessionID[1][2]&0xff,localSessionID[1][3]&0xff,
remoteSessioID[1][0]&0xff,remoteSessioID[1][1]&0xff,remoteSessioID[1][2]&0xff,remoteSessioID[1][3]&0xff);
ms_filter_call_method(stream->tcpRecv,MS_TCP_READ_SET_LOCAL_FRAG,localSessionID[1]);
ms_filter_call_method(stream->tcpRecv,MS_TCP_READ_SET_REMOTE_FRAG,remoteSessioID[1]);
if(ms_filter_call_method(stream->tcpRecv,MS_TCP_READ_LOGIN,0)!=0){
printf("audiostream.c::audiio_stream_start_call - TcpReadFilter fail to login\n");
ms_mutex_unlock(&stream_mutex);
return -20;
} stream->source=ms_filter_new(MS_LINUX_SOUND_READ_ID);
if(stream->source==NULL){
ms_mutex_unlock(&stream_mutex);
return -2;
} stream->dest=ms_filter_new(MS_LINUX_SOUND_WRITE_ID);
if(stream->dest==NULL){
ms_mutex_unlock(&stream_mutex);
return -8;
} ms_filter_link(stream->tcpRecv,0,stream->decoder,0);
ms_filter_link(stream->decoder,0,stream->dest, 0);
ms_filter_link(stream->source,0,stream->encoder,0);
ms_filter_link(stream->encoder,0,stream->tcpSend,0); stream->ticker = ms_ticker_new();
if(stream->ticker==NULL){
ms_mutex_unlock(&stream_mutex);
return -6;
} ms_ticker_set_name(stream->ticker,"Audio MSTicker"); ms_ticker_attach(stream->ticker, stream->source); ms_ticker_attach(stream->ticker, stream->tcpRecv); ms_mutex_unlock(&stream_mutex);
return 0;
}
//关闭音频流
void audio_stream_stop(AudioStream *stream) {
/* detach */ ms_mutex_lock(&stream_mutex); int i=0; if(stream->ticker != NULL && stream->source!=NULL)
ms_ticker_detach(stream->ticker, stream->source); if(stream->ticker != NULL && stream->tcpRecv!=NULL)
ms_ticker_detach(stream->ticker,stream->tcpRecv); if(stream->tcpRecv!=NULL && stream->decoder!=NULL)
ms_filter_unlink(stream->tcpRecv, 0, stream->decoder, 0); if(stream->decoder!=NULL && stream->dest!=NULL)
ms_filter_unlink(stream->decoder, 0, stream->dest, 0); if(stream->source!=NULL && stream->encoder!=NULL)
ms_filter_unlink(stream->source, 0, stream->encoder, 0); if(stream->encoder!=NULL && stream->tcpSend!=NULL)
{
printf("ms_filter_unlink(stream->encoder, 0, stream->tcpSend, 0) \n\n");
ms_filter_unlink(stream->encoder, 0, stream->tcpSend, 0);
} /* destroy filter */
ms_mutex_unlock(&stream_mutex);
audio_stream_free(stream);
printf("audio_stream_stop 10\n");
}

mediastreamer使用教程的更多相关文章

  1. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  2. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  3. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  4. Angular2入门系列教程4-服务

    上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...

  5. Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境

    一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...

  6. wepack+sass+vue 入门教程(三)

    十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...

  7. wepack+sass+vue 入门教程(二)

    六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...

  8. wepack+sass+vue 入门教程(一)

    一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...

  9. Virtual Box配置CentOS7网络(图文教程)

    之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...

随机推荐

  1. HTML错误码

    1XX 信息性状态码 2XX 成功状态码 3XX 重定向状态码 4XX 客户端错误状态码 5XX 服务器错误状态码

  2. vijos P1915 解方程 加强版

    背景 B酱为NOIP 2014出了一道有趣的题目, 可是在NOIP现场, B酱发现数据规模给错了, 他很伤心, 哭得很可怜..... 为了安慰可怜的B酱, vijos刻意挂出来了真实的题目! 描述 已 ...

  3. CRC校验码原理、实例、手动计算

    目录一.CRC16实现代码二.CRC32编码字符表三.CRC校验码的手动计算示例四.CRC校验原理五.CRC的生成多项式参考 一.CRC16实现代码 思路:取一个字符(8bit),逐位检查该字符,如果 ...

  4. .NET定时任务执行管理器开源组件–FluentScheduler

    在日常项目里通常会遇到定时执行任务的需求,也就是定时器..NET Framework里关于定时器的类有3个,分别是System.Windows.Forms.Timer.System.Timers.Ti ...

  5. php $CI =& get_instance();

    初学php 看有人这样写,$CI =& get_instance(); 要你自定义的类库中访问CodeIgniter的原始资源,你必须使用 get_instance() 函数.这个函数返回一个 ...

  6. win7 cmd 操作mysql数据库

    一 ,对MySql服务器的开启,重启,关闭等操作       当然,可以在win7的界面环境下,关闭或开启MySql服务.但是经常找不到win7的服务管理器,主要定位方法有二:命令行下输入servic ...

  7. 开源任务管理平台TaskManagerV2.0介绍及升级说明

    上一篇开源任务管理平台TaskManager介绍发布后,有网友联系我看看能不能做个后台管理界面,方便管理系统中所有的任务.由于时间和技术问题1.0版本的时候,新增了一个3分钟读取配置文件动态修改任务的 ...

  8. 多说评论系统API调用和本地身份说明(JWT)

    多说评论系统是一个非常好用的第三方评论插件,聚合了大多数的SNS平台账号登录和分享功能,UI也很不错. 作为网站快速接入评论系统,多说是一个比较好的选择,其也提供了一些实用的API去满足定制化需求. ...

  9. 使用canvas绘制一片星空

    效果图 五角星计算方式 代码 <body style="margin:0px;padding:0px;width:100%;height:100%;overflow:hidden;&q ...

  10. Windows 新装进阶操作指南

    Windows禁用CTRL+Space切换输入法 注册表打开HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\00000010 把Key Mo ...