Android国标接入端如何播放GB28181平台端语音广播数据

GB28181语音广播这块,我们依据GB/T28181-2016针对流程和实例代码,做过详细的描述,本次主要是探讨下,广播数据过来后,如何处理。

鉴于我们之前有非常成熟的RTMP|RTSP低延迟播放模块,语音广播数据过来后,调用startAudioPlay(),ntsOnInviteAudioBroadcastResponse()处理如下:

@Override
public void ntsOnInviteAudioBroadcastResponse(String sourceID, String targetID, int statusCode, PlaySessionDescription sessionDescription) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "ntsOnInviteAudioBroadcastResponse, statusCode:" + status_code_ +" sourceID:" + source_id_ + ", targetID:" + target_id_);boolean is_need_destory_rtp = true;if (gb28181_agent_ != null ) {boolean is_need_bye = 200==status_code_;if (200 == status_code_ && session_description_ != null && rtp_receiver_handle_ != 0 ) {MediaSessionDescription audio_des = session_description_.getAudioDescription();SDPRtpMapAttribute audio_attr = null;if (audio_des != null && audio_des.getRtpMapAttributes() != null && !audio_des.getRtpMapAttributes().isEmpty() )audio_attr = audio_des.getRtpMapAttributes().get(0);if ( audio_des != null && audio_attr != null ) {lib_player_.SetRTPReceiverSSRC(rtp_receiver_handle_, audio_des.getSSRC());lib_player_.SetRTPReceiverPayloadType(rtp_receiver_handle_, audio_attr.getPayloadType(),audio_attr.getEncodingName(), 2, audio_attr.getClockRate());// 如果是PCMA, SDK会默认填 采样率8000, 通道1, 其他音频编码需要手动填入// lib_player_.SetRTPReceiverAudioSamplingRate(rtp_receiver_handle_, 8000);// lib_player_.SetRTPReceiverAudioChannels(rtp_receiver_handle_, 1);lib_player_.SetRTPReceiverRemoteAddress(rtp_receiver_handle_, audio_des.getAddress(), audio_des.getPort());lib_player_.InitRTPReceiver(rtp_receiver_handle_);if (startAudioPlay()) {is_need_bye = false;is_need_destory_rtp = false;gb_broadcast_source_id_ = source_id_;gb_broadcast_target_id_ = target_id_;btnGB28181AudioBroadcast.setText("终止GB28181语音广播");btnGB28181AudioBroadcast.setEnabled(true);}}} else {btnGB28181AudioBroadcast.setText("GB28181语音广播");}if (is_need_bye)gb28181_agent_.byeAudioBroadcast(source_id_, target_id_);}if (is_need_destory_rtp)destoryRTPReceiver();}private String source_id_;private String target_id_;private int status_code_;private PlaySessionDescription session_description_;public Runnable set(String source_id, String target_id, int status_code, PlaySessionDescription session_description) {this.source_id_ = source_id;this.target_id_ = target_id;this.status_code_ = status_code;this.session_description_ = session_description;return this;}}.set(sourceID, targetID, statusCode, sessionDescription),0);
}

startAudioPlay()初始化实例后,为了保证低延迟,拉流端设置0 buffer,处于调试方便,设置download speed回调2-5秒一次(可以看到是不是有音频数据过来),由于只需要播放音频,不需要视频,所以不要设置surface下去,然后设置拉流数据回调,需要注意的是,拉到的audio数据,不要转aac输出:

private boolean startAudioPlay() {if (player_handle_ != 0 )return false;player_handle_ = lib_player_.SmartPlayerOpen(context_);if (player_handle_ == 0)return false;lib_player_.SetSmartPlayerEventCallbackV2(player_handle_,new EventHandePlayerV2());// 缓存大小可以调整lib_player_.SmartPlayerSetBuffer(player_handle_, 0);// lib_player_.SmartPlayerSetFastStartup(player_handle_, 0);// set report download speed(默认2秒一次回调 用户可自行调整report间隔)lib_player_.SmartPlayerSetReportDownloadSpeed(player_handle_, 1, 20);lib_player_.SmartPlayerClearRtpReceivers(player_handle_);lib_player_.SmartPlayerAddRtpReceiver(player_handle_, rtp_receiver_handle_);lib_player_.SmartPlayerSetSurface(player_handle_, null);// lib_player_.SmartPlayerSetRenderScaleMode(player_handle_, 1);lib_player_.SmartPlayerSetAudioOutputType(player_handle_, 1);lib_player_.SmartPlayerSetMute(player_handle_, 0);lib_player_.SmartPlayerSetAudioVolume(player_handle_, 100);lib_player_.SmartPlayerSetExternalAudioOutput(player_handle_, new PlayerExternalPCMOutput());lib_player_.SmartPlayerSetUrl(player_handle_, "rtp://ntinternal/rtpreceiver/implemention0");if (0 != lib_player_.SmartPlayerStartPlay(player_handle_)) {lib_player_.SmartPlayerClose(player_handle_);player_handle_ = 0;Log.e(TAG,  "start audio paly failed");return false;}lib_player_.SmartPlayerSetAudioDataCallback(player_handle_, new PlayerAudioDataOutput());lib_player_.SmartPlayerSetPullStreamAudioTranscodeAAC(player_handle_, 0);if (0 ==lib_player_.SmartPlayerStartPullStream(player_handle_) ) {// 启动定时器,长时间收不到音频数据,则停止播放,发送BYElast_received_audio_data_time_.set(SystemClock.elapsedRealtime());handler_.postDelayed(new AudioPlayerPCMTimer(player_handle_), AudioPlayerPCMTimer.INTERVAL_MS);}return true;
}

调用StartPlay后,拿到的audio数据,塞到publisher端,做回音消除处理:

class PlayerExternalPCMOutput implements NTExternalAudioOutput {private int buffer_size_ = 0;private ByteBuffer pcm_buffer_ = null;@Overridepublic ByteBuffer getPcmByteBuffer(int size)  {//Log.i("getPcmByteBuffer", "size: " + size);if(size < 1)return null;if(buffer_size_ != size) {buffer_size_ = size;pcm_buffer_ = ByteBuffer.allocateDirect(buffer_size_);}return pcm_buffer_;}public void onGetPcmFrame(int ret, int sampleRate, int channel, int sampleSize, int is_low_latency) {/*Log.i("onGetPcmFrame", "ret: " + ret + ", sampleRate: " + sampleRate + ", channel: " + channel + ", sampleSize: " + sampleSize +",is_low_latency:" + is_low_latency + " buffer_size:" + buffer_size);*/if (null == pcm_buffer_)return;pcm_buffer_.rewind();if (ret == 0 && isGB28181StreamRunning && publisherHandle != 0 )libPublisher.SmartPublisherOnFarEndPCMData(publisherHandle, pcm_buffer_, sampleRate, channel, sampleSize, is_low_latency);}
}private static int align(int d, int a) { return (d + (a - 1)) & ~(a - 1); }class PlayerAudioDataOutput implements NTAudioDataCallback {private int buffer_size_ = 0;private int param_info_size_ = 0;private ByteBuffer buffer_ = null;private ByteBuffer parameter_info_ = null;@Overridepublic ByteBuffer getAudioByteBuffer(int size) {//Log.i("getAudioByteBuffer", "size: " + size);if( size < 1 ) return null;if (size <= buffer_size_ && buffer_ != null )return buffer_;buffer_size_ = align(size + 256, 16);buffer_ = ByteBuffer.allocateDirect(buffer_size_);// Log.i("getAudioByteBuffer", "size: " + size + " buffer_size:" + audio_buffer_size);return buffer_;}@Overridepublic ByteBuffer getAudioParameterInfo(int size) {//Log.i("getAudioParameterInfo", "size: " + size);if(size < 1) return null;if ( size <= param_info_size_ &&  parameter_info_ != null )return  parameter_info_;param_info_size_ = align(size + 32, 16);parameter_info_ = ByteBuffer.allocateDirect(param_info_size_);//Log.i("getAudioParameterInfo", "size: " + size + " buffer_size:" + param_info_size);return parameter_info_;}public void onAudioDataCallback(int ret, int audio_codec_id, int sample_size, int is_key_frame, long timestamp, int sample_rate, int channel, int parameter_info_size, long reserve)  {/*Log.i("onAudioDataCallback", "ret: " + ret + ", audio_codec_id: " + audio_codec_id + ", sample_size: " + sample_size + ", timestamp: " + timestamp +",sample_rate:" + sample_rate);*/last_received_audio_data_time_.set(SystemClock.elapsedRealtime());}
}

如果长时间收不到数据,主动断掉音频广播:

class AudioPlayerPCMTimer implements Runnable {public static final int THRESHOLD_MS = 60*1000; // 暂时设置到1分钟public static final int INTERVAL_MS = 10*1000; // 十秒一次, 太频繁影响主线程public AudioPlayerPCMTimer(long handle) {handle_ = handle;}@Overridepublic void run() {if (0 == handle_)return;if (handle_ != player_handle_) {Log.i(TAG, "AudioPlayerPCMTimer handle changed, will stop this timer, handle:" + handle_ + " new handle:" + player_handle_);return;}long last_update_time = last_received_audio_data_time_.get();long cur_time = SystemClock.elapsedRealtime();// Log.i(TAG, "AudioPlayerPCMTimer last_update_time:" + last_update_time + " cur_time:" + cur_time);if ( (last_update_time + this.THRESHOLD_MS) >  cur_time) {// 继续定时器handler_.postDelayed(new AudioPlayerPCMTimer(this.handle_), this.INTERVAL_MS);//  Log.i(TAG, "AudioPlayerPCMTimer running.");}else {Log.i(TAG, "AudioPlayerPCMTimer,trigger threshold, bye audio, stop player.");if (gb_broadcast_source_id_ != null && gb_broadcast_target_id_ != null) {if (gb28181_agent_ != null)gb28181_agent_.byeAudioBroadcast(gb_broadcast_source_id_, gb_broadcast_target_id_);}gb_broadcast_source_id_ = null;gb_broadcast_target_id_ = null;stopAudioPlayer();destoryRTPReceiver();btnGB28181AudioBroadcast.setText("GB28181语音广播");btnGB28181AudioBroadcast.setEnabled(false);}}private long handle_;
}

停止广播数据播放:

private void stopAudioPlayer() {if (player_handle_ != 0 ) {lib_player_.SmartPlayerStopPullStream(player_handle_);lib_player_.SmartPlayerStopPlay(player_handle_);lib_player_.SmartPlayerClose(player_handle_);player_handle_ = 0;}
}

销毁RTPReceiver:

private void destoryRTPReceiver() {if (rtp_receiver_handle_ != 0) {lib_player_.UnInitRTPReceiver(rtp_receiver_handle_);lib_player_.DestoryRTPReceiverSession(rtp_receiver_handle_);lib_player_.DestoryRTPReceiver(rtp_receiver_handle_);rtp_receiver_handle_ = 0;}
}

以上是针对GB28181平台端音频广播播放的一点说明,感兴趣的开发者,可以酌情参考,也可以和我探讨Android平台GB28181接入模块的测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Win11和Win10有什么区别 Win11和Win10区别对比

Win11是微软全新一代操作系统&#xff0c;在界面和功能上和Win10相比还是有不少区别的&#xff0c;如果你还在犹豫要不要升级Win11的话&#xff0c;那么不妨来看看Win11和Win10之间有哪些区别吧。 1、 开始菜单&#xff1a;简单的图标&#xff0c;没有动态磁贴 Windows 11 的…

Android平台RTSP、RTMP播放端如何实现YUV或ARGB数据按设定角度旋转

做音视频RTSP或RTMP直播播放器的时候&#xff0c;不免会遇到这样的诉求&#xff0c;实时播放或快照的时候&#xff0c;由于前端摄像头安装角度不一定是正向&#xff0c;导致播放或快照的时候&#xff0c;视频view显示的画面是呈90 180甚至270旋转的。 以Android平台为例&#…

Win11任务栏颜色如何更改 Win11更改任务栏颜色教程

win11系统中任务栏颜色默认为浅蓝色&#xff0c;有用户认为它可能会与白色的网页或界面重叠&#xff0c;影响自己的操作&#xff0c;想问问有没有什么方法可以更改任务栏的颜色。可以通过更改主题或者更改深色浅色模式来更改任务栏的颜色&#xff0c;将其调整为自己喜欢的颜色。…

国网B接口注册(REGISTER)接口描述和消息示例

技术背景 电网视频监控系统是智能电网的一个重要组成部分&#xff0c;广泛应用于电网的建设、生产、运行、经营等方面。由于视频监控系统在不同的建设时期选用了不同的技术和不同厂家的产品&#xff0c;导致了标准不统一、技术路线不一致。目前国家电网公司智能电网建设&#…

Win7系统怎么设置虚拟内存

我们在日常生活中使用电脑的时候&#xff0c;有时候会以你为系统内存不足导致系统崩溃&#xff0c;甚至严重的还会导致电脑死机。电脑内存不足的时候&#xff0c;那么Win7系统怎么设置虚拟内存呢?如果您不会设置虚拟内存的话&#xff0c;就让小编来教教你Win7系统设置虚拟内存…

国网B接口资源上报(Push_Resourse)接口描述和消息示例

上篇blog&#xff0c;梳理了国网B接口的REGISTER接口描述和消息示例&#xff0c;前端系统加电启动并初次注册成功后&#xff0c;向平台上报前端系统的设备资源信息&#xff08;包括&#xff1a;视频服务器、DVR/DVS、摄像机、告警设备、环境量采集设备等模拟或数字信号采集设备…

Win7电脑无法获取ip地址怎么解决

有的朋友会遇到了电脑无法获取ip地址的情况&#xff0c;一般ip地址是路由自动分配的&#xff0c;如果获取不到ip可能是路由器出来问题&#xff0c;那Win7电脑无法获取ip地址怎么解决呢?今天小编带给大家win7系统电脑无法获取ip地址的解决方法&#xff0c;一起来看看吧。 Win7…

GB/T 28181-2016多响应消息传输探究

我们在实现Android平台GB28181设备接入模块的时候&#xff0c;有遇到发送多条记录的情况&#xff0c;本文主要探讨下GB28181多响应传输。 规范解读 如GB/T28181-2016规范所说&#xff1a;目录查询响应、文件查询响应、订阅后的通知消息会出现响应、通知消息需发送多条记录的情…

windows7系统设置动态屏保的教程

我们知道电脑在长时间没有操作的情况下就会自动锁屏&#xff0c;可以起到保护我们隐私的作用&#xff0c;也可以起到一个美观的作用&#xff0c;那系统自带的屏保我们不满意的话&#xff0c;想重新设置却不知道在哪里设置怎么办?没关系下面给大家带来了windows7系统设置动态屏…

Android平台GB28181设备接入端语音广播如何实现实时音量调节

Android平台GB28181设备接入&#xff0c;语音广播功能非常重要&#xff0c;本文要介绍的&#xff0c;不是语音广播的流程&#xff0c;语音广播流程&#xff0c;之前的blog也有非常详细的分享&#xff0c;感兴趣的可以参考官方规范书的交互流程&#xff1a; 语音广播这块&#x…

GB28181基于TCP协议的视音频媒体传输探究及实现

我们先看看官方规范针对TCP协议的视音频传输描述&#xff1a; 实时视频点播、历史视频回放与下载的 TCP媒体传输应支持基于RTP封装的视音频PS流&#xff0c;封装格式参照IETFRFC4571。 流媒体服务器宜同时支持作为TCP媒体流传输服务端和客户端。默认情况下&#xff0c;前端设…

qq浏览器怎么导入其他浏览器收藏夹

现在浏览器种类非常多&#xff0c;有时候由于特殊需要&#xff0c;一个电脑有好几个浏览器&#xff0c;在使用浏览器的过程中收藏夹里的东西非常的多&#xff0c;但时间越久&#xff0c;收藏夹东西累计得越来也多&#xff0c;我们记性再好也会偶尔记不住自己需要的东西是在哪个…

Android平台GB28181接入端如何对接UVC摄像头?

我们在对接Android平台GB28181接入的时候&#xff0c;有公司提出这样的需求&#xff0c;除了采集执法记录仪摄像头自带的数据外&#xff0c;还想通过执法记录仪采集外接UVC摄像头。 实际上&#xff0c;这块对我们来说有点炒冷饭了&#xff0c;不算新的诉求。​大牛直播SDK​在2…

win10系统电脑wifi图标不见了的开启方法

很多的用户都习惯了在桌面右下方的小图标中设置网络&#xff0c;但是很多时候都遇到了图标不见了的情况&#xff0c;win10系统电脑wifi图标不见了怎么办呢&#xff1f;就此问题&#xff0c;今天就为你们带来了win10系统电脑wifi图标不见了的开启方法&#xff0c;一起看看吧。 w…

Android平台实现系统内录(捕获播放的音频)并推送RTMP服务技术方案探究

几年来&#xff0c;我们在做无纸化同屏或在线教育相关场景的时候&#xff0c;总是被一件事情困扰&#xff1a;如何实现Android平台的系统内录&#xff0c;并推送到其他播放端&#xff0c;常用的场景比如做无纸化会议或教育的时候&#xff0c;主讲人或老师需要放一个视频&#x…

windows10电脑无法连接到internet怎么解决

许多上网的小伙伴都不知道电脑无法连接到internet怎么办而导致电脑没法上网的问题&#xff0c;windows10电脑无法连接到internet怎么解决?就此问题&#xff0c;今天就专门为大家带来了电脑无法连接到internet解决方法&#xff0c;快来学习看看吧。 windows10电脑无法连接到int…

Android平台GB28181设备接入端PTZ对接详解

PTZCmd实现背景 上一篇blog“Android平台GB28181设备接入模块之球机/云台控制探究”谈到&#xff0c;Android平台做国标GB28181设备接入端的时候&#xff0c;PTZ控制要不要处理&#xff1f;如果处理&#xff0c;难度大不大&#xff1f; 首先说要不要处理&#xff1a;如果只是…

Win7笔记本查看无线网卡是否“支持的承载网络”的方法

如果你笔记本电脑无线网卡可以支持的承载网络&#xff0c;那么我们就可以将无线网卡开启wifi共享&#xff0c;不过我们要怎么查看呢?就此问题&#xff0c;下面小编介绍Win7笔记本查看无线网卡是否“支持的承载网络”的方法&#xff0c;一起来学习吧! Win7笔记本查看无线网卡是…

Android平台GB28181设备接入模块摄像头采集方向不对怎么办?

背景 我们在做Android平台GB28181设备接入模块的时候&#xff0c;有开发者提到这样的诉求&#xff1a;他们的智能头盔、执法记录仪等设备&#xff0c;采集到的图像&#xff0c;是旋转了90、180甚至270的&#xff0c;设备本身无法针对图像做翻转或者旋转操作&#xff0c;问我们…

Win7系统无法复制粘贴怎么解决

现在电脑已经成为了我们每天都要使用的工具&#xff0c;然而随着使用的时间越长&#xff0c;就越容易出现各种电脑问题&#xff0c;不管是多小的问题&#xff0c;都会影响我们使用电脑。Win7系统无法复制粘贴怎么解决&#xff1f;今天请跟小编一起来看看Win7系统的电脑突然无法…