技術(shù)背景
早在2015年,我們發(fā)布了RTMP直播推送模塊,那時(shí)候音視頻直播這塊場(chǎng)景需求,還不像現(xiàn)在這么普遍,我們做這塊的初衷,主要是為了實(shí)現(xiàn)移動(dòng)單兵應(yīng)急指揮系統(tǒng)的低延遲音視頻數(shù)據(jù)傳輸。好多開發(fā)者可能會(huì)疑惑,走RTMP怎么可能低延遲?網(wǎng)上看到的RTMP推拉流延遲,總歸要2-3秒起,如果是自己實(shí)現(xiàn)框架,RTMP推拉流邏輯自己實(shí)現(xiàn)的話,延遲確實(shí)可以控制在毫秒級(jí),這個(gè)已無(wú)需贅述。
隨著無(wú)紙化會(huì)議、智慧教室、智能化硬件產(chǎn)品的普及,RTMP的技術(shù)方案發(fā)展一度非常好,有些無(wú)人機(jī)或智能機(jī)器人,都可以自帶推送RTMP流數(shù)據(jù),配合大牛直播SDK的RTMP低延遲播放器模塊,可以實(shí)現(xiàn)毫秒級(jí)的技術(shù)體驗(yàn)。
那為什么后面要做GB28181設(shè)備接入模塊呢?我們推出的Android平臺(tái)GB28181接入模塊的目的,可實(shí)現(xiàn)不具備國(guó)標(biāo)音視頻能力的 Android終端,通過(guò)平臺(tái)注冊(cè)接入到現(xiàn)有的GB/T28181—2016服務(wù),可用于如執(zhí)法記錄儀、智能安全帽、智能監(jiān)控、智慧零售、智慧教育、遠(yuǎn)程辦公、明廚亮灶、智慧交通、智慧工地、雪亮工程、平安鄉(xiāng)村、生產(chǎn)運(yùn)輸、車載終端等場(chǎng)景。
GB28181規(guī)范,信令和媒體數(shù)據(jù)分離,可以訂閱實(shí)時(shí)位置信息、云臺(tái)控制、對(duì)焦等,數(shù)據(jù)傳輸走TCP或UDP,實(shí)現(xiàn)按需查看和語(yǔ)音廣播、語(yǔ)音對(duì)講,更成體系化,也更適合有交互的場(chǎng)景。
我們實(shí)現(xiàn)demo的時(shí)候,RTMP推送和GB28181都放到一起了,也就是說(shuō),可以同時(shí)使用RTMP推送和GB28181設(shè)備接入,也可以單獨(dú)使用。?
技術(shù)對(duì)比
RTMP推送
?RTMP采用的是TCP傳輸,采用全自研框架,易于擴(kuò)展,自適應(yīng)算法讓延遲更低、采集編碼傳輸效率更高。延遲配合我們的播放器,輕松實(shí)現(xiàn)毫秒級(jí)延遲。
功能設(shè)計(jì)如下:
- 音頻編碼:AAC/SPEEX;
- 視頻編碼:H.264、H.265(RTMP擴(kuò)展H.265);
- 推流協(xié)議:RTMP;
- [音視頻]支持純音頻/純視頻/音視頻推送;
- [攝像頭]支持采集過(guò)程中,前后攝像頭實(shí)時(shí)切換;
- 支持幀率、關(guān)鍵幀間隔(GOP)、碼率(bit-rate)設(shè)置;
- 支持RTMP推送 live|record模式設(shè)置;
- 支持前置攝像頭鏡像設(shè)置;
- 支持軟編碼、特定機(jī)型硬編碼;
- 支持橫屏、豎屏推送;
- 支持Android屏幕采集推送;
- 支持自建標(biāo)準(zhǔn)RTMP服務(wù)器或CDN;
- 支持?jǐn)嗑W(wǎng)自動(dòng)重連、網(wǎng)絡(luò)狀態(tài)回調(diào);
- 支持動(dòng)態(tài)水?。ㄎ淖?、圖片);
- 支持降噪處理、自動(dòng)增益控制;
- 支持實(shí)時(shí)快照;
- 支持實(shí)時(shí)靜音和實(shí)時(shí)音量調(diào)節(jié);
- 支持錄像功能擴(kuò)展(錄制MP4文件);
- 支持Android 5.1及以上版本。
接口調(diào)用如下:
class ButtonStartPushListener implements View.OnClickListener {
public void onClick(View v) {
if (isPushingRtmp) {
stopPush();
btnRTMPPusher.setText("推送RTMP");
return;
}
Log.i(TAG, "onClick start push rtmp..");
if (libPublisher == null)
return;
if (!isRTSPPublisherRunning && !isGB28181StreamRunning && !isRecording) {
InitAndSetConfig();
}
if (libPublisher.SmartPublisherSetURL(publisherHandle, rtmp_pusher_url) != 0) {
Log.e(TAG, "Failed to set publish stream URL..");
}
int startRet = libPublisher.SmartPublisherStartPublisher(publisherHandle);
if (startRet != 0) {
Log.e(TAG, "Failed to start push stream..");
return;
}
if (!isRTSPPublisherRunning && !isGB28181StreamRunning && !isRecording) {
CheckInitAudioRecorder();
}
startLayerPostThread();
btnRTMPPusher.setText("停止推送 ");
isPushingRtmp = true;
}
}
停止RTMP推送
//停止rtmp推送
private void stopPush() {
if(!isPushingRtmp)
return;
isPushingRtmp = false;
if (!isRTSPPublisherRunning && !isGB28181StreamRunning && !isRecording)
stopLayerPostThread();
if (!isRTSPPublisherRunning && !isGB28181StreamRunning && !isRecording) {
if (audioRecord_ != null) {
Log.i(TAG, "stopPush, call audioRecord_.StopRecording..");
audioRecord_.Stop();
if (audioRecordCallback_ != null) {
audioRecord_.RemoveCallback(audioRecordCallback_);
audioRecordCallback_ = null;
}
audioRecord_ = null;
}
}
if (null == libPublisher || 0 == publisherHandle)
return;
libPublisher.SmartPublisherStopPublisher(publisherHandle);
if (!isRTSPPublisherRunning && !isGB28181StreamRunning && !isRecording) {
releasePublisherHandle();
}
}
GB/T28181
國(guó)標(biāo)GB/T28181協(xié)議全稱《安全防范視頻監(jiān)控聯(lián)網(wǎng)系統(tǒng)信息傳輸、交換、控制技術(shù)要求》,是一個(gè)定義視頻聯(lián)網(wǎng)傳輸和設(shè)備控制標(biāo)準(zhǔn)的白皮書,由公安部科技信息化局提出,該標(biāo)準(zhǔn)規(guī)定了城市監(jiān)控報(bào)警聯(lián)網(wǎng)系統(tǒng)中信息傳輸、交換、控制的互聯(lián)結(jié)構(gòu)、通信協(xié)議結(jié)構(gòu),傳輸、交換、控制的基本要求和安全性要求,以及控制、傳輸流程和協(xié)議接口等技術(shù)要求。解決了視頻間互聯(lián)互通,數(shù)據(jù)共享,以及設(shè)備控制的問(wèn)題,這個(gè)問(wèn)題從頂層解決了視頻信息各自為戰(zhàn)的問(wèn)題,打通了視頻聯(lián)網(wǎng)的信息孤島。
支持對(duì)接數(shù)據(jù)類型:
- 編碼前數(shù)據(jù)(目前支持的有YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等數(shù)據(jù)類型);
- 編碼后數(shù)據(jù)(如無(wú)人機(jī)等264/HEVC數(shù)據(jù),或者本地解析的MP4音視頻數(shù)據(jù));
- 拉取RTSP或RTMP流并接入至GB28181平臺(tái)(比如其他IPC的RTSP流,可通過(guò)Android平臺(tái)GB28181接入到國(guó)標(biāo)平臺(tái))。
?功能設(shè)計(jì)如下:
- 音頻編碼:G.711 A律、AAC;
- 視頻編碼:H.264、H.265;
- 支持純視頻、音視頻PS打包傳輸;
- [攝像頭]支持采集過(guò)程中,前后攝像頭實(shí)時(shí)切換;
- 支持幀率、關(guān)鍵幀間隔(GOP)、碼率(bit-rate)設(shè)置;
- 支持前置攝像頭鏡像設(shè)置;
- 支持軟編碼、特定機(jī)型硬編碼;
- 支持橫屏、豎屏推送;
- 支持RTP OVER UDP和RTP OVER TCP被動(dòng)模式(TCP媒體流傳輸客戶端);
- 支持信令通道網(wǎng)絡(luò)傳輸協(xié)議TCP/UDP設(shè)置;
- 支持注冊(cè)、注銷,支持注冊(cè)刷新及注冊(cè)有效期設(shè)置;
- 支持設(shè)備目錄查詢應(yīng)答;
- 支持心跳機(jī)制,支持心跳間隔、心跳檢測(cè)次數(shù)設(shè)置;
- 支持移動(dòng)設(shè)備位置(MobilePosition)訂閱和通知;
- 支持云臺(tái)控制和預(yù)置位查詢;
- 支持設(shè)備目錄查詢應(yīng)答;
- 支持TeleBoot遠(yuǎn)程啟動(dòng)回調(diào);
- 支持語(yǔ)音廣播;
- 支持語(yǔ)音對(duì)講;
- 支持動(dòng)態(tài)水?。ㄎ淖?、圖片);
- 支持降噪處理、自動(dòng)增益控制;
- 支持實(shí)時(shí)快照;
- 支持實(shí)時(shí)靜音和實(shí)時(shí)音量調(diào)節(jié);
- 支持錄像功能擴(kuò)展(錄制MP4文件);
- 適用國(guó)家標(biāo)準(zhǔn):GB/T 28181—2016;
- 支持Android 5.1以上版本。
信令處理
GBSIPAgentListener主要系GB28181注冊(cè)、心跳、DevicePosition等,如注冊(cè)成功、注冊(cè)超時(shí)、注冊(cè)網(wǎng)絡(luò)傳輸層錯(cuò)誤、心跳異常、設(shè)備位置請(qǐng)求處理:
public interface GBSIPAgentListener
{
/*注冊(cè)成功
* @param dateString: 服務(wù)器日期,用來(lái)校準(zhǔn)設(shè)備端時(shí)間,用戶自行決定是否校準(zhǔn)設(shè)備時(shí)間
*/
void ntsRegisterOK(String dateString);
/*
*注冊(cè)超時(shí)
*/
void ntsRegisterTimeout();
/*
*注冊(cè)網(wǎng)絡(luò)傳輸層異常
*/
void ntsRegisterTransportError(String errorInfo);
/*
*心跳達(dá)到異常次數(shù)
*/
void ntsOnHeartBeatException(int exceptionCount, String lastExceptionInfo);
/*
* 設(shè)備位置請(qǐng)求, 這個(gè)主要用在移動(dòng)設(shè)備位置訂閱上
* @param interval 請(qǐng)求間隔, 單位是毫秒
*/
void ntsOnDevicePositionRequest(String deviceId, int interval);
}
GBSIPAgentPlayListener主要系GB28181的Invite、Ack、Bye等處理:
public interface GBSIPAgentPlayListener {
/*
*收到s=Play的實(shí)時(shí)視音頻點(diǎn)播
*/
void ntsOnInvitePlay(String deviceId, SessionDescription sessionDescription);
/*
*發(fā)送play invite response 異常
*/
void ntsOnPlayInviteResponseException(String deviceId, int statusCode, String errorInfo);
/*
* 收到CANCEL play INVITE請(qǐng)求
*/
void ntsOnCancelPlay(String deviceId);
/*
* 收到Ack
*/
void ntsOnAckPlay(String deviceId);
/*
* 收到Bye
*/
void ntsOnByePlay(String deviceId);
/*
* 不是在收到BYE Message情況下, 終止Play
*/
void ntsOnTerminatePlay(String deviceId);
/*
* Play會(huì)話對(duì)應(yīng)的對(duì)話終止, 一般不會(huì)出發(fā)這個(gè)回調(diào),目前只有在響應(yīng)了200K, 但在64*T1時(shí)間后還沒(méi)收到ACK,才可能會(huì)出發(fā)
收到這個(gè), 請(qǐng)做相關(guān)清理處理
*/
void ntsOnPlayDialogTerminated(String deviceId);
}
GBSIPAgentAudioBroadcastListener主要系GB28181語(yǔ)音廣播處理相關(guān),如有語(yǔ)音廣播相關(guān)需求,可參照demo實(shí)例實(shí)現(xiàn):
public interface GBSIPAgentAudioBroadcastListener {
/*
*收到語(yǔ)音廣播通知
*/
void ntsOnNotifyBroadcastCommand(String fromUserName, String fromUserNameAtDomain, String sn, String sourceID, String targetID);
/*
*需要準(zhǔn)備接受語(yǔ)音廣播的SDP內(nèi)容
*/
void ntsOnAudioBroadcast(String commandFromUserName, String commandFromUserNameAtDomain, String sourceID, String targetID);
/*
*音頻廣播, 發(fā)送Invite請(qǐng)求異常
*/
void ntsOnInviteAudioBroadcastException(String sourceID, String targetID, String errorInfo);
/*
*音頻廣播, 等待Invite響應(yīng)超時(shí)
*/
void ntsOnInviteAudioBroadcastTimeout(String sourceID, String targetID);
/*
*音頻廣播, 收到Invite消息最終響應(yīng)
*/
void ntsOnInviteAudioBroadcastResponse(String sourceID, String targetID, int statusCode, SessionDescription sessionDescription);
/*
* 音頻廣播, 收到BYE Message
*/
void ntsOnByeAudioBroadcast(String sourceID, String targetID);
/*
* 不是在收到BYE Message情況下, 終止音頻廣播
*/
void ntsOnTerminateAudioBroadcast(String sourceID, String targetID);
}
GBSIPAgentDeviceControlListener主要系GB28181設(shè)備控制相關(guān),比如遠(yuǎn)程啟動(dòng)、云臺(tái)控制:
public interface GBSIPAgentDeviceControlListener {
/*
* 收到遠(yuǎn)程啟動(dòng)控制命令
*/
void ntsOnDeviceControlTeleBootCommand(String deviceId, String teleBootValue);
/*
* 云臺(tái)控制
*/
void ntsOnDeviceControlPTZCmd(String deviceId, String typeValue);
}
GBSIPAgentQueryCommandListener主要系GB28181查詢命令,如預(yù)置位查詢:
public interface GBSIPAgentQueryCommandListener {
/*
* 設(shè)備預(yù)置位查詢
*/
void ntsOnDevicePresetQueryCommand(String fromUserName, String fromUserNameAtDomain, String sn, String deviceId);
}
GBSIPAgentTalkListener主要系GB28181語(yǔ)音對(duì)講相關(guān)處理:
public interface GBSIPAgentTalkListener {
/*
*收到s=Talk 語(yǔ)音對(duì)講
*/
void ntsOnInviteTalk(String deviceId, SessionDescription sessionDescription);
/*
*發(fā)送talk invite response 異常
*/
void ntsOnTalkInviteResponseException(String deviceId, int statusCode, String errorInfo);
/*
* 收到CANCEL Talk INVITE請(qǐng)求
*/
void ntsOnCancelTalk(String deviceId);
/*
* 收到Ack
*/
void ntsOnAckTalk(String deviceId);
/*
* 收到Bye
*/
void ntsOnByeTalk(String deviceId);
/*
* 不是在收到BYE Message情況下, 終止Talk
*/
void ntsOnTerminateTalk(String deviceId);
/*
* Talk會(huì)話對(duì)應(yīng)的對(duì)話終止, 一般不會(huì)出發(fā)這個(gè)回調(diào),目前只有在響應(yīng)了200K, 但在64*T1時(shí)間后還沒(méi)收到ACK,才可能會(huì)出發(fā)
收到這個(gè), 請(qǐng)做相關(guān)清理處理
*/
void ntsOnTalkDialogTerminated(String deviceId);
}
媒體數(shù)據(jù)處理
RTP數(shù)據(jù)發(fā)送
RTP Sender(SmartPublisherJniV2.java)相關(guān)接口設(shè)計(jì):
/*
* SmartPublisherJniV2.java
* Author: https://daniusdk.com
*/
/*
* 創(chuàng)建RTP Sender實(shí)例
*
* @param reserve:保留參數(shù)傳0
*
* @return RTP Sender 句柄,0表示失敗
*/
public native long CreateRTPSender(int reserve);
/**
*設(shè)置 RTP Sender傳輸協(xié)議
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param transport_protocol, 0:UDP, 1:TCP, 默認(rèn)是UDP
*
* @return {0} if successful
*/
public native int SetRTPSenderTransportProtocol(long rtp_sender_handle, int transport_protocol);
/**
*設(shè)置 RTP Sender IP地址類型
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param ip_address_type, 0:IPV4, 1:IPV6, 默認(rèn)是IPV4, 當(dāng)前僅支持IPV4
*
* @return {0} if successful
*/
public native int SetRTPSenderIPAddressType(long rtp_sender_handle, int ip_address_type);
/**
*設(shè)置 RTP Sender RTP Socket本地端口
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param port, 必須是偶數(shù),設(shè)置0的話SDK會(huì)自動(dòng)分配, 默認(rèn)值是0
*
* @return {0} if successful
*/
public native int SetRTPSenderLocalPort(long rtp_sender_handle, int port);
/**
*設(shè)置 RTP Sender SSRC
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param ssrc, 如果設(shè)置的話,這個(gè)字符串要能轉(zhuǎn)換成uint32類型, 否則設(shè)置失敗
*
* @return {0} if successful
*/
public native int SetRTPSenderSSRC(long rtp_sender_handle, String ssrc);
/**
*設(shè)置 RTP Sender RTP socket 發(fā)送Buffer大小
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param buffer_size, 必須大于0, 默認(rèn)是512*1024, 當(dāng)前僅對(duì)UDP socket有效, 根據(jù)視頻碼率考慮設(shè)置合適的值
*
* @return {0} if successful
*/
public native int SetRTPSenderSocketSendBuffer(long rtp_sender_handle, int buffer_size);
/**
*設(shè)置 RTP Sender RTP時(shí)間戳?xí)r鐘頻率
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param clock_rate, 必須大于0, 對(duì)于GB28181 PS規(guī)定是90kHz, 也就是90000
*
* @return {0} if successful
*/
public native int SetRTPSenderClockRate(long rtp_sender_handle, int clock_rate);
/**
*設(shè)置 RTP Sender 目的IP地址, 注意當(dāng)前用在GB2818推送上,只設(shè)置一個(gè)地址,將來(lái)擴(kuò)展如果用在其他地方,可能要設(shè)置多個(gè)目的地址,到時(shí)候接口可能會(huì)調(diào)整
*
* @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);
/**
* 設(shè)置是否開啟 RTP Receiver
* @param rtp_sender_handle, CreateRTPSender返回值
* @param is_enable, 0表示不收RTP包, 1表示收RTP包, SDK默認(rèn)值為0.
* @return
*/
public native int EnableRTPSenderReceive(long rtp_sender_handle, int is_enable);
/**
*設(shè)置RTP Receiver SSRC
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param ssrc, 如果設(shè)置的話,這個(gè)字符串要能轉(zhuǎn)換成uint32類型, 否則設(shè)置失敗
*
* @return {0} if successful
*/
public native int SetRTPSenderReceiveSSRC(long rtp_sender_handle, String ssrc);
/**
*設(shè)置RTP Receiver Payload 相關(guān)信息
*
* @param rtp_sender_handle, CreateRTPSender返回值
*
* @param payload_type, 請(qǐng)參考 RFC 3551
*
* @param encoding_name, 編碼名, 請(qǐng)參考 RFC 3551, 如果payload_type不是動(dòng)態(tài)的, 可能傳null就好
*
* @param media_type, 媒體類型, 請(qǐng)參考 RFC 3551, 1 是視頻, 2是音頻
*
* @param clock_rate, 請(qǐng)參考 RFC 3551
*
* @return {0} if successful
*/
public native int SetRTPSenderReceivePayloadType(long rtp_sender_handle, int payload_type, String encoding_name, int media_type, int clock_rate);
/**
*設(shè)置RTP Receiver PS的pts和dts clock frequency
*
* @param rtp_sender_handle, CreateRTPSender返回值
*
* @param ps_clock_frequency, 默認(rèn)是90000, 一些特殊場(chǎng)景需要設(shè)置
*
* @return {0} if successful
*/
public native int SetRTPSenderReceivePSClockFrequency(long rtp_sender_handle, int ps_clock_frequency);
/**
*設(shè)置 RTP Receiver 音頻采樣率
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param sampling_rate, 音頻采樣率
*
* @return {0} if successful
*/
public native int SetRTPSenderReceiveAudioSamplingRate(long rtp_sender_handle, int sampling_rate);
/**
*設(shè)置 RTP Receiver 音頻通道數(shù)
*
* @param rtp_sender_handle, CreateRTPSender返回值
* @param channels, 音頻通道數(shù)
*
* @return {0} if successful
*/
public native int SetRTPSenderReceiveAudioChannels(long rtp_sender_handle, int channels);
/**
*初始化RTP Sender, 初始化之前先調(diào)用上面的接口配置相關(guān)參數(shù)
*
* @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, 成功的話返回響應(yīng)的端口, 請(qǐng)?jiān)贗nitRTPSender返回成功之后調(diào)用
*/
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就無(wú)效了,請(qǐng)不要再使用
*
* @param rtp_sender_handle, CreateRTPSender返回值
*
* @return {0} if successful
*/
public native int DestoryRTPSender(long rtp_sender_handle);
RTP數(shù)據(jù)接收
對(duì)應(yīng)RTP Receiver(SmartPlayerJniV2.java)相關(guān)接口設(shè)計(jì),如無(wú)語(yǔ)音廣播或語(yǔ)音對(duì)講相關(guān)技術(shù)需求,這部分可忽略:
/*
* SmartPlayerJniV2.java
* Author: https://daniusdk.com
*/
/*
* 創(chuàng)建RTP Receiver
*
* @param reserve:保留參數(shù)傳0
*
* @return RTP Receiver 句柄,0表示失敗
*/
public native long CreateRTPReceiver(int reserve);
/**
*設(shè)置 RTP Receiver傳輸協(xié)議
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param transport_protocol, 0:UDP, 1:TCP, 默認(rèn)是UDP
*
* @return {0} if successful
*/
public native int SetRTPReceiverTransportProtocol(long rtp_receiver_handle, int transport_protocol);
/**
*設(shè)置 RTP Receiver IP地址類型
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param ip_address_type, 0:IPV4, 1:IPV6, 默認(rèn)是IPV4
*
* @return {0} if successful
*/
public native int SetRTPReceiverIPAddressType(long rtp_receiver_handle, int ip_address_type);
/**
*設(shè)置 RTP Receiver RTP Socket本地端口
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param port, 必須是偶數(shù),設(shè)置0的話SDK會(huì)自動(dòng)分配, 默認(rèn)值是0
*
* @return {0} if successful
*/
public native int SetRTPReceiverLocalPort(long rtp_receiver_handle, int port);
/**
*設(shè)置 RTP Receiver SSRC
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param ssrc, 如果設(shè)置的話,這個(gè)字符串要能轉(zhuǎn)換成uint32類型, 否則設(shè)置失敗
*
* @return {0} if successful
*/
public native int SetRTPReceiverSSRC(long rtp_receiver_handle, String ssrc);
/**
*創(chuàng)建 RTP Receiver 會(huì)話
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param reserve, 保留值,目前傳0
*
* @return {0} if successful
*/
public native int CreateRTPReceiverSession(long rtp_receiver_handle, int reserve);
/**
*獲取 RTP Receiver RTP Socket本地端口
*
* @param rtp_receiver_handle, CreateRTPReceiver
*
* @return 失敗返回0, 成功的話返回響應(yīng)的端口, 請(qǐng)?jiān)贑reateRTPReceiverSession返回成功之后調(diào)用
*/
public native int GetRTPReceiverLocalPort(long rtp_receiver_handle);
/**
*設(shè)置 RTP Receiver Payload 相關(guān)信息
*
* @param rtp_receiver_handle, CreateRTPReceiver
*
* @param payload_type, 請(qǐng)參考 RFC 3551
*
* @param encoding_name, 編碼名, 請(qǐng)參考 RFC 3551, 如果payload_type不是動(dòng)態(tài)的, 可能傳null就好
*
* @param media_type, 媒體類型, 請(qǐng)參考 RFC 3551, 1 是視頻, 2是音頻
*
* @param clock_rate, 請(qǐng)參考 RFC 3551
*
* @return {0} if successful
*/
public native int SetRTPReceiverPayloadType(long rtp_receiver_handle, int payload_type, String encoding_name, int media_type, int clock_rate);
/**
*設(shè)置 RTP Receiver 音頻采樣率
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param sampling_rate, 音頻采樣率
*
* @return {0} if successful
*/
public native int SetRTPReceiverAudioSamplingRate(long rtp_receiver_handle, int sampling_rate);
/**
*設(shè)置 RTP Receiver 音頻通道數(shù)
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param channels, 音頻通道數(shù)
*
* @return {0} if successful
*/
public native int SetRTPReceiverAudioChannels(long rtp_receiver_handle, int channels);
/**
*設(shè)置 RTP Receiver 遠(yuǎn)端地址
*
* @param rtp_receiver_handle, CreateRTPReceiver
* @param address, IP地址
* @param port, 端口
*
* @return {0} if successful
*/
public native int SetRTPReceiverRemoteAddress(long rtp_receiver_handle, String address, int port);
/**
*初始化 RTP Receiver
*
* @param rtp_receiver_handle, CreateRTPReceiver
*
* @return {0} if successful
*/
public native int InitRTPReceiver(long rtp_receiver_handle);
/**
*UnInit RTP Receiver
*
* @param rtp_receiver_handle, CreateRTPReceiver
*
* @return {0} if successful
*/
public native int UnInitRTPReceiver(long rtp_receiver_handle);
/**
*Destory RTP Receiver Session
*
* @param rtp_receiver_handle, CreateRTPReceiver
*
* @return {0} if successful
*/
public native int DestoryRTPReceiverSession(long rtp_receiver_handle);
/**
*Destory RTP Receiver
*
* @param rtp_receiver_handle, CreateRTPReceiver
*
* @return {0} if successful
*/
public native int DestoryRTPReceiver(long rtp_receiver_handle);
PostAudioPacket(SmartPlayerJniV2.java),投遞音頻包給外部Live source,目前僅于語(yǔ)音對(duì)講使用:
/*
* SmartPlayerJniV2.java
* Author: https://daniusdk.com
*/
/**
* 投遞音頻包給外部Live source, 注意ByteBuffer對(duì)象必須是DirectBuffer
*
* @param handle: return value from SmartPlayerOpen()
*
* @return {0} if successful
*/
public native int PostAudioPacket(long handle, int codec_id,
java.nio.ByteBuffer packet, int offset, int size, long pts, boolean is_pts_discontinuity,
java.nio.ByteBuffer extra_data, int extra_data_offset, int extra_data_size, int sample_rate, int channels);
總結(jié)
Android平臺(tái)音視頻數(shù)據(jù)流通,主要還看技術(shù)方案選擇怎樣的場(chǎng)景,如果是對(duì)接執(zhí)法記錄儀、智能安全帽、智能監(jiān)控、智慧零售、智慧教育、遠(yuǎn)程辦公、明廚亮灶、智慧交通、智慧工地、雪亮工程、平安鄉(xiāng)村、生產(chǎn)運(yùn)輸、車載終端等場(chǎng)景等,目前選擇GB28181的更多一些,如果主要是上云或者無(wú)紙化同屏、智慧教室等,還是RTMP推送多一些。具體可以根據(jù)場(chǎng)景選擇適合自己的技術(shù)方案。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-498193.html
大家比較擔(dān)心延遲問(wèn)題,如果GB28181平臺(tái)側(cè)走RTMP或者webrtc的話,延遲也不大,和RTMP方案一樣,整體都可以做到毫秒級(jí)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-498193.html
到了這里,關(guān)于Android平臺(tái)音視頻推送選RTMP還是GB28181?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!