Mediastream2 用法介绍及简明实例分析

linphone是一个轻量级voip客户端,linphone的架构设计十分的清晰,其底层音视频引擎mediastream2是一个独立的模块,基于它可以很容易的实现各种音视频的应用。

linphone 整体架构介绍

http://www.linphone.org/eng/documentation/dev/

linphone拥有自己的用户接口和核心引擎(音频/视频引擎),允许在相同的函数基础上建立不同的用户接口。

  • 用户接口

GTK+用户接口

命令行接口(linphonec, linphonecsh)

IPhone用户接口(基于objective C)

基于Java实现的Andorid应用

  • liblinphone,核心引擎:提供了高度容易扩展的函数接口,它是一个功能强大的SIP VoIP video SDK,我们可以基于该框架实现任意的语音/视频应用。

liblinphone基于下列组件实现:

mediastream2,功能强大的音/视多媒体SDK,用于创建和处理音视频流

oRTP,简单的RTP处理库。

eXosip,SIP UA 库,其基于libosip2实现。

 

linphone和liblinphone都是使用C语言实现的,下面为linphone的整体结构。




Mediastream2实现机制

http://www.linphone.org/eng/documentation/dev/mediastreamer2.html

 

mediastream2是一个功能强大的,轻量级流处理引擎,特别适合于音视频电话应用方面的开发。它能够完成音视频流的捕获、接收、发送、编码、解码、渲染等功能。

 

特性:

  1. 可以捕获、重放多种基于各种平台音频架构(ALSA, AudioUnits, AudioQueue, WaveApi)。
  2. 接收、发送RTP数据包。
  3. 支持如下的音视频编解码格式:音频speex, G711, GSM, iLBC, AMR, AMR-WB, G722, SILK, G729; 视频: H263, theora, MPEG4, H264 and VP8.
  4. 支持音频的wav格式文件的读取和保存。
  5. 捕获摄像头的YUV图片格式(基于平台独立的API)。
  6. 优化,渲染YUV图片。
  7. 立体声输出。
  8. 自定义声音侦测。
  9. 回声消除,基于speex库 和Android上的webrtc AEC机制。
  10. 支持音频会议。
  11. 支持音频参数均衡。
  12. 音量控制,自动增益控制。
  13. 具有IEC NAT穿越动能。
  14. 自适应比特率控制算法:根据接收的RTCP反馈信息自动适应编码速率。

mediastream2以扩展插件的形式支持H264, ILBC, SILK, AMR, AMR-WB and G729。

 

设计和原理:

mediastream2中每一个处理实体都包含一个MSFilter结构,每一个MSFiter有一个或者若干个输入和输出,通过这些输入和输出可以将各个MSFilter连接起来。

下面为一个简单的例子:

  1. MSRtpRecv:接收网络上的数据包,解包后将它们输出到下一个MSFilter。
  2. MSSpeexDec:接收输入的音频数据包(假设音频用speex编码),解码并输出到下一个MSFilter。
  3. MSFileRec:接收输入的语音数据并保存为wav格式文件(假设输入为16bit 线性 PCM)。

MSFilter可以被串接成一个filter链,我们接收网络上的RTP包,然后解码并保存成一个wav文件。

MSRtpRecv --> MSSpeexDec --> MSFileRec  
 

媒体处理中的调度对象为MSTicker,它一个独立的线程,其每10ms被唤醒一次,然后它会处理他所管理的媒体链的数据。几个MSTicker可以同时运行,例如,一个负责处理音频,一个负责处理视频,或在不同的处理器中运行不同的MSTicker。

 

以上是Linphone官方网站上的介绍,下面我们实现一个本地录音机实例来具体说明MSFilter到底是如何工作的。



本地录音机的实现

 

1.Filter的分类和定义

从源码目录我们可以看到Filter大概分为以下几种,音频,视频和其他。

 

音频Filter

├── aac-eld.c

├── alaw.c                  ITU-G.711 alaw encoder & decoder

├── ulaw.c                 ITU-G.711 ulaw encoder & decoder

