GB28181设备接入端如何播放语音广播数据?

2023-11-19

技术背景

语音广播功能是GB28181设备接入端非常重要的功能属性,语音广播让终端和平台之间,有了实时双向互动,可以满足执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等场景的技术诉求。

这里我们先回顾下GB28181规范关于语音广播的描述:

语音广播功能实现用户通过语音输入设备向前端语音输出设备的语音广播。

语音输入设备/语音输入联网系统(以下简称“语音流发送者”)、SIP 服务器向语音输出设备/语音输出视频监控联网系统(以下简称“语音流接收者”)发送通知消息,语音流接收者收到通知消息后,进行判断处理。

若能够接收广播,则向语音流发送者发起呼叫请求,获取广播媒体流。

语音输入设备、语音输出设备编码应符合E.1 的规定。如果设备具备语音输出能力,则在设备目录查询和订阅时,需要上报语音输出设备。如果不上报语音输出设备,则表示该设备没有语音输出能力。

上报语音输出通道时,ParentID 填写其父设备的 ID。例如,IPC 具备语音输出能力,在 IPC 上报设备目录时,需要上报语音输出设备。该语音输出设备ID的类型编码为 137,其父设备为该IPC。NVR 本身具备语音输出能力,在 NVR 上报设备目录时,除了上报 NVR 接入的 IPC 以及IPC 自身的语音输出设备之外,还需要上报语音输出设备。该语音输出设备ID的类型编码为137.其父设备为该NVR。监控中心与设备之间进行语音广播,可以直接对语音输出设备发送语音广播通知,也可以对语音输出设备所属的前端主设备发送语音广播通知。

对前端主设备发送语音广播通知消息中仅需携带前端主设备编码,表示对该设备上所有的语音输出设备进行语音广播。例如,对IPC 发送语音广播通知,表示对该IPC 接入的所有语音输出设备进行广播;对 NVR 发送语音广播通知,表示对 NVR 下所有 IPC以及自身的语音输出设备进行广播。

语音流的封装格式应符合 C.2.4 音频流的 RTP 封装的定义。

语音广播宜符合附录 K 规定的媒体流保活机制。

技术实现

本文我们不再探讨GB28181语音广播的具体流程,这里我们假定信令交互已经完成,准备接收数据:

收到broadcast语音广播后,我们的处理逻辑如下:

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 EventHandlerPlayerV2());

  // 缓存大小可以调整
  lib_player_.SmartPlayerSetBuffer(player_handle_, 0);

  // lib_player_.SmartPlayerSetFastStartup(player_handle_, 0);

  // set report download speed(默认2秒一次回调 用户可自行调整report间隔)
  lib_player_.SmartPlayerSetReportDownloadSpeed(player_handle_, 1, 2);

  lib_player_.SmartPlayerClearRtpReceivers(player_handle_);
  lib_player_.SmartPlayerAddRtpReceiver(player_handle_, rtp_receiver_handle_);

  lib_player_.SmartPlayerSetSurface(player_handle_, null);

  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,  "[daniusdk]start audio play failed");
    return false;
  }

  lib_player_.SmartPlayerSetAudioDataCallback(player_handle_, new PlayerAudioDataOutput());
  lib_player_.SmartPlayerSetPullStreamAudioTranscodeAAC(player_handle_, 0);

  if (0 ==lib_player_.SmartPlayerStartPullStream(player_handle_) ) {
    // 启动定时器,长时间收不到音频数据,则停止播放,发送BYE
    last_received_audio_data_time_.set(SystemClock.elapsedRealtime());
    handler_.postDelayed(new AudioPlayerPCMTimer(player_handle_), AudioPlayerPCMTimer.INTERVAL_MS);
  }

  return true;
}

简单来说,就是启动了个纯语音播放的实例,来处理过来的PCMA或PS的audio数据。

其中PlayerExternalPCMOutput()主要是把数据塞到GB28181数据采集处理的模块,来实现语音广播的回音消除的目的。

class PlayerExternalPCMOutput implements NTExternalAudioOutput {
  private int buffer_size_ = 0;
  private ByteBuffer pcm_buffer_ = null;

