• Linphone3.5.2 ARM RV1109音视频对讲开发记录


    Linphone3.5.2 ARM RV1109音视频对讲开发记录

    说明

    这是一份事后记录,主要记录的几个核心关键点,有可能很多细节没有记上,主要是方便后面自己再找回来!

    版本 3.5.2

    一些原因选的是这样一个旧的版本!
    新的开发最好选新一些的版本吧, 像 4.5, 4.2, 3.8 这一类的!

    因为之前没有开发过Linphone的应用,所以对整个框架不了解,一头雾水! 上网找了比较多的资料!

    因为只是事后记录,下面记录一下核心的操作,为后面其他需要对接的开发人员指示一下操作的路线吧!

    前前后后,自己花了接近两周的时间,对这个框架大体了解了!
    所以认为下面的实现是比较合适的方案了!最小的改动了Linphone框架代码,把音视频的实现都是放在APP应用中了。
    在处理音频的3A算法,视频编解码都与Linphone无关,也不需要Linphone在编译时来链接应用平台对接的库。

    整体应用概述

    我的主板是RV1109,人脸平板产品,做为社区的门口、门栋机!需要呼叫室内分机或物业电话机!

    在Linphone中有实现音视频的标准的处理,但往往在嵌入式平台上处理音视频上又是不标准的!各个厂家的方式
    又不标准,比如很多嵌入式平台上默认上就不支持ALSA,视频也没有走V4L2的框架,编解码都有自己的SDK实现
    这时就需要自己实现Linphone低层的一些音视频处理设备!

    如在这个平台上即是自己实现的音视频处理逻辑!

    定义msfilterID

    在枚举类中:typedef enum MSFilterId,定义我们自己的音频及视频ID

    typedef enum MSFilterId
    	...
    	...
    	MS_H264Stream_CUS_ID,
    	MS_H264_ENC_CUS_ID,
    	MS_H264_DEC_CUS_ID,
    } MSFilterId;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编写对应的音视频设备

    针对上面定义的 MS_H264Stream_CUS_ID , MS_H264_ENC_CUS_ID, MS_H264_DEC_CUS_ID 这几个filter,我们需要对应的加以实现!

    用户自定义的filter,mediastreamer2里提供了相应的注册函数,这一部分代码不需要写到linphone里去,所以我们写在我们自己的应用APP中即可!

    对针音频的:

    音频设备上linphone里本身也有ALSA的实现,但我们自己使用了ALSA的混音配置,有一些差异,同时对音频数据在发送前需要做3A处理,消回声,去噪这些,
    如果把这部分代码写到linphone中去就比较麻烦.为了方便,还是自己在应用中实现对音频的处理,同时很多ARM嵌入式主板,可能并没有提供ALSA接口的适配,
    所以很多时候,还是自己实现一个MSSndCardDesc简单.

    具体声明如下,各个方法的实现,只要看看mediastreamer2中的ALSA实现,简单对照实现即可!

    	MSSndCardDesc alsa_card_desc={
    		.driver_type="ALSA",
    		.detect=alsa_card_detect,
    		.init=alsa_card_init,
    		.set_level=alsa_card_set_level,
    		.get_level=alsa_card_get_level,
    		.set_capture=alsa_card_set_source,
    		.set_control=NULL,
    		.get_control=NULL,
    		.create_reader=alsa_card_create_reader,
    		.create_writer=alsa_card_create_writer,
    		.uninit=alsa_card_uninit,
    		.duplicate=alsa_card_duplicate,
    		.unload = NULL
    	};
    
    	bool Linphone_AlsaMSFilter::linphone_Alsa_init()
    	{
    
    		static MSSndCardManager *cm = NULL;
    
    		if(cm)
    		{
    			return true;
    		}
    
    		cm = ms_snd_card_manager_get();
    		ms_snd_card_manager_register_desc(cm, &alsa_card_desc);
    
    		return true;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    对针视频的:

    因为视频是通过硬件的处理的,像RV1109,海思等方案都是调用硬编解码,所以不管是接收到视频流,还是发送视频流,
    linphone只要负责收到或发送H264这样的流,并不负责编解码
    所以这里需要把mediaStreamer2中的编解码及视频设备源处理一下。分别实现自己的编解码器及视频源设备!
    具体的实现,就在各个方案上不同的! 基本定义如下!

    	//定议两个并不需要的编解码器,这是应为我没有编译FFMPEG进来!
    	MSFilterDesc ms_h264_enc_desc={
    		.id=MS_H264_ENC_CUS_ID,
    		.name="MSh264EncCus",
    		.text=("A video H264 encoder using ffmpeg library."),
    		.category=MS_FILTER_ENCODER,
    		.enc_fmt="H264",
    		.ninputs=0, /*MS_YUV420P is assumed on this input */
    		.noutputs=0,
    		.init=enc_h264_init,
    		.preprocess=enc_preprocess,
    		.process=enc_process,
    		.postprocess=enc_postprocess,
    		.uninit=enc_uninit,
    		.methods=methods,
    		.flags = 0,
    	};
    	
    	MSFilterDesc ms_h264_dec_cus_desc={
    		.id=MS_H264_DEC_CUS_ID,
    		.name="MSH264DecCus",
    		.text="A H264 decoder based on ffmpeg project.",
    		.category=MS_FILTER_DECODER,
    		.enc_fmt="H264",
    		.ninputs=1,
    		.noutputs=1,
    		.init=dec_init,
    		.preprocess=NULL,
    		.process=dec_process,
    		.postprocess=NULL,
    		.uninit=dec_uninit,
    		.methods=h264_dec_methods,
    		.flags=0
    	};
    
    	
    	//在一个合适的地方注册filter
    	ms_filter_register(&ms_h264_dec_cus_desc);
    	
    	ms_filter_register(&ms_h264_enc_desc);
    	
    	
    	//定义真正传输H264视频的Filter
    	MSFilterDesc ms_h264Stream_desc={
    		.id=MS_H264Stream_CUS_ID,
    		.name="MSH264StreamReadCus",
    		.text="Ms H264 Stream read source Cus",
    		.category=MS_FILTER_OTHER,
    		.enc_fmt = NULL,
    		.ninputs=0,
    		.noutputs=1,
    		.init=h264Stream_read_init,
    		.preprocess=h264Stream_read_preprocess,
    		.process=h264Stream_read_process,
    		.postprocess=h264Stream_read_postprocess,
    		.uninit=h264Stream_read_uninit,
    		.methods=h264Stream_read_methods,
    		.flags=0
    	};
    	
    	//初始化注册filter
    	bool Linphone_h264msfilter::Linphone_h264msfilter_init()
    	{
    		 static MSWebCamManager* pMSWebCamManager= ms_web_cam_manager_get();
    
    		 if(!pMSWebCamManager)
    		 {
    			 return true;
    		 }
    
    		 ms_web_cam_manager_register_desc(pMSWebCamManager, &ms_h264Stream_card_desc);
    
    		return true;
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    几个关健点的修改

    视频处理的一个基本流:

    linphone_core_update_streams->linphone_call_start_media_streams->linphone_call_start_video_stream->video_stream_start

    linphone_call_start_video_stream 这个过程中有对视频源对像的更新(vstream)

    创建VIDEO对应的filter及前后关系设置

    videostream.c:video_stream_start
    ms_filter_link

    设备的的摄像头数据是已经经过编码成H264的数据了修改 video_stream_start 中的ms_filter_link配置从数据源直接指向RTP

    	if(stream->source->desc->id == MS_H264Stream_CUS_ID)
    	{
    		ms_filter_link (stream->source, 0, stream->rtpsend, 0);			
    	}
    	else
    	{
    		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->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);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这个文件中有好几处都需要对应的修改 ms_filter_link 关系,这里不一一列出了,都是在这个文件里了!

    几个同音视频相关配置接口

    同音视频相关的的几个接口,需要注意一下,因为在设置这几个参数后,会影响到音视频设备的开启关闭!

    linphone_core_enable_video

    视频接口配置,配置是否有摄像头及是否显示视频,通过这个配置后会设置video_conf的capture和display标识

    linphone_call_enable_camera

    设置是否开启摄像头

    linphone_call_params_enable_early_media_sending

    设置接听前是否有音视频发送

  • 相关阅读:
    React Router 路由守卫
    CentOS 7 安装新版本的Nginx
    Python中的装饰器
    【机器学习】Tensorflow.js:我在浏览器中使用机器学习实现了图像分类
    LVS负载均衡
    ResponseEntity下载包含点的文件名无法下载
    Tomcat 线程模型&性能调优
    【MySQL】存储过程与存储函数
    内网渗透(八十五)之ADCS证书服务攻击
    VINS中的观测性问题
  • 原文地址:https://blog.csdn.net/jhting/article/details/132924856