mediastreamer使用教程
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使用教程的更多相关文章
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境
一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- Virtual Box配置CentOS7网络(图文教程)
之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...
随机推荐
- Openjudge 1.13.37:乒乓球
总时间限制: 1000ms 内存限制: 65536kB 描述 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及.其中11分制改革引起了很大的争议,有一部分球员 ...
- bench.sh 跑分测速
#!/bin/bash #==============================================================# # Description: bench te ...
- Qt——自定义属性
一.Qt中的属性 属性是指窗口或控件的属性,比如opacity属性表示“透明度”,geometry指的是“位置和大小”,pos属性代表“位置”. qt中的控件有自带的属性,我们也可以自己定义属性. Q ...
- ajax返回值中有回车换行、空格的解决方法分享
最近在写一个页面,用jquery ajax来实现判断,刚写好测试完全没有问题,过了两天发现出现问题,判断不成了.后来发现所有alert出来的返回值前面都会加若干换行和空格.(至今不明白,同一台电脑,同 ...
- AppBox升级进行时 - Attach陷阱(Entity Framework)
AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. Attach方法 前面我们已经多次使用Attach方法,上一次使用Attach ...
- 【三石jQuery视频教程】03.创建垂直时间表(Timeline)
视频地址:http://v.qq.com/page/g/i/o/g0150rvi6io.html 大家好,欢迎来到[三石jQuery视频教程],我是您的老朋友 - 三生石上. 今天,我们要通过基本的H ...
- JS组件系列——Bootstrap Table 表格行拖拽
前言:之前一直在研究DDD相关知识,好久没更新JS系列文章了.这两天做了一个简单的业务需求,觉得效果还可以,今天在这里分享给大家,欢迎拍砖~~ 一.业务需求及实现效果 项目涉及到订单模块,那天突然接到 ...
- 《JavaScript高级程序设计》 - 读书笔记 - 第5章 引用类型
5.1 Object 类型 对象是引用类型的实例.引用类型是一种数据结构,用于将数据和功能组织在一起. 新对象是使用new操作符后跟一个构造函数来创建的.构造函数本身就是一个函数,只不过该函数是出于创 ...
- C 语言学习的第 05 课:C 语言基础(01)
C语言程序中的绝大部分应该记录在以.c作为扩展名的文件里,这种文件叫做C语言 程序的源文件. C语言中还包括以.h作为扩展名的文件,这种文件叫做头文件. C语言中的四则运算: 加:+ 减:- 乘 ...
- maven 打包
使用命令行形式打包 1.配置maven环境变量,在变量path中加入maven路径. 2.在要打包的项目目录下使用:Ctrl+shift+鼠标右键点击,点击 在此处打开命令行窗口. 在打开的命令行窗口 ...