├── l16.c                    L16 dummy encoder & decoder

├── msg722.c            G.722 wideband encoder & decoder

├── msopus.c            opus encoder & decoder

├── msspeex.c           speex encoder & decoder

├── gsm.c                   GSM encoder & decoder

├── oss.c                    Sound playback & playback filter for OSS drivers

├── alsa.c                   Sound playback & playback filter ALSA Driver

├── macsnd.c            Sound playback & playback filter for OSX Audio Unit

├── arts.c                   Sound playback & playback filter aRts Driver

├── pasnd.c               Sound playback & playback filter Port Audio

├── winsnd.c             Sound playback & playback for Windows Sound drivers

├── aqsnd.c               Sound playback & playback for OSX AudioQueueService

├── pulseaudio.c       Sound input & output plugin based on PulseAudio

├── audiomixer.c      A filter that mixes down 16 bit sample audio streams

├── chanadapt.c              A filter that converts from mono to stereo and vice versa

├── dtmfgen.c           DTMF generator

├── equalizer.c          Parametric sound equalizer

├── genericplc.c        Generic PLC

├── msconf.c             A filter to make conferencing

├── msfileplayer.c    Raw files and wav reader

├── msfilerec.c          Wav file recorder

├── msresample.c     Audio resampler

├── msvolume.c        A filter that controls and measure sound volume

├── tonedetector.c    Custom tone detection filter

├── speexec.c           Echo canceller using speex library(回声消除)

├── webrtc_aec.c       Echo canceller using WebRTC library(回声消除)

 

视频Filter

├── h264dec.c                 H264 decoder

├── videodec.c                 H.263 MPEG4 MJEPG snow decoder

├── videoenc.c                 H.263 MPEG4 MJEPG snow encoder

├── theora.c                            theora encoder & decoder

├── vp8.c                          VP8 encoder & decoder

├── drawdib-display.c    A video display based on windows DrawDib api

├── extdisplay.c               A display filter sending the buffers to draw to the                                        upper layer

├── x11video.c          A video display using X11+Xv

├── glxvideo.c           A video display using GL (glx)

├── videoout.c           A SDL-based video display

├── jpegwriter.c        Take a video snapshot as jpg file

├── mire.c                  outputs synthetic moving picture

├── nowebcam.c       A filter that outputs a static image.

├── pixconv.c            A pixel format converter

├── sizeconv.c           a small video size converter

├── wincevideods.c  A video4windows compatible source filter to stream pictures

├── msv4l2.c             A filter to grab pictures from Video4Linux2-powered cameras

├── msv4l.c               A video4linux compatible source filter to stream pictures

├── winvideo2.c        A video for windows (vfw.h) based source filter to grab pictures

├── winvideo.c          A video4windows compatible source filter to stream pictures

├── winvideods.c      A video4windows compatible source filter to stream pictures

 

其他Filter

├── msrtp.c               RTP input & ouput

├── tee.c              Reads from input and copy to its multiple outputs

├── join.c             Send several inputs to one output

├── itc.c               Inter ticker communication

└── void.c                 Trashes its input (useful for terminating some graphs)

 

核心组件

├── eventqueue.c     事件队列

├── mscommon.c      初始化等

├── msfilter.c        Filter定义

├── msqueue.c          队列结构

├── mssndcard.c       声卡处理

├── msticker.c           定时器

├── mswebcam.c      摄像头处理

└── mtu.c                   MTU

 

每个Filter都定义有一个描述信息,所有Filter的描述在ms_base_filter_descs[]ms_voip_filter_descs[]两个数组中定义,下面以Tee Filter为例说明,后面我们会用到。

 

我们可以根据ID或者描述构造一个Filter对象,如:

MSFilter *tee=ms_filter_new(MS_TEE_ID)

 

要回收此对象,如:

ms_filter_destroy(tee);

 

或者调用此对象的某种方法,如:

ms_filter_call_method(tee,MS_TEE_UNMUTE,&pin);

 

