如何快速实现Android平台前端设备接入能力

2023-11-06

技术背景

SIP(会话初始化协议)是在 IP网络上进行多媒体通信的应用层控制协议,以几种RFC的形式提供,其中最重要的是包含核心协议规范的RFC3261。该协议用于创建,修改和终止与一个或多个参与者的会话。通过会话,我们了解了一组进行通信的发送方和接收方,以及在通信过程中这些发送方和接收方保持的状态。会话的示例可以包括Internet电话呼叫,多媒体分发,多媒体会议,分布式计算机游戏等。

SIP不是通信设备将需要的唯一协议,也不意味着是通用协议。SIP的目的仅仅是使通信成为可能,通信本身必须通过其他方式(可能还有其他协议)来实现。

与SIP一起最常使用的两种协议是RTP和SDP。 RTP协议用于承载实时多媒体数据(包括音频,视频和文本),该协议可以将数据编码和拆分为数据包,并通过Internet传输此类数据包。

另一个重要的协议是SDP,用于描述和编码会话参与者的功能。 然后,将这种描述用于协商会话的特征,以便所有设备都可以参与(例如,包括协商用于编码媒体的编解码器,以便所有参与者都可以对其进行解码,协商使用的传输协议 等等)。

GB/T28181-2011 《安全防范视频监控联网系统信息传输、交换、控制技术要求》是由公安部科技信息化局提出,由全国安全防范报警系统标准化技术委员会(SAC/TC100)归口,公安部一所等多家单位共同起草的一部国家标准。

该标准规定了城市监控报警联网系统中信息传输、交换、控制的互联结构、通信协议结构,传输、交换、控制的基本要求和安全性要求,以及控制、传输流程和协议接口等技术要求。该标准适用于安全防范监控报警联网系统的方案设计、系统检测、验收以及与之相关的设备研发、生产,其他信息系统可参考采用。
该标准于2012年6月1日正式发布实施,在全国范围内的平安城市项目建设中被普遍推广应用。GB/T28181-2011标准自发布以来,受到了各大视频监控厂商的积极响应。截止2012年底,有近百家视频监控企业通过公安部一所、公安部三所的认证,如深圳宙视达、浙江宇视、超视科技、东方网力、海康威视、高远时代、浙江大华、先进视讯、波粒科技、华为技术、中兴力维、中星电子、科达、天地伟业等。

相关接口

废话不多说,直接上设计接口,好多开发者网上看到的大多是非常简单的接口。极致简单,一直是我们追求的目标,但是更好的参数化配置和可扩展的设计,也是一个规范化产品的必经之路。

除了常规的音视频采集编码接口外,GB28181设备接入模块,主要分信令交互和媒体数据传输两个部分,以大牛直播SDK(官方)分别介绍下相关接口设计。

