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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何实现多路海康大华等RTSP数据转RTMP推送

發布時間:2025/3/12 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何实现多路海康大华等RTSP数据转RTMP推送 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個好的轉發模塊,首先要低延遲!其次足夠穩定靈活、有狀態反饋機制、資源占用低,跨平臺,最好以接口形式提供,便于第三方系統集成。

以Windows平臺為例,我們的考慮的點如下

1. 拉流:通過RTSP直播播放SDK的數據回調接口,拿到音視頻數據;

2. 轉推:通過RTMP直播推送SDK的編碼后數據輸入接口,把回調上來的數據,傳給RTMP直播推送模塊,實現RTSP數據流到RTMP服務器的轉發;

3. 錄像:如果需要錄像,借助RTSP直播播放SDK,拉到音視頻數據后,直接存儲MP4文件即可;

4. 快照:如果需要實時快照,拉流后,解碼調用播放端快照接口,生成快照,因為快照涉及到video數據解碼,如無必要,可不必開啟,不然會額外消耗性能。

5. 拉流預覽:如需預覽拉流數據,只要調用播放端的播放接口,即可實現拉流數據預覽;

6. 數據轉AAC后轉發:考慮到好多監控設備出來的音頻可能是PCMA/PCMU的,如需要更通用的音頻格式,可以轉AAC后,在通過RTMP推送;

7. 轉推RTMP實時靜音:只需要在傳audio數據的地方,加個判斷即可;

8. 拉流速度反饋:通過RTSP播放端的實時碼率反饋event,拿到實時帶寬占用即可;

9. 整體網絡狀態反饋:考慮到有些攝像頭可能會臨時或異常關閉,RTMP服務器亦是,可以通過推拉流的event回調狀態,查看那整體網絡情況,如此界定:是拉不到流,還是推不到RTMP服務器。

系統設計架構圖

Windows轉發demo分析

大牛直播SDK的轉發demo,Windows平臺,對應C++ demo工程:WIN-RelaySDK-CPP-Demo,如需下載demo源碼,參看 Github

1. 拉流:拉流和播放有些類似,但不需要播放(也就是說不要解碼,資源消耗非常低),在做過基礎的參數配置之后(對應demo里面OpenPullHandle()),設置音視頻數據回調,然后調用StartPullStream()即可:

1.1 基礎參數設置:

bool nt_stream_relay_wrapper::OpenPullHandle(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute) {if ( pull_handle_ != NULL )return true;if ( url.empty() )return false;duration_ = 0;NT_HANDLE pull_handle = NULL;ASSERT( pull_api_ != NULL );if (NT_ERC_OK != pull_api_->Open(&pull_handle, render_wnd_, 0, NULL)){return false;}ASSERT(pull_handle != NULL);pull_api_->SetEventCallBack(pull_handle, this, &NT_Pull_SDKEventHandle);pull_api_->SetBuffer(pull_handle, 0);pull_api_->SetFastStartup(pull_handle, 1);pull_api_->SetRTSPTcpMode(pull_handle, is_rtsp_tcp_mode ? 1 : 0);pull_api_->SetMute(pull_handle, is_mute ? 1 : 0);if ( NT_ERC_OK != pull_api_->SetURL(pull_handle, url.c_str()) ){pull_api_->Close(pull_handle);pull_handle = NULL;return false;}if ( setting_pos_ >= 0ll ){pull_api_->SetPos(pull_handle, setting_pos_);}pull_handle_ = pull_handle;return true; }

1.2 設置音視頻數據回調:

pull_api_->SetPullStreamVideoDataCallBack(pull_handle_, this, &SP_SDKPullStreamVideoDataHandle);pull_api_->SetPullStreamAudioDataCallBack(pull_handle_, this, &SP_SDKPullStreamAudioDataHandle);

1.3 開始拉流:

auto ret = pull_api_->StartPullStream(pull_handle_);if ( NT_ERC_OK != ret ){if ( !is_playing_ ){pull_api_->Close(pull_handle_);pull_handle_ = NULL;}return false;}

拉流整體代碼如下:

bool nt_stream_relay_wrapper::StartPull(const std::string& url, bool is_rtsp_tcp_mode, bool is_transcode_aac) {if ( is_pulling_ )return false;if ( !OpenPullHandle(url, is_rtsp_tcp_mode) )return false;pull_api_->SetPullStreamVideoDataCallBack(pull_handle_, this, &SP_SDKPullStreamVideoDataHandle);pull_api_->SetPullStreamAudioDataCallBack(pull_handle_, this, &SP_SDKPullStreamAudioDataHandle);pull_api_->SetPullStreamAudioTranscodeAAC(pull_handle_, is_transcode_aac? 1: 0);auto ret = pull_api_->StartPullStream(pull_handle_);if ( NT_ERC_OK != ret ){if ( !is_playing_ ){pull_api_->Close(pull_handle_);pull_handle_ = NULL;}return false;}is_pulling_ = true;return true; }

2. 停止拉流:

停止拉流流程比較簡單,先判斷是否在拉流狀態,如果拉流,調用StopPullStream() 即可,如沒有預覽畫面,調用Close()接口關閉拉流實例。

