Android平台RTMP多实例推送的几种情况探讨

好多开发者提到,如何实现Android平台,多实例推送,多实例推送,有几种理解:

  1. 多路编码,多个实例分别推送到不同的RTMP URL(如Android采集板卡同时接2路出去);
  2. 同一路编码,多个实例分别推送到不同的RTMP URL(如推送到内网、外网不同的RTMP服务器);
  3. 部分路编码、部分路对接编码后的H.264/AAC数据,多个实例分别推送到不同的RTMP URL(混合推)。

目前,市面上的大多设计,都不够灵活,以下以“Android回调编码后的音视频数据”为例,推送一路原始的编码后的RTMP数据出去,然后,编码后的数据,回调到上层,再启动一个新的Publisher实例,推到新的RTMP地址(当然只是业务展示,实际可用于对接第三方系统,如GB28181或其他服务):

具体流程如下:

  1. 设置音视频callback

对应接口:

	/*** Set Audio Encoded Data Callback.** @param audio_encoded_data_callback: Audio Encoded Data Callback.** @return {0} if successful*/public native int SmartPublisherSetAudioEncodedDataCallback(long handle, Object audio_encoded_data_callback);/*** Set Video Encoded Data Callback.** @param video_encoded_data_callback: Video Encoded Data Callback.** @return {0} if successful*/public native int SmartPublisherSetVideoEncodedDataCallback(long handle, Object video_encoded_data_callback);