媒体数据传输相关

	/*+++++++++++++++RTP Sender相关接口+++++++++++++++*/

	/*
	 * 创建RTP Sender实例
	 *
	 * @param reserve:保留参数传0
	 *
	 * @return RTP Sender 句柄,0表示失败
	 */
	public native long CreateRTPSender(int reserve);

	/**
	 *设置 RTP Sender传输协议
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param transport_protocol, 0:UDP, 1:TCP, 默认是UDP
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderTransportProtocol(long rtp_sender_handle, int transport_protocol);

	/**
	 *设置 RTP Sender IP地址类型
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param ip_address_type, 0:IPV4, 1:IPV6, 默认是IPV4, 当前仅支持IPV4
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderIPAddressType(long rtp_sender_handle, int ip_address_type);

	/**
	 *设置 RTP Sender RTP Socket本地端口
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param port, 必须是偶数,设置0的话SDK会自动分配, 默认值是0
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderLocalPort(long rtp_sender_handle, int port);

	/**
	 *设置 RTP Sender SSRC
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderSSRC(long rtp_sender_handle, String ssrc);

	/**
	 *设置 RTP Sender RTP socket 发送Buffer大小
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param buffer_size, 必须大于0, 默认是512*1024, 当前仅对UDP socket有效, 根据视频码率考虑设置合适的值
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderSocketSendBuffer(long rtp_sender_handle, int buffer_size);

	/**
	 *设置 RTP Sender RTP时间戳时钟频率
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param clock_rate, 必须大于0, 对于GB28181 PS规定是90kHz, 也就是90000
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderClockRate(long rtp_sender_handle, int clock_rate);

	/**
	 *设置 RTP Sender 目的IP地址, 注意当前用在GB2818推送上,只设置一个地址,将来扩展如果用在其他地方,可能要设置多个目的地址,到时候接口可能会调整
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param address, IP地址
	 * @param port, 端口
	 *
	 * @return {0} if successful
	 */
	public native int SetRTPSenderDestination(long rtp_sender_handle, String address, int port);

	/**
	 *初始化RTP Sender, 初始化之前先调用上面的接口配置相关参数
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 *
	 * @return {0} if successful
	 */
	public native int InitRTPSender(long rtp_sender_handle);

	/**
	 *获取RTP Sender RTP Socket本地端口
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 *
	 * @return 失败返回0, 成功的话返回响应的端口, 请在InitRTPSender返回成功之后调用
	 */
	public native int GetRTPSenderLocalPort(long rtp_sender_handle);

	/**
	 * UnInit RTP Sender
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 *
	 * @return {0} if successful
	 */
	public native int UnInitRTPSender(long rtp_sender_handle);

	/**
	 * 释放RTP Sender, 释放之后rtp_sender_handle就无效了,请不要再使用
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 *
	 * @return {0} if successful
	 */
	public native int DestoryRTPSender(long rtp_sender_handle);

 信令相关操作

	/*+++++++++++++++GB28181相关接口+++++++++++++++*/

	/**
	 * 设置GB28181 RTP Sender
	 *
	 * @param rtp_sender_handle, CreateRTPSender返回值
	 * @param rtp_payload_type, 对于GB28181 PS, 协议定义是96, 具体以SDP为准
	 *
	 * @return {0} if successful
	 */
	public native int SetGB28181RTPSender(long handle, long rtp_sender_handle, int rtp_payload_type);

	/**
	 * 启动 GB28181 媒体流
	 *
	 * @return {0} if successful
	 */
	public native int StartGB28181MediaStream(long handle);

	/**
	 * 停止 GB28181 媒体流
	 *
	 * @return {0} if successful
	 */
	public native int StopGB28181MediaStream(long handle);


	/*---------------GB28181相关接口---------------*/

 启动、停止GB28181

完成视频分辨率等参数配置后,点击“启动GB28181”,即可开始走信令交互流程,设备端主动发送Register,进入后续交互流程。

如需停止GB28181,点停止即可。

GB28181设备端主要实现了按需推送数据到平台端。

    class ButtonGB28181AgentListener implements OnClickListener {
        public void onClick(View v) {
            stopGB28181Stream();
            destoryRTPSender();

            if (null == gb28181_agent_ ) {
                if( !initGB28181Agent() )
                    return;
            }

            if (gb28181_agent_.isRunning()) {
                gb28181_agent_.terminateAllPlays(true);// 目前测试下来,发送BYE之后,有些服务器会立即发送INVITE,是否发送BYE根据实际情况看
                gb28181_agent_.stop();
                btnGB28181Agent.setText("启动GB28181");
            }
            else {
                if ( gb28181_agent_.start() ) {
                    btnGB28181Agent.setText("停止GB28181");
                }
            }
        }
    }

注册

当Andriod设备端第一次接入平台端时,设备端将持续向平台端发送 REGISTER消息,直到 Server端回复"200 OK"代表注册成功。

如果设备或系统注册不成功,宜延迟一定的随机时间后重新注册每隔一定时间客户端都会再次向服务器刷新注册,防止注册过期导致连接断开。

以基本注册为例:基本注册采用IETFRFC3261规定的基于数字摘要的挑战应答式安全技术进行注册。

注册流程描述如下 :
a) 1:SIP 代理向 SIP 服务器发送 Register请求;
b) 2:SIP 服务器向 SIP代理发送响应401,并在响应的消息头 WWW_Authenticate字段中给出适合S IP 代理的认证体制和参数 ;
c) 3:SIP 代理重新向 SIP 服务器发送 Register 请求 , 在请求的 Authorization 字段给出信任书, 包含认证信息 ;
d) 4:SIP 服务器对请求进行验证 , 如果检查出 SIP 代理身份合法 , SIP 代理发送成功响应 200OK, 如果身份不合法则发送拒绝服务应答
相关注册反馈:
    @Override
    public void ntsRegisterOK(String dateString) {
        Log.i(TAG, "ntsRegisterOK Date: " + (dateString!= null? dateString : ""));
    }

    @Override
    public void ntsRegisterTimeout() {
        Log.e(TAG, "ntsRegisterTimeout");
    }

    @Override
    public void ntsRegisterTransportError(String errorInfo) {
        Log.e(TAG, "ntsRegisterTransportError error:" + (errorInfo != null?errorInfo :""));
    }