方法都是在上面tee_methods数组中定义的,Tee只有两种方法

static MSFilterMethod tee_methods[]={

       {     MS_TEE_MUTE  ,      tee_mute     },

       {     MS_TEE_UNMUTE    ,tee_unmute       },

       {     0     ,      NULL            }

};

 

tee_init 在构造对象时执行一次,tee_uninit在回收时执行一次,tee_process在每次调度时执行。

 

 

2.声卡的管理和使用

声卡的处理在核心组件mssndcard.c中统一管理和使用。

在文件中的开头定义了声卡的全局管理句柄,在库初始化时会把所有可用的声卡挂载到这个链表上。

 

static MSSndCardManager *scm=NULL

struct _MSSndCardManager{

                  MSList *cards;

                  MSList *descs;

};

 

Filter类似,每种声卡也有一个描述信息,所有声卡的描述在ms_snd_card_descs[] 数组中定义,相当一个容器:



ms_init() 函数在初始化库的时候依次注册ms_snd_card_manager_register_desc列表中支持的驱动,执行相应的etect函数侦测声卡,然后构造声卡对象并调用对象的Init函数;

 

当我们需要一个采集或者回放的Filter时,可以直接调用:

MSSndCard *card_capture =ms_snd_card_manager_get_default_capture_card(ms_snd_card_manager_get());

 

ms_snd_card_manager_get() 返回一个全局的声卡管理句柄,

ms_snd_card_manager_get_default_capture_card() 扫描全局的管理句柄中注册的声卡设备,并返回第一个可用的声卡对象。

 

继续调用声卡对象的CreateReader方法,可以得到的声音采集的MSFilte对象。

MSFilter *filte_capture=ms_snd_card_create_reader(card_capture)

 


3.设计Filter

现在我们来设计我们的Filter链,有些文档叫Graph.




总共需要4Filter,采集,复制,保存和回放,Tee Filter在上文已经简单了解过了,他可以把一份数据拷贝到多出。

 

要使用Filter要先进行mediastream2 oRTP的初始化,mediastream2库依赖于oRTP库,先初始化oRTP:

ortp_init();

 

然后初始化mediastream2库:

ms_init();

 

我们先简单看一下,他的初始化都大概做了些什么?

    ms_base_filter_descs[]ms_voip_filter_descs[]数组上面提到过,定义了所有的Filterms_snd_card_descs[]上面也提到过,定义了所有的声卡驱动,此处就是把所有的定义注册到系统中,摄像头的管理和使用方式其实和声卡是类似的,在后面的视频流实例中我们会用到。最后是加载插件,像我们后面要用到的H.264编码器,在程序中是没有的,前面提到过,是以插件的形式提供的,其实就是动态库的形式。所有的东西都注册完毕,我们就可以创建我们要用的Filter了。

 

1.创建Filter

MSSndCard *card_capture= ms_snd_card_manager_get_default_capture_card(ms_snd_card_manager_get());

MSSndCard *card_playback= ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get());

 

MSFilter *capture=ms_snd_card_create_reader(card_capture);

MSFilter *playback=ms_snd_card_create_writer(card_playback);

MSFilter *tee=ms_filter_new(MS_TEE_ID);

MSFilter *rec=ms_filter_new(MS_FILE_REC_ID);

 

2.设置Filter

int rate=48000;

ms_filter_call_method (capture, MS_FILTER_SET_SAMPLE_RATE,&rate);

ms_filter_call_method (playback, MS_FILTER_SET_SAMPLE_RATE,&rate);

ms_filter_call_method (rec,MS_FILTER_SET_SAMPLE_RATE, &rate);

ms_filter_call_method(rec,MS_FILE_REC_OPEN,"test.wav");

ms_filter_call_method_noarg(rec,MS_FILE_REC_START);

 

3.连接Filter

ms_filter_link(capture,0,tee,0);

ms_filter_link(tee,0, playback,0);

ms_filter_link(tee,1,rec,0);

 

4.开始调度

MSTicker *ticker=ms_ticker_new();