void nt_stream_relay_wrapper::StopPull() {if ( !is_pulling_ )return;pull_api_->StopPullStream(pull_handle_);if ( !is_playing_ ){pull_api_->Close(pull_handle_);pull_handle_ = NULL;}is_pulling_ = false; }

3. 拉流端預覽:

拉流端預覽,說白了就是播放拉流數據,流程比較簡單,demo調用如下,如不需要播放聲音,調用SetMute(),實時打開/關閉即可:

bool nt_stream_relay_wrapper::StartPlay(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute) {if ( is_playing_ )return false;if ( !OpenPullHandle(url, is_rtsp_tcp_mode, is_mute) )return false;pull_api_->SetMute(pull_handle_, is_mute ? 1 : 0);auto ret = pull_api_->StartPlay(pull_handle_);if ( NT_ERC_OK != ret ){if ( !is_pulling_ ){pull_api_->Close(pull_handle_);pull_handle_ = NULL;}return false;}is_playing_ = true;return true; }

4. 拉流端關閉預覽:

void nt_stream_relay_wrapper::StopPlay() {if ( !is_playing_ )return;pull_api_->StopPlay(pull_handle_);if ( !is_pulling_ ){pull_api_->Close(pull_handle_);pull_handle_ = NULL;}is_playing_ = false; }

5. 開始推流到RTMP服務器:

推流的流程,如之前所述,調用RTMP推送模塊,然后數據源傳編碼后的音視頻數據即可,下圖的demo源碼,同時展示了,RTSP流獲取到后,轉推RTMP的時候,數據解密的處理:

bool nt_stream_relay_wrapper::StartPush(const std::string& url) {if ( is_pushing_ )return false;if ( url.empty() )return false;if ( !OpenPushHandle() )return false;auto push_handle = GetPushHandle();ASSERT(push_handle != nullptr);ASSERT(push_api_ != NULL);if ( NT_ERC_OK != push_api_->SetURL(push_handle, url.c_str(), NULL) ){if ( !is_started_rtsp_stream_ ){push_api_->Close(push_handle);SetPushHandle(nullptr);}return false;}// 加密測試 +++// push_api_->SetRtmpEncryptionOption(push_handle, url.c_str(), 1, 1);// NT_BYTE test_key[16] = {'1', '2', '3'};// push_api_->SetRtmpEncryptionKey(push_handle, url.c_str(), test_key, 16);// 加密測試 --if ( NT_ERC_OK != push_api_->StartPublisher(push_handle, NULL) ){if ( !is_started_rtsp_stream_ ){push_api_->Close(push_handle);SetPushHandle(nullptr);}return false;}// // test push rtsp ++// push_api_->SetPushRtspTransportProtocol(push_handle, 1);// // push_api_->SetPushRtspTransportProtocol(push_handle, 2);// push_api_->SetPushRtspURL(push_handle, "rtsp://player.daniulive.com:554/liverelay111.sdp");// push_api_->StartPushRtsp(push_handle, 0);// // test push rtsp--is_pushing_ = true;return true; }

6. 傳遞轉推RTMP數據:

void nt_stream_relay_wrapper::OnVideoDataHandle(NT_HANDLE handle, NT_UINT32 video_codec_id, NT_BYTE* data, NT_UINT32 size, NT_SP_PullStreamVideoDataInfo* info) {if (!is_pushing_ && !is_started_rtsp_stream_)return;if ( pull_handle_ != handle )return;if (data == NULL)return;if (size < 1)return;if (info == NULL)return;std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);if (!is_pushing_ && !is_started_rtsp_stream_)return;if (push_handle_ == NULL)return;push_api_->PostVideoEncodedDataV2(push_handle_, video_codec_id,data, size, info->is_key_frame_, info->timestamp_, info->presentation_timestamp_); }void nt_stream_relay_wrapper::OnAudioDataHandle(NT_HANDLE handle, NT_UINT32 auido_codec_id,NT_BYTE* data, NT_UINT32 size, NT_SP_PullStreamAuidoDataInfo* info) {if (!is_pushing_ && !is_started_rtsp_stream_)return;if (pull_handle_ != handle)return;if (data == NULL)return;if (size < 1)return;if (info == NULL)return;std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);if (!is_pushing_ && !is_started_rtsp_stream_)return;if (push_handle_ == NULL)return;push_api_->PostAudioEncodedData(push_handle_, auido_codec_id, data, size,info->is_key_frame_, info->timestamp_, info->parameter_info_, info->parameter_info_size_); }

7. 關閉實時RTMP轉推

void nt_stream_relay_wrapper::StopPush() {if ( !is_pushing_ )return;is_pushing_ = false;std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);if ( nullptr == push_handle_ )return;push_api_->StopPublisher(push_handle_);// // test push rtsp ++// push_api_->StopPushRtsp(push_handle_);// // test push rtsp--if ( !is_started_rtsp_stream_ ){push_api_->Close(push_handle_);push_handle_ = nullptr;} }

以上就是RTSP或RTMP流轉RTMP推送的流程,感興趣的開發者,可做設計參考。

總結

以上是生活随笔為你收集整理的如何实现多路海康大华等RTSP数据转RTMP推送的全部內容,希望文章能夠幫你解決所遇到的問題。

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