信息查询(Catalog)

 注册成功后,客户端与服务器之间信息查询操作,如目录查询、历史录像文件查看等,GB28181使用 SIP扩展协议规定的 Message方法实现。目前使用了两种类型的查询命令:Catalog 设备目录查询消息、RecordInfo 历史录像文件查询消息。
本文以Catalog设备目录查询消息为例:平台端向设备端发送Catalog请求,设备端回复200 OK后,发送设备信息,平台端回复200 OK,如遇多个设备信息,切记分次发送。
    private boolean initGB28181Agent()
    {
        if ( gb28181_agent_ != null )
            return  true;

        String local_ip_addr = IPAddrUtils.getIpAddress(myContext);
        Log.i(TAG, "initGB28181Agent local ip addr: " + local_ip_addr);

        if ( local_ip_addr == null || local_ip_addr.isEmpty() ) {
            Log.e(TAG, "initGB28181Agent local ip is empty");
            return  false;
        }

        gb28181_agent_ = GBSIPAgentFactory.getInstance().create();
        if ( gb28181_agent_ == null ) {
            Log.e(TAG, "initGB28181Agent create agent failed");
            return false;
        }

        gb28181_agent_.addListener(this);

        // 必填信息
        gb28181_agent_.setLocalAddressInfo(local_ip_addr, gb28181_sip_local_port_);
        gb28181_agent_.setServerParameter(gb28181_sip_server_addr_, gb28181_sip_server_port_, gb28181_sip_server_id_, gb28181_sip_server_domain_);
        gb28181_agent_.setUserInfo(gb28181_sip_username_, gb28181_sip_password_);

        // 可选参数
        gb28181_agent_.setUserAgent(gb28181_sip_user_agent_filed_);
        gb28181_agent_.setTransportProtocol(gb28181_sip_trans_protocol_==0?"UDP":"TCP");

        // GB28181配置
        gb28181_agent_.config(gb28181_reg_expired_, gb28181_heartbeat_interval_, gb28181_heartbeat_count_);

        com.gb28181.ntsignalling.Device gb_device = new com.gb28181.ntsignalling.Device("34020000001380000001", "安卓测试设备", Build.MANUFACTURER, Build.MODEL,
                    "宇宙","火星1","火星", true);

        getLocation(this);
        gb_device.setLongitude(mLongitude);
        gb_device.setLatitude(mLatitude);
        gb28181_agent_.addDevice(gb_device);

        if (!gb28181_agent_.initialize()) {
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.initialize failed.");
            return  false;
        }

        return true;
    }

心跳(KeepAlive)

KeepAlive以MESSAGE的形式传递,异常处理如下:
    @Override
    public void ntsOnHeartBeatException(int exceptionCount,  String lastExceptionInfo) {
        Log.e(TAG, "ntsOnHeartBeatException heart beat timeout count reached, count:" + exceptionCount+
                ", exception info:" + (lastExceptionInfo!=null?lastExceptionInfo:""));

        // 10毫秒后,停止信令, 然后重启
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "gb28281_heart_beart_timeout");
                stopGB28181Stream();
                destoryRTPSender();

                if (gb28181_agent_ != null) {
                    Log.i(TAG, "gb28281_heart_beart_timeout sip stop");
                    gb28181_agent_.stop();

                    Log.i(TAG, "gb28281_heart_beart_timeout sip start");
                    gb28181_agent_.start();
                }
            }

        },10);
    }

Invite处理

假定整个信令交互流程顺利,Android设备端完成Register、Catalog、KeepAlive消息处理后,平台端发过来Invite请求并携带SDP消息体。