设置回调:libPublisher.SmartPublisherSetAudioEncodedDataCallback(publisherHandle, new PublisherAudioEncodedDataCallback());libPublisher.SmartPublisherSetVideoEncodedDataCallback(publisherHandle, new PublisherVideoEncodedDataCallback());
  1. 实现 PublisherAudioEncodedDataCallback 和 PublisherVideoEncodedDataCallback:
    class PublisherAudioEncodedDataCallback implements NTAudioDataCallback{private int audio_buffer_size = 0;private int param_info_size = 0;private ByteBuffer audio_buffer_ = null;private ByteBuffer parameter_info_ = null;@Overridepublic ByteBuffer getAudioByteBuffer(int size){//Log.i("getAudioByteBuffer", "size: " + size);if( size < 1 ){return null;}if ( size <= audio_buffer_size && audio_buffer_ != null ){return audio_buffer_;}audio_buffer_size = size + 512;audio_buffer_size = (audio_buffer_size+0xf) & (~0xf);audio_buffer_ = ByteBuffer.allocateDirect(audio_buffer_size);// Log.i("getAudioByteBuffer", "size: " + size + " buffer_size:" + audio_buffer_size);return audio_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 = size + 32;param_info_size = (param_info_size+0xf) & (~0xf);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 + ",chn: " + channel + ", parameter_info_size:" + parameter_info_size);if ( audio_buffer_ == null)return;audio_buffer_.rewind();if ( ret == 0 && publisherHandle2 != 0 ) {libPublisher.SmartPublisherPostAudioEncodedData(publisherHandle2, audio_codec_id, audio_buffer_, sample_size, is_key_frame, timestamp, parameter_info_, parameter_info_size);}}}class PublisherVideoEncodedDataCallback implements NTVideoDataCallback{private int video_buffer_size = 0;private ByteBuffer video_buffer_ = null;@Overridepublic ByteBuffer getVideoByteBuffer(int size){//Log.i("getVideoByteBuffer", "size: " + size);if( size < 1 ){return null;}if ( size <= video_buffer_size &&  video_buffer_ != null ){return  video_buffer_;}video_buffer_size = size + 1024;video_buffer_size = (video_buffer_size+0xf) & (~0xf);video_buffer_ = ByteBuffer.allocateDirect(video_buffer_size);// Log.i("getVideoByteBuffer", "size: " + size + " buffer_size:" + video_buffer_size);return video_buffer_;}public void onVideoDataCallback(int ret, int video_codec_id, int sample_size, int is_key_frame, long timestamp, int width, int height, long presentation_timestamp){Log.i("onVideoDataCallback", "ret: " + ret + ", video_codec_id: " + video_codec_id + ", sample_size: " + sample_size + ", is_key_frame: "+ is_key_frame +  ", timestamp: " + timestamp +",width: " + width + ", height:" + height + ",presentation_timestamp:" + presentation_timestamp);if ( video_buffer_ == null)return;video_buffer_.rewind();if ( ret == 0 && publisherHandle2 !=0 ) {libPublisher.SmartPublisherPostVideoEncodedData(publisherHandle2, video_codec_id, video_buffer_, sample_size, is_key_frame, timestamp, presentation_timestamp);}}}
  1. 提供开始回调数据和停止回调数据接口:
	/*** Start output Encoded Data(用于编码后的音视频数据回调)** @return {0} if successful*/public native int SmartPublisherStartOutputEncodedData(long handle);/***  Stop output Encoded Data** @return {0} if successful*/public native int SmartPublisherStopOutputEncodedData(long handle);
  1. 上层demo调用实例:
    class ButtonEncodedDataCallbackListener implements OnClickListener {public void onClick(View v) {if (isEncodedDatacallbackRunning) {stopEncodedDataCallback();if (!isPushing && !isRTSPPublisherRunning && !isRecording) {ConfigControlEnable(true);}btnEncodedDataCallback.setText("启动编码数据回调");isEncodedDatacallbackRunning = false;if (publisherHandle2 != 0) {libPublisher.SmartPublisherStopPublisher(publisherHandle2);libPublisher.SmartPublisherClose(publisherHandle2);publisherHandle2 = 0;}return;}Log.i(TAG, "onClick start encoded data callback..");if (libPublisher == null)return;if (!isPushing && !isRTSPPublisherRunning && !isRecording) {InitAndSetConfig();}libPublisher.SmartPublisherSetAudioEncodedDataCallback(publisherHandle, new PublisherAudioEncodedDataCallback());libPublisher.SmartPublisherSetVideoEncodedDataCallback(publisherHandle, new PublisherVideoEncodedDataCallback());int startRet = libPublisher.SmartPublisherStartOutputEncodedData(publisherHandle);if (startRet != 0) {isEncodedDatacallbackRunning = false;Log.e(TAG, "Failed to start encoded data callback.");return;}if (!isPushing && !isRTSPPublisherRunning && !isRecording) {if (pushType == 0 || pushType == 1) {CheckInitAudioRecorder();    //enable pure video publisher..}ConfigControlEnable(false);}btnEncodedDataCallback.setText("停止编码数据回调");isEncodedDatacallbackRunning = true;int audio_opt = 2;int video_opt = 2;publisherHandle2 = libPublisher.SmartPublisherOpen(myContext, audio_opt, video_opt,videoWidth, videoHeight);if (publisherHandle2 == 0) {Log.e(TAG, "sdk open failed!");return;}String relayUrl = "rtmp://player.daniulive.com:1935/hls/stream8888";libPublisher.SmartPublisherSetURL(publisherHandle2, relayUrl);libPublisher.SmartPublisherStartPublisher(publisherHandle2);}};//停止编码后数据回调private void stopEncodedDataCallback() {if(!isEncodedDatacallbackRunning){return;}if (!isPushing && !isRTSPPublisherRunning && !isRecording) {if (audioRecord_ != null) {Log.i(TAG, "stopRecorder, call audioRecord_.StopRecording..");audioRecord_.Stop();if (audioRecordCallback_ != null) {audioRecord_.RemoveCallback(audioRecordCallback_);audioRecordCallback_ = null;}audioRecord_ = null;}}if (libPublisher != null) {libPublisher.SmartPublisherStopOutputEncodedData(publisherHandle);}if (!isPushing && !isRTSPPublisherRunning && !isRecording) {if (publisherHandle != 0) {if (libPublisher != null) {libPublisher.SmartPublisherClose(publisherHandle);publisherHandle = 0;}}}}

以上demo为了便于演示多实例效果,另启了个新的推送实例(对应新的publisherHandle),音视频编码后的数据,通过新的实例,调用编码后的音视频数据接口,继续推RTMP出去,从而实现多实例推送目的。

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

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

相关文章

雨林木风win11 64位全新专业版系统v2021.08

雨林木风win11 64位全新专业版系统v2021.08是目前非常火热的电脑操作系统&#xff0c;系统运行速度非常的快速&#xff0c;拥有稳定、安全、兼容性强等特点&#xff0c;多样化的服务可供你的使用&#xff0c;支持在线的升级&#xff0c;非常的便捷&#xff0c;可以提高系统的性…

面向内网无纸化会议/智慧教室/实时同屏,组播还是RTMP?

一、背景 为满足内网无纸化/电子教室等内网超低延迟需求&#xff0c;避免让用户配置单独的服务器&#xff0c;我们研发了轻量级RTSP服务开发包。 单播不再赘述&#xff0c;这里重点介绍下我们的组播技术方案&#xff1a; 组播解决的主要痛点是服务器部署和带宽占用问题&…

打印更无缝:微软改善Win11中通用打印体验

微软昨日透露&#xff0c;将会在 Windows 11 系统中改进打印体验。从下面的截图中可以看到&#xff0c;用户可以直接在设置应用中添加打印机。对于使用通用打印机驱动的打印机&#xff0c;微软增加了为打印作业添加密码的功能。 打印更无缝&#xff1a;微软改善Win11中通用打印…

Windows平台如何快速实现RTSP/RTMP直播播放

前段时间&#xff0c;我们在 https://blog.csdn.net/renhui1112/article/details/104143794 提到“RTSP播放器开发过程中需要考虑哪些关键因素”&#xff0c;本次主要介绍&#xff0c;如何调用SDK实现RTSP/RTMP播放能力。 本文以调用大牛直播SDK为例&#xff1a; demo说明 SD…

Windows平台RTSP播放器/RTMP播放器设计需要考虑的几个点

我们在实现Windows平台RTSP播放器或RTMP播放器的时候&#xff0c;需要考虑的点很多&#xff0c;比如多实例设计、多绘制模式兼容、软硬解码支持、快照、RTSP下TCP-UDP自动切换等&#xff0c;以下就其中几个方面&#xff0c;做个大概的探讨。 1. 视频绘制模式 我们在实现Windo…

网易邮箱大师如何定时发送 定时发送邮件方法步骤详解

网易邮箱大师是我们日常使用邮箱的最佳软件&#xff0c;不仅能批量登录邮件&#xff0c;还能定时发送邮件&#xff0c;可谓功能齐全&#xff0c;很多小伙伴不知道如何定时发送邮件&#xff0c;那么接下来小编说的这篇文章肯定会对你有帮助。 操作步骤如下&#xff1a; 1、打开…

Windows平台下如何实现Unity3D下的RTMP推送

好多开发者苦于很难在unity3d下实现RTMP直播推送&#xff0c;本次以大牛直播SDK&#xff08;Github&#xff09;的Windows平台RTMP推送模块&#xff08;以推摄像头为例&#xff0c;如需推屏幕数据&#xff0c;设置相关参数即可&#xff09;为例&#xff0c;介绍下unity3d的RTMP…

Android平台如何实现屏幕数据采集并推送至RTMP服务器

随着无纸化、智慧教室等场景的普及&#xff0c;好多企业或者开发者开始寻求更高效稳定低延迟的RTMP同屏方案&#xff0c;本文以大牛直播SDK(Github)的同屏demo&#xff08;对应工程&#xff1a;SmartServicePublisherV2&#xff09;为例&#xff0c;介绍下如何采集编码推送RTMP…

网易邮箱大师如何注册邮箱 注册邮箱方法步骤介绍

网易邮箱大师是款高效强大的全平台邮箱客户端&#xff0c;支持所有邮箱登录&#xff0c;功能强大&#xff0c;一个PC端就能登录多个邮箱&#xff0c;很多小伙伴不知道如何注册登录邮箱&#xff0c;那么就跟着小编一起来看看如何操作吧。 操作步骤如下&#xff1a; 1、打开网易…

D3D还是GDI? Windows平台播放RTSP或RTMP渲染模式比较

先说结论&#xff0c;Windows平台播放渲染这块&#xff0c;支持D3D的前提下&#xff0c;优先D3D&#xff0c;如果检测到不支持D3D&#xff0c;数据回调上来&#xff0c;GDI模式绘制。 相比GDI模式&#xff0c;D3D绘制更细腻&#xff0c;绘制效率更高&#xff0c;CPU占用低&…

Android投屏(屏幕共享)设计需要考虑的关键因素

许多开发者&#xff0c;在做智慧教室同屏、会议同屏之类的方案时&#xff0c;基于Andriod平台的采集&#xff0c;往往遇到各种各样的问题&#xff0c;以下就几个点&#xff0c;抛砖引玉&#xff1a; 1. 内网环境下&#xff0c;组播还是RTMP&#xff1f; 回答&#xff1a;这个…

微信公众号怎么给微店设置运费

微信小店想要设置运费&#xff0c;该怎么设置呢?今天我们就来看看使用微信公众号设置微店运费的教程。 1、在电脑登录你的微信公众号服务号&#xff0c;确保已经事先开通了微信小店功能 微信公众号怎么给微店设置运费? 2、点击左侧导航栏的微信小店&#xff0c;进去后点击…

RTSP/RTMP播放端录像不可忽视的几个设计要点

很多开发者提到&#xff0c;拉取的摄像机&#xff08;一般RTSP流&#xff09;或RTMP流&#xff0c;如果需要录制&#xff0c;需要考虑哪些因素&#xff0c;本文以大牛直播SDK的Windows平台拉流端录像为例&#xff08;github&#xff09;&#xff0c;做个简单的介绍&#xff1a;…

海康摄像机rtsp地址格式(官方最新版)

★目前海康录像机、网络摄像机&#xff0c;网络球机的RTSP单播取流格式如下&#xff08;车载录像机不支持RTSP取流&#xff09;&#xff1a; rtsp://用户名:密码IP:554/Streaming/Channels/101 →录像机示例&#xff1a; 取第1个通道的主码流预览 rtsp://admin:hik1234510.…

QQ邮箱怎么发送文件夹 怎样在QQ邮箱里发送压缩文件夹

有很多用户想要知道怎么样才能通过QQ邮箱来发送自己的一些文件压缩包&#xff0c;应该怎么操作呢?不要慌&#xff0c;现在小编就给大家分享一下&#xff0c;下面一起来学习操作步骤吧! 其实&#xff0c;无论何种邮箱都无法发送文件夹&#xff0c;都只能对文件进行操作。如果文…

时光手帐怎么修改作品 时光手帐修改作品封面方法

对于自己在时光手账Pro中的手账本封面是可以随时更改的。那么&#xff0c;怎么在时光手账Pro中更改自己手账封面?下面我使用苹果手机(安卓端操作方法一致)来分享一下具体的操作流程。 首先打开手机&#xff0c;点击进入时光手账Pro。 时光手帐怎么修改作品 时光手帐修改作品…

几款优秀的点播、RTSP/RTMP直播播放器介绍

1.ijkplayer 项目地址&#xff1a; https://github.com/Bilibili/ijkplayer 介绍&#xff1a;Ijkplayer 是Bilibili发布的基于 FFplay 的轻量级 Android/iOS 视频播放器。实现了跨平台功能&#xff0c;API 易于集成&#xff1b;编译配置可裁剪&#xff0c;方便控制安装包大小&…

Android平台RTMP推流或轻量级RTSP服务(摄像头或同屏)编码前数据接入类型总结

很多开发者在做Android平台RTMP推流或轻量级RTSP服务&#xff08;摄像头或同屏&#xff09;时&#xff0c;总感觉接口不够用&#xff0c;以大牛直播SDK为例 (Github) 我们来总结下&#xff0c;我们常规需要支持的编码前音视频数据有哪些类型&#xff1a; 1. Android摄像头前后…

作业帮口算批改怎么开 作业帮口算批改如何用

作业帮口算批改功能怎么用?作业帮最近全新改版的消息传的很火&#xff0c;新增了口算批改的功能&#xff0c;很吸引人。但是还有很多用户不是很清楚作业帮口算批改功能怎么用&#xff0c;下面是小编整理的关于作业帮口算批改功能怎么用的相关资讯&#xff0c;快来看看吧! 作业…

RTSP播放器或RTMP播放器常用的事件回调设计

很多开发者在开发RTSP或RTMP播放器的时候&#xff0c;不晓得哪些event回调事件是有意义的&#xff0c;针对此&#xff0c;我们以大牛直播SDK&#xff08;github&#xff09;的Android平台RTSP/RTMP直播播放端为例&#xff0c;简单介绍下常用的event id&#xff0c;总的来说&…