查派网站建设,wordpress文章开始加内容,苏州 建设中心网站,自贡建设投资有限公司网站GB28181语音广播这块#xff0c;我们依据GB/T28181-2016针对流程和实例代码#xff0c;做过详细的描述#xff0c;本次主要是探讨下#xff0c;广播数据过来后#xff0c;如何处理。
鉴于我们之前有非常成熟的RTMP|RTSP低延迟播放模块#xff0c;语音广播数据过来后我们依据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 200status_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接入模块的测试。