  @Override
  public 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) {
    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 void stopAudioPlayer() {
  if (player_handle_ != 0 ) {
    lib_player_.SmartPlayerStopPullStream(player_handle_);
    lib_player_.SmartPlayerStopPlay(player_handle_);
    lib_player_.SmartPlayerClose(player_handle_);
    player_handle_ = 0;
  }
}

总结

GB28181语音广播这块,如果平台侧和终端,都是按照规范来实现的话,问题会少很多,实际尴尬的是,大厂或部分厂商先入为主,实际生产环境,不一定按照预期的,谁的问题谁处理,作为Android终端模块,push不动国标平台侧的时候,有时候只有兼容它,这种痛苦真是一言难尽。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GB28181设备接入端如何播放语音广播数据? 的相关文章

随机推荐

  • 路由器常见配置和解决方案

    示列1 分析 由于Windows系统的网关没有配置 如果配置好了再次ping不通的话 可能是由于DNS没有配置 转载于 https www cnblogs com l75790 p 11022632 html
  • rdb map出錯rbd sysfs write failed

    創建了一個rbd鏡像 rbd create size 4096 docker test 然後 在Ceph client端將該rbd鏡像映射為本地設備時出錯 rbd map docker test name client admin rbd
  • 微信小程序<open-data type=“userAvatarUrl“>真机无法获取头像问题/解决办法

    今天在做小程序的时候使用open data type userAvatarUrl 标签发现在本地开发的时候可以获取本人的头像 但是在真机上就无法显示解决办法 我们要换一种思路去处理 使用官方提供的方法 官网文档链接 wxml
  • 模块功能耗时长排查

    模块功能耗时长排查 1 场景介绍1 1 1 原有场景 OA服务 发送代办 代办推送到OA代办中心 OA代办中心 推送到 总部统一代办中心 我们排查请求耗时 发现 OA代办中心 推送到 总部统一代办中心的业务代码耗时非常久 1 2 原有场景总
  • Ubuntu配置NFS服务器(Linux挂载Linux)

    Ubuntu配置NFS服务器 服务器端的配置 Ubuntu安装NFS服务器端 sudo apt get install nfs kernel server 服务端查看版本 nfsstat s 在桌面上创建共享目录 mkdir share 修
  • ChatGPT提示词工程进阶教学

    ChatGPT提示词工程 1 两种大型语言模型LLM 1 1 基础大模型 base LLM 1 2 指令调优大模型 Instruction Tuned LLM 2 如何更清晰 具体地书写提示词 2 1 在提示词中使用 定界符 2 2 向模型
  • 正则表达式的贪婪与非贪婪匹配

    例 String str 地点 北京市123区456 测试测试 测试 要匹配在 地点 之后并且在 之前的内容 贪婪匹配 正则表达式一般趋向于最大长度匹配 也就是所谓的贪婪匹配 例如上面的str 使用正则 Patter p lt 地点 默认是
  • 【面试刷题】——指针存的是什么

    指针 Pointer 是一种用于存储变量或数据对象内存地址的数据类型 指针存储的是内存地址 这个内存地址指向计算机内存中的某个特定位置 这个位置存储着实际的数据 当你创建一个指针变量时 它会指向另一个变量的内存地址 从而允许你通过该指针来访
  • linux内部调用摄像头的第三方程序(命令):cheese

    linux内部调用摄像头的第三方程序 命令 cheese sudo apt get install cheese 关于cheese的使用可能会出现异常 Clutter WARNING Whoever translated default L
  • PHP实现发送邮件(附代码)

    发送邮寄功能的实现用到了PHP中的phpmailer函数包 它支持openssl和sockets 下载地址 下载后找到class phpmailer php class smtp php这两个文件 和你的代码放在一个目录 要实现发送邮件的功
  • mipi协议_MIPI系列之“MIPI CSI/DSI接口的FPGA实现”

    欢迎FPGA工程师加入官方微信技术群 点击蓝字关注我们FPGA之家 中国最好最大的FPGA纯工程师社群 本文主要介绍MIPI D PHY在FPGA上的实现 随着camera和显示技术的发展 MIPI接口在实际运用中越来越广泛 MIPI接口协
  • Solaris 10以太网卡设置

    前言 Solaris操作系统的以太网卡 以下简称网卡 设置 是一个老生常谈的话题 网上的相关资料也是汗牛充栋 数不胜数 但对刚刚接触Solaris的朋友来说 最需要的大概是一篇简明通俗 易读易用的操作指南 鉴于此 本文将网卡设置过程中涉及的
  • Robotframework 入门教程(二)

    变量 RF用 分别表示标量 列表 和字典 对应的就是python中的sre list和dict RF中Variables用来创建变量 修改我们的demo robot如下 对应于python的语法 var value list1 a b c
  • java集合List学习(结合源代码)

    一 首先 我们来一个简单的程序 import java util ArrayList import java util List public class Person public static void main String args
  • 含分布式电源的配电网日前两阶段优化调度模型(Matlab代码实现)

    个人主页 研学社的博客 欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 文献来源 4 Matlab代码 数据 文章讲解 1 概述 文
  • 彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)

    尊重作者 支持原创 如需转载 请附上原地址 https blog csdn net libaineu2004 article details 19245205 一 Qt Creator环境设置 1 cpp或h文件从window上传到Ubun
  • SDP文件的作用及其意义

    SDP是一个IETF标准格式 用来描述视频和 或者音频的RTP流 sdp文件时如何生成的 刚接触这一块 没有思路用记事本新建一个 txt文件 另存时把扩展名改为 sdp就生成了 具体内容可以参考rfc2327 以及具体编码格式对应的各个补充
  • reset_index()函数

    reset index 函数 作用 使用索引重置生成一个新的DataFrame或Series 可以把索引用作列 话不多说直接上代码 gt gt gt import pandas as pd gt gt gt import numpy as
  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • GB28181设备接入端如何播放语音广播数据?

    技术背景 语音广播功能是GB28181设备接入端非常重要的功能属性 语音广播让终端和平台之间 有了实时双向互动 可以满足执法记录仪 智能安全帽 智能监控 智慧零售 智慧教育 远程办公 明厨亮灶 智慧交通 智慧工地 雪亮工程 平安乡村 生产运