ms_ticker_attach(ticker, capture);

 

此后每隔10ms,就会对Filter处理一次。

 

5.停止调度,解除连接并资源回收

ms_filter_call_method_noarg(rec,MS_FILE_REC_CLOSE); //很重要,重写wav文件头

ms_ticker_detach(ticker, capture);

ms_ticker_destroy(ticker);

ms_filter_unlink(capture,0,tee,0);

ms_filter_unlink(tee,0, playback,0);

ms_filter_unlink(tee,1,rec,0);

ms_filter_destroy(capture);

ms_filter_destroy(playback);

ms_filter_destroy(tee);                                                 

ms_filter_destroy(rec);

 

 

到此,一个有本地录音回放的小程序就实现了。下面用一个视频回放并录制h.264裸码流的实例来说明mediastream2中对视频流是如何处理的。


本地录像机的实现

 

1.和本地录音机一样,还是先设计我们的Graph

 



未完待续......

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先接到这一个项目,说是要用mediastreamer2做一个网络电话。之前也是从来没有接触过。于是首先开始在百度中搜索一下需要哪些东西,以及那些步骤。最后大致了解了一下,做这个项目最终要的就是需要移植好多的库,每一个库都需要配置,最后在交叉编译好动态库,然后在执行mediastreamer2的时候去调用这些动态库和头文件就OK了。 1、首先meidastream2是基于ortp库的,那么首先就是下载源码,交叉编译。 交叉编译ortp 下载源码:http://savannah.c3sl.ufpr.br/linphone/ortp/sources/?C=S;O=A 我使用0.18.0版本 ortp-0.18.0.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf ortp-0.18.0.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure CC=arm-linux-gcc --host=arm-linux --target=arm-linux --prefix=/home/protocol_stack/install/ make make install 然后用chmod 777 **.sh 执行脚本./**.sh 这样子就完成了配置,编译,安装。(安装目录为/home/protocol_stack/install/,也就是最后生成的头文件,可执行文件,库文件都会在这个目录下) 2、因为项目是要用到SIP协议的,所以我们还需要移植sip的库 osip2和eXosip2协议,这两个协议对应两个库,osip是简单的osip协议,但是因为API少等一系列原因,增加了eXosip2对osip2的补充。 交叉编译osip2 下载源码:http://ftp.gnu.org/gnu/osip/ 我使用的版本是3.6.0 libosip2-3.6.0.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf libosip2-3.6.0.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure --host=arm-linux --target=arm-linux --prefix=/home/protocol_stack/install/ make make install 然后用chmod 777 **.sh 执行脚本./**.sh 交叉编译eXosip2 下载源码:http://ftp.gnu.org/gnu/osip/ 我使用的版本是3.6.0 libeXosip2-3.6.0.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf libeXosip2-3.6.0.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure --host=arm-linux --target=arm-linux --prefix=/home/protocol_stack/install/ PKG_CONFIG_PATH=/home/protocol_stack/install/lib/pkgconfig make make install 然后用chmod 777 **.sh 执行脚本./**.sh 接下来可以编译mediastreamer2了,不过ms2,依赖好多库:ogg、speex、pulseaudio。而pulseaudio又依赖许多库:alsa、json、libtool。 3、交叉编译ogg 下载源码:http://xiph.org/downloads/ 我使用1.3.1版本 libogg-1.3.3.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf libogg-1.3.3.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure CC=arm-linux-gcc --prefix=/home/protocol_stack/install/ --host=arm-linux make make install 然后用chmod 777 **.sh 执行脚本./**.sh 4、交叉编译speex 下载源码:http://www.speex.org/downloads/ 我使用1.2rc1版本 speex-1.2rc1.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf speex-1.2rc1.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure CC=arm-linux-gcc --prefix=/home/protocol_stack/install/ --with-ogg=/home/protocol_stack/install/ --enable-fixed-point --disable-float-api \ --host=arm-linux make make install 然后用chmod 777 **.sh 执行脚本./**.sh 5、交叉编译pulseaudio 下载源码:http://freedesktop.org/software/pulseaudio/releases/ 我使用1.0版本 pulseaudio-1.0.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf pulseaudio-1.0.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure CC=arm-linux-gcc CXX=arm-linux-g++ --prefix=/home/protocol_stack/install --host=arm-linux --disable-rpath --disable-nls --disable-dbus --disable-bluez --disable-samplerate --disable-solaris --disable-gconf --disable-avahi --disable-jack --disable-lirc --disable-glib2 --disable-gtk2 --disable-openssl --disable-ipv6 --disable-asyncns --disable-per-user-esound-socket --disable-oss-output --disable-oss-wrapper --disable-x11 --enable-neon-opt=no --with-database=simple PKG_CONFIG_PATH=/home/protocol_stack/install/lib/pkgconfig CPPFLAGS=-I/home/protocol_stack/install/include LDFLAGS=-L/home/protocol_stack/install/lib CFLAGS=-I/home/protocol_stack/install/include make make install 然后用chmod 777 **.sh 执行脚本./**.sh 错误1: checking for ltdl.h... no configure: error: Unable to find libltdl version 2. Makes sure you have libtool 2.4 or later installed. make: *** No targets specified and no makefile found. Stop. 分析;找不到libltdl。确保你有libtool 2.4及以上的版本。 下载libtool 2.4.2版本 这时需要交叉编译libtool 下载源码:ftp://ftp.gnu.org/gnu/libtool/ 我使用2.4.2版本 libtool-2.4.2.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf libtool-2.4.2.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure --host=arm-linux --prefix =/home/protocol_stack/install/ make make install 然后用chmod 777 **.sh 执行脚本./**.sh 交叉编译alsa: http://www.alsa-project.org/main/index.php/Main_Page 这个库的版本需要根据你嵌入式Linux内核中alsa的版本而定,可以使用命令查看内核中alsa的版本: # cat /proc/asound/version Advanced Linux Sound Architecture Driver Version 1.0.24. 可以到内核中alsa驱动版本是1.0.24,所以我选1.0.24版本 alsa-lib-1.0.24.1.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf speex-1.2rc1.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure --host=arm-linux --prefix =/home/protocol_stack/install/ make make install 然后用chmod 777 **.sh 执行脚本./**.sh 错误:configure: error: Package requirements ( sndfile >= 1.0.20 ) were not met: No package 'sndfile' found 分析:缺少库 libsndfile库,那么接下来再进行交叉编译libsndfile libsndfile-1.0.25.tar.gz http://www.linuxfromscratch.org/blfs/view/svn/multimedia/libsndfile.html 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf libsndfile-1.0.25.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure --host=arm-linux --prefix =/home/protocol_stack/install/ make make install 然后用chmod 777 **.sh 执行脚本./**.sh 7、最后编译mediastreamer2 下载源码:http://ftp.twaren.net/Unix/NonGNU//linphone/mediastreamer/ 我使用2.8版本 mediastreamer-2.8.0.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf mediastreamer-2.8.0.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 把下边这三行写成一个脚本 vim **.sh ./configure CC=arm-linux-gcc --prefix=/home/protocol_stack/install/ PKG_CONFIG_PATH=/home/protocol_stack/install/lib/pkgconfig --disable-gsm --enable-video=no --enable-macsnd=no --disable-static --disable-sdl --disable-x11 --disable-ffmpeg --host=arm-linux --target=arm-linux make make install 然后用chmod 777 **.sh 执行脚本./**.sh 上面的configure选项没有屏蔽v4l1和v4l2,所以还得交叉编译v4l 编译v4l libv4l-0.6.4.tar.gz 下载源码:http://pkgs.fedoraproject.org/repo/pkgs/libv4l/ 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf libv4l-0.6.4.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 我使用0.6.4版本 libv4l-0.6.4.tar.gz make clean make CC=arm-linux-gcc make install PREFIX=/home/protocol_stack/install 编译mediastreamer2出错:(1)checking for LIBCHECK... no checking for LIBJSON... no configure: error: Package requirements ( json >= 0.9 ) were not met: No package 'json' found 解决方法就是交叉编译json 下载源码:http://ftp.debian.org/debian/pool/main/j/json-c/ 分析:缺少json库,那么我们继续交叉编译json库 json-c_0.12.1.orig.tar.gz 然后通过winshare(Windows和Linux的通信)把下载好的库文件拷贝到Linux下, 然后解压 tar zxvf mediastreamer-2.8.0.tar.gz 注意这个时候可能会发生错误,是没有权限的问题,那么就在命令行前边加上sudo 然后配置 ./configure --host=linux-arm \ --prefix =/home/protocol_stack/install/ make && make install 好了,json库已经编译完成了。接下来我们继续编译mediastreamer2 。。。。。 但是还是有问题,怎么办呢?还是哪个问题还是找不到json库。 分析:在json的论坛中,找到了解决方案:把编译生成的/lib/pkgconfig/这个目录下生成了一个json-c.pc。最后mediastreamer2在调用的时候找的是json.pc。那么我们就把这个文件名改为json.pc #mv json-c.pc json.pc OK,这次这个是可以编译的过去了。接下来继续编译 。。。 又出现问题了 /home/protocol_stack/install/lib/libjson.so: undefined reference to `rpl_malloc' /home/protocol_stack/install/lib/libjson.so: undefined reference to `rpl_realloc' 问题分析: 这个错误的原因是因为没有定义 rpl_malloc 和 rpl_realloc 这两个变量。 那么我们应该怎么办么? 那么就在这个目录下进行查这两个变量是在哪里定义的? 于是:#grep "rpl_malloc" -nR * ....... 找到了,原来这两个变量是在这个config的文件中的。是一个宏开关 那么就好办了,我们就直接把这两个宏进行注释。 嗯嗯,继续。。。我们重新编译json库。。。嗯嗯编译好了,接下来继续来编译mediastreamer2 。。。。 又出错了,还是这个原因 /home/protocol_stack/install/lib/libjson.so: undefined reference to `rpl_malloc' /home/protocol_stack/install/lib/libjson.so: undefined reference to `rpl_realloc 嗯嗯,还是这个原因?究竟是为什么呢。再次来到json的目录下,再次看有没有把那两个宏开关给关闭? 嗯哼? 竟然没有关闭? 分析?明白了。原来是我把配置和编译同时执行了。这个宏开关是./configure ...生成的。 那么就只好,这样。把./configure。。。生成的config文件,再进行关闭宏开关。最后直接make && make install -j8 直接编译,安装,是不能再次进行配置的。因为以配置config文件就会再次生成,那么宏开关就又开了。 OK,安装好了,下来继续进行编译mediastreamer2.。。。。。。。。。。。 。。。。。。。。。。。。。。 又出现了问题? error: /user/include/python2.7/pyconfig.h:15:52: fatal error: arm-linux-gnueabi/python2.7/pyconfig.h: No such file or directory compilation terminated. 分析::找不到arm-linux-gnueabi/python2.7/pyconfig.h这文件。那就继续交叉编译python 好吧,继续下载python,然后再进行交叉编译,但是编译Python的时候出来一系列的问题。根本没有办法解决。 那么该怎么办呢?时候一个小时又一个小时的过去? 最后有一个大胆的想法,既然python都编译不下去。那就不要了。 于是,在mediastreamer2的./configure 中添上一项 --without-python 。 。。。再次配置编译。。。。。。。。。。。 error: /user/include/python2.7/pyconfig.h:15:52: fatal error: arm-linux-gnueabi/python2.7/pyconfig.h: No such file or directory compilation termiated. 嗯哼?还是一样的错误。怎么办呢? 于是乎就又在论坛上进行找灵感。。。。。 还是找不到。。。 又一结合前边几个库的配置编译,发现不使能一个模块还可以用另外一个--disable-python 。。。 于是乎 就把--without-python改为了--disable-python 继续编译。。。。 。。。。。。。。。。。。。。。。。。。。。 到了这个节骨眼上了,编译每跳一下,我的心就跟着逗一下。。。。心酸 。。。。。。 。。。。。。 。。。。。。 竟然编译成功了。。。。 哈哈。。。。。。。。。 于是,马上就把编译好的库,拷贝到了开发板。。。 嗯嗯,本来还想把编译好的库目录树拷贝下的,但是太多了,放不下。。。算了吧。。。。 找到编译好的库 在库中的/bin中找到arm-linux-mediastream 然后执行./arm-linux-mediastream 。。。。报错了 问题: error : while loading shared libraries: libmediastreamer.so.1: cannot open shared object file: No such file 答案:分析: 遇到这个问题就是,libmediastreamer.so.1这个动态库,在可执行文件armlinuxmediastreamer执行的时候,会调用这个动态库,但是环境变量中找不到这个动态库。那么我们就是要把我们编译好的动态链接库的目录加到环境变量中 LD_LIBRARY_PATH=$LD_LIBRARY_PATH://arm/lib/这个目录下就是放着我们编译好的所有的动态链接库(包括libmediastreamer.so.1) 执行步骤:LD_LIBRARY_PATH=$LD_LIBRARY_PATH://arm/lib export LD_LIBRARY_PATH ./arm-linux-mediastream mediastream --local --remote --payload [ --fmtp ] [ --jitter ] [ --width ] [ --height ] [ --bitrate ] [ --ec (enable echo canceller) ] [ --ec-tail ] [ --ec-delay ] [ --ec-framesize ] [ --agc (enable automatic gain control) ] [ --ng (enable noise gate)] [ --ng-threshold (noise gate threshold) ] [ --ng-floorgain (gain applied to the signal when its energy is below the threshold.) ] [ --capture-card ] [ --playback-card ] [ --infile <input wav file> specify a wav file to be used for input, instead of soundcard ] [ --outfile specify a wav file to write audio into, instead of soundcard ] [ --camera ] [ --el (enable echo limiter) ] [ --el-speed (gain changes are smoothed with a coefficent) ] [ --el-thres (Threshold above which the system becomes active) ] [ --el-force (The proportional coefficient controlling the mic attenuation) ] [ --el-sustain (Time in milliseconds for which the attenuation is kept unchanged after) ] [ --el-transmit-thres (TO BE DOCUMENTED) ] [ --rc (enable adaptive rate control) ] [ --zrtp (enable zrtp) ] [ --verbose (most verbose messages) ] [ --video-windows-id <video surface:preview surface>] [ --srtp (enable srtp, master key is generated if absent from comand line) [ --netsim-bandwidth (simulates a network download bandwidth limit) 于是按照第一种方式进行 参数添加 ./arm-linux-mediastream --local 8888 --remote 127.0.0.1:88 88 OK运行正常了 下面是运行信息。。。 ortp-message-audio_stream_process_rtcp: interarrival jitter=119 , lost packets percentage since last report=0.000000, round trip time=0.000000 seconds ortp-message-oRTP-stats: RTP stats : ortp-message- number of rtp packet sent=150 ortp-message- number of rtp bytes sent=25800 bytes ortp-message- number of rtp packet received=150 ortp-message- number of rtp bytes received=25800 bytes ortp-message- number of incoming rtp bytes successfully delivered to the application=25284 ortp-message- number of rtp packet lost=0 ortp-message- number of rtp packets received too late=0 ortp-message- number of bad formatted rtp packets=0 ortp-message- number of packet discarded because of queue overflow=0 ortp-message-Bandwidth usage: download=81.290281 kbits/sec, upload=81.288664 kbits/sec ortp-message-Receiving RTCP SR ortp-message-Receiving RTCP SDES ortp-message-Found CNAME=unknown@unknown ortp-message-Found TOOL=oRTP-0.18.0 ortp-message-Found NOTE=This is free sofware (LGPL) ! ortp-message-Quality indicator : 4.888437 运行正常了。。。。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值