Android设备端可获取到比如deviceid, tcp/udp传输模式、rtp端口,address类型等,并构建200 OK,携带相关的音视频信息。

    @Override
    public void ntsOnInvitePlay(String deviceId, InvitePlaySessionDescription session_des) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG,"ntsInviteReceived, device_id:" +device_id_+", is_tcp:" + session_des_.isRTPOverTCP()
                        + " rtp_port:" + session_des_.getMediaPort() + " ssrc:" + session_des_.getSSRC()
                        + " address_type:" + session_des_.getAddressType() + " address:" + session_des_.getAddress());

                // 可以先给信令服务器发送临时振铃响应
                //sip_stack_android.respondPlayInvite(180, device_id_);

                long rtp_sender_handle = libPublisher.CreateRTPSender(0);
                if ( rtp_sender_handle == 0 ) {
                    gb28181_agent_.respondPlayInvite(488, device_id_);
                    Log.i(TAG, "ntsInviteReceived CreateRTPSender failed, response 488, device_id:" + device_id_);
                    return;
                }

                gb28181_rtp_payload_type_ = session_des_.getPSRtpMapAttribute().getPayloadType();

                libPublisher.SetRTPSenderTransportProtocol(rtp_sender_handle, session_des_.isRTPOverUDP()?0:1);
                libPublisher.SetRTPSenderIPAddressType(rtp_sender_handle, session_des_.isIPv4()?0:1);
                libPublisher.SetRTPSenderLocalPort(rtp_sender_handle, 0);
                libPublisher.SetRTPSenderSSRC(rtp_sender_handle, session_des_.getSSRC());
                libPublisher.SetRTPSenderSocketSendBuffer(rtp_sender_handle, 2*1024*1024); // 设置到2M
                libPublisher.SetRTPSenderClockRate(rtp_sender_handle, session_des_.getPSRtpMapAttribute().getClockRate());
                libPublisher.SetRTPSenderDestination(rtp_sender_handle, session_des_.getAddress(), session_des_.getMediaPort());

                if ( libPublisher.InitRTPSender(rtp_sender_handle) != 0 ) {
                    gb28181_agent_.respondPlayInvite(488, device_id_);
                    libPublisher.DestoryRTPSender(rtp_sender_handle);
                    return;
                }

                int local_port = libPublisher.GetRTPSenderLocalPort(rtp_sender_handle);
                if (local_port == 0) {
                    gb28181_agent_.respondPlayInvite(488, device_id_);
                    libPublisher.DestoryRTPSender(rtp_sender_handle);
                    return;
                }

                Log.i(TAG,"get local_port:" + local_port);

                String local_ip_addr = IPAddrUtils.getIpAddress(myContext);
                gb28181_agent_.respondPlayInviteOK(device_id_,local_ip_addr, local_port);

                gb28181_rtp_sender_handle_ = rtp_sender_handle;
            }

            private String device_id_;
            private InvitePlaySessionDescription session_des_;

            public Runnable set(String device_id, InvitePlaySessionDescription session_des) {
                this.device_id_ = device_id;
                this.session_des_ = session_des;
                return this;
            }
        }.set(deviceId, session_des),0);
    }

Ack确认

平台端发送Ack确认,设备端收到Ack后,开始发送音视频数据。

    @Override
    public void ntsOnAckPlay(String deviceId) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG,"ntsOnACKPlay, device_id:" +device_id_);

                if (!isRecording && !isRTSPPublisherRunning && !isPushingRtsp && !isPushingRtmp) {
                    InitAndSetConfig();
                }

                libPublisher.SetGB28181RTPSender(publisherHandle, gb28181_rtp_sender_handle_, gb28181_rtp_payload_type_);
                int startRet = libPublisher.StartGB28181MediaStream(publisherHandle);
                if (startRet != 0) {

                    if (!isRecording && !isRTSPPublisherRunning && !isPushingRtmp && !isPushingRtsp) {
                        if (publisherHandle != 0) {
                            libPublisher.SmartPublisherClose(publisherHandle);
                            publisherHandle = 0;
                        }
                    }

                    destoryRTPSender();

                    Log.e(TAG, "Failed to start GB28181 service..");
                    return;
                }

                if (!isRecording && !isRTSPPublisherRunning && !isPushingRtsp && !isPushingRtmp) {
                    if (pushType == 0 || pushType == 1) {
                        CheckInitAudioRecorder();    //enable pure video publisher..
                    }
                }

                isGB28181StreamRunning = true;
            }

            private String device_id_;

            public Runnable set(String device_id) {
                this.device_id_ = device_id;
                return this;
            }

        }.set(deviceId),0);
    }

BYE

