日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android如何回调编码后的音视频数据

發布時間:2025/3/12 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android如何回调编码后的音视频数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有開發者提到,在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());

2. 實現?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);}}}

3. 提供開始回調數據和停止回調數據接口:

/*** 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);

4. 上層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為了便于演示方便,另啟動了個新的推送實例,音視頻編碼后的數據,通過新的實例,調用編碼后的音視頻數據接口,繼續推RTMP出去。

此Demo的優越性在于,回調編碼后的音視頻數據功能,可與推RTMP、錄像、內置RTSP服務SDK組合使用,亦可單獨使用。

?

總結

以上是生活随笔為你收集整理的Android如何回调编码后的音视频数据的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。