如果客户端需要断开Invite会话,则会发送BYE,客户端返回200 OK。

    @Override
    public void ntsOnByePlay(String deviceId)
    {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "ntsOnByePlay, stop GB28181 media stream, deviceId=" + device_id_);

                stopGB28181Stream();
                destoryRTPSender();
            }

            private String device_id_;

            public Runnable set(String device_id) {
                this.device_id_ = device_id;
                return this;
            }

        }.set(deviceId),0);
    }

注销

客户端向服务器发送 Register命令消息,消息中的 Expire字段设置为0即是注销。
 

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

如何快速实现Android平台前端设备接入能力 的相关文章

  • H.264(H264)视频文件的制作

    一 准备工作 1 下载并安装优酷客户端 2 下载ffmpeg可执行文件 解压可用 不需要下载源码自己编译 ffmpeg可执行文件下载链接 http download csdn net detail caoshangpa 9492758 二
  • 基于RTMP实现Linux

    背景 Windows操作系统自问世以来 以其简单易用的图形化界面操作受到大众追捧 为计算机的普及 科技的发展做出了不可磨灭的功绩 也慢慢的成为人们最依赖的操作系统 在中国 90 以上的办公环境都是Windows 学校和各种培训班的培训内容也
  • 网络流媒体(七)———RTSP

    RTSP协议介绍 RTSP协议的一些分析 一 一些字符串函数的使用 RTSP协议的一些分析 二 printf类似函数 sscanf以及log保存到内存中 printf输入重定位 1 简介 DSP产生的媒体流需要通过网络传送到客户端 如图1
  • 如何开发一个音视频播放器(ffmpeg3.2+sdl2.0)

    如何开发一个音视频播放器 ffmpeg3 2 SDL2 0 前言 创建一个音视频播放器的步骤 一 播放音频 二 播放视频 三 音视频同步 源码分析 一 正式开始前的准备工作 二 配置音视频基本参数 获取文件基本信息 初始化音频参数 初始化视
  • Windows平台实现Unity下窗体

    技术背景 随着Unity3D的应用范围越来越广 越来越多的行业开始基于Unity3D开发产品 如传统行业中虚拟仿真教育 航空工业 室内设计 城市规划 工业仿真等领域 基于此 好多开发者苦于在Unity环境下 没有低延迟的推拉流解决方案 前几
  • RTSP和RTP、RTCP协议介绍

    一 RTSP 1 简介 RTSP Real Time Stream Protocol 协议是一个基于文本的多媒体播放控制协议 属于应用层 RTSP以客户端方式工作 对流媒体提供播放 暂停 后退 前进等操作 它主要用来控制具有实时特性的数据的
  • Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?

    技术背景 好多开发者 问我们最多的问题是 为什么要设计轻量级RTSP服务 轻量级RTSP服务 和RTSP服务有什么区别 针对这个问题 我们的回答是 轻量级RTSP服务解决的核心痛点是避免用户或者开发者单独部署RTSP服务或者RTMP服务 R
  • 国家开源软件资源库

    http yp oss org cn software show cat php cat id 5 基本信息 成熟度 Dimdim 2009 05 19 1 2 3 4 5 6 7
  • 交换机端口镜像及Wireshake抓包

    1 首先配置交换机 先将交换机断开与其他交换机连接的网线 保证电脑端只与这一个交换机通信 2 之前配置过交换机的 如果记得IP 可以直接通过交换机的IP进行登录 3 如果忘记交换机的IP 则可以重置 交换机上有一个reset按键 重置后 我
  • Android平台GB28181设备接入端如何实时更新经纬度实现国标平台侧电子地图位置标注

    技术背景 我们在做GB28181设备接入端的时候 其中有个功能 不难但非常重要 那就是GB28181实时位置的订阅 mobileposition subscribe 和上报 notify 特别是执法记录仪 智能安全帽 车载终端等场景下 现场
  • 【无标题】ZLM和wvp配置

    ZLM配置 wvp对zlm要求的配置只有一个 具体值随便设置 以9080为例 http port 9080 wvp配置 确保media gt ip为zlm的IP media gt port为刚才配置的9080 其他wvp配置参考配置说明按需
  • FFmpeg学习(11)——视频转码之-crf参数详解

    什么是固定码率因子crf Constant Rate Factor 固定码率因子 CRF 是 x264 和 x265 编码器的默认质量 和码率控制 设置 取值范围是 0 到 51 这其中越低的值 结果质量越好 同时输出文件越大 越高的值意味
  • GB/T28181-2022针对H.265、AAC的说明和技术实现

    GB T28181 2022规范说明 GB T28181 2022相对来GB T28181 2016针对H 265 AAC的更新如下 更改了 联网系统通信协议结构图 媒体流通道增加了 H 265 G 722 1 AAC 见 4 3 1 20
  • GB/T28181-2016传输要求和Android平台设备接入技术实现

    相关协议规范 GB T28181 2016公共安全视频监控联网系统 信息传输 交换 控制技术要求相关的传输要求如下 5 1 网络传输协议要求 联网系统网络层应支持IP协议 传输层应支持 TCP和 UDP协议 5 2 媒体传输协议要求 视音频
  • Android平台一对一音视频通话方案对比:WebRTC VS RTMP VS RTSP

    一对一音视频通话使用场景 一对一音视频通话都需要稳定 清晰和流畅 以确保良好的用户体验 常用的使用场景如下 社交应用 社交应用是一种常见的使用场景 用户可以通过音视频通话进行面对面的交流 在线教育 老师和学生可以通过音视频通话功能进行实时互
  • 深入理解Google Cast(三)探寻原理

    如何开发一个receiver application 先来简单说一下这个话题 Receiver本质就是一个网页 由html CSS和jacascript开发 如果要自定义receiver application 需要在 Google Cas
  • 视频编码格式发展史

    1 编码标准之战 想预测未来 就回顾历史 先来看看H 264这些编码的从标准化到现在普及的过程 人们一直在想尽办法提高视频编码的效率 让它在尽可能小的体积内提供最好的画面质量 从而满足人们对于视频传输 存储的需求 长期以来 视频编码标准主要
  • live555 流媒体开源库

    live555对每一个从事过流媒体开发的从业者而言 都不曾陌生 就像每一个从事音视频行业的从业者而言 ffmpeg也不曾陌生 随着行业需求的发展 live555也是越见强大 因前几天帮朋友项目查找问题 重拾live555 没想到时隔10年
  • [技术分享]Android平台实时音视频录像模块设计之道

    实现背景 录像有什么难的 无非就是数据过来 编码保存mp4而已 这可能是好多开发者在做录像模块的时候的思考输出 是的 确实不难 但是做好 或者和其他模块有非常好的逻辑配合 确实不容易 好多开发者希望聊聊录像模块 实际上录像这块 需求层面的东
  • GB28181状态信息报送解读及Android端国标设备接入技术实现

    今天主要聊聊GB T28181状态信息报送这块 先回顾下协议规范相关细节 然后再针对代码实现 做个简单的说明 状态消息报送基本要求 当源设备 包括网关 SIP设备 SIP客户端或联网系统 发现工作异常时 应立即向本 SIP监控域 的SIP服

随机推荐

  • Spark实时数据流分析与可视化:实战指南【上进小菜猪大数据系列】

    上进小菜猪 沈工大软件工程专业 爱好敲代码 持续输出干货 本文介绍了如何利用Apache Spark技术栈进行实时数据流分析 并通过可视化技术将分析结果实时展示 我们将使用Spark Streaming进行数据流处理 结合常见的数据处理和可
  • [每日习题]年终奖(动态规划) 迷宫问题(DFS+回溯)——牛客习题

    hello 大家好 这里是bang bang 本篇记录2道牛客习题 年终奖 简单 迷宫问题 中等 如有需要 希望能有所帮助 目录 1 年终奖 2 迷宫问题 1 年终奖 年终奖 牛客题霸 牛客网 nowcoder com 描述 小东所在公司要
  • auto_copy.py

    coding utf 8 author DT date 20190118 import os import os path import shutil import time datetime def del file path for f
  • k8s1.23.15版本二进制部署/扩容及高可用架构详解

    前言 众所周知 kubernetes在2020年的1 20版本时就提出要移除docker 这次官方消息表明在1 24版本中彻底移除了dockershim 即移除docker 但是在1 24之前的版本中还是可以正常使用docker的 考虑到可
  • kali虚拟机安装出现无法定位软件包,无法找到任何软件包的解决方法

    问题如下 出现这种安装问题 原因是长时间未打开kali虚拟机 解决方法 输入命令 sudo apt update 注 在root或非root用户下都可以 然后继续安装就可以了
  • 【NLP】第 8 章:使用基于注意力的神经网络构建聊天机器人

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • python爬虫正则表达式

    博主简介 博主是一个大二学生 主攻人工智能领域研究 感谢缘分让我们在CSDN相遇 博主致力于在这里分享关于人工智能 C python 爬虫等方面的知识分享 如果有需要的小伙伴 可以关注博主 博主会继续更新的 如果有错误之处 大家可以指正 专
  • 蓝桥杯常用模板

    文章目录 蓝桥杯算法模板 最大公约数 GCD 拓展欧几里得 EXGCD 最小公倍数 LCM 多个数的GCD和LCM 判断闰年 整数快速幂 用于快速求幂 快速幂取模 快速乘 O logn 对于一个大数最后结果只需要部分结尾数字 则在过程中取模
  • (十一)javascript内置对象之Math内置对象

    内置对象就是 js 语言自带的一些对象 这些对象可供开发者使用 这些内置对象提供了一些常用的或是最基本而必要的一些功能 内置对象最大的优点是帮助我们快速开发 javascript提供的常用的内置对象有 Math Date Array Str
  • matlab plot 连续曲线,Matlab怎么画出连续的曲线?

    因为你是在for循环中画的 所以循环一次算出一个点 matlab就画一个点 你可以在循环完毕后在使用plot画图 clear all clc i 1 脚标i L1 1 L2 1 L 1 C1 1 C2 1 C 1 m 0 5 w 50 a
  • C++期末复习运算符混淆---打妖怪

    7 2 打妖怪 低级错误 运算符混淆问题 实验1 第二题 话说孙大圣保唐僧西天取经 路上遇到一妖怪 妖怪共有 v 滴血 大圣每打一棒就能使妖怪失去 h 滴血 妖怪一旦没血就会立即死去 大圣打 n 棒刚好将妖怪打死 请编写程序 输入 v 和
  • 代码题: 看代码说结果, 事件循环 + async 函数的

    1 基本的 async await 和事件循环 console log 1 async function asyncFunc console log 2 await Promise resolve console log 3 asyncFu
  • Simulated Binary Crossover(SBX)的学习

    最近在做作业遇到一个Dejong s fifth function的multi modal的问题 用传统的GA方法尝试了很多次 的确没办法搞定 随机很多次也不一定在global optimum的地方得到一次解 前几天去导师家里的路上谈到这个
  • 什么是 MATLAB(矩阵实验室)?工作、功能和应用

    MATLAB 被 MathWorks 定义为专有软件应用程序和编程语言 可促进复杂的数据分析任务 例如算法实施 与其他应用程序交互以及操作数据矩阵 本文介绍了 MATLAB 的用途 其关键概念以及 2022 年的用例 什么是 MATLAB
  • 【解决】TypeError: this.$refs.treeRefs.xxx is not a function

    问题 使用refs触发子组件内方法时报 TypeError this refs treeRefs xxx is not a function 解决 经查看 发现子组件被放在了v for循环体内 示例代码如下
  • 虚拟机上部署K8S集群

    虚拟机上部署K8S集群 安装VM Ware 安装Docker 安装K8S集群 安装kubeadm 使用kubeadm引导集群 安装VM Ware 参考 http www taodudu cc news show 2034573 html a
  • 推荐系统:Wide & Deep模型解析

    1 Wide Deep模型介绍 经典推荐深度模型 Wide Deep 对应的论文 Wide Deep Learning for Recommender Systems 链接 arxiv Wide Deep的模型架构如下图所示 可以看到Wid
  • 运维技能风向标

    运维介绍 运维是一个融合多学科 网络 系统 开发 安全 应用架构 存储等 的综合性技术岗位 从最初的网络管理 网管 发展到现在的系统运维工程师 网络运维工程师 安全运维工程师 运维开发工程师等 可以看出 运维的分工一直在细化 并且对综合技能
  • Element Plus for Vue 3 入门教程

    本文首发 Element Plus for Vue 3 入门教程 Element Plus 有那些升级 Element Plus 与 Element UI 是什么关系 老 Element 项目是否可以平滑升级到 Vue 3 Element
  • 如何快速实现Android平台前端设备接入能力

    技术背景 SIP 会话初始化协议 是在 IP网络上进行多媒体通信的应用层控制协议 以几种RFC的形式提供 其中最重要的是包含核心协议规范的RFC3261 该协议用于创建 修改和终止与一个或多个参与者的会话 通过会话 我们了解了一组进行通信的