基于RTMP实现Linux|麒麟操作系统下屏幕|系统声音采集推送
背景
Windows操作系統(tǒng)自問世以來,以其簡(jiǎn)單易用的圖形化界面操作受到大眾追捧,為計(jì)算機(jī)的普及、科技的發(fā)展做出了不可磨滅的功績(jī),也慢慢的成為人們最依賴的操作系統(tǒng)。在中國(guó),90%以上的辦公環(huán)境都是Windows,學(xué)校和各種培訓(xùn)班的培訓(xùn)內(nèi)容也都是Windows,Windows操作系統(tǒng)已經(jīng)滲入到各行各業(yè),人們已經(jīng)習(xí)慣了Windows的界面和操作習(xí)慣,IT計(jì)算機(jī)和Windows已經(jīng)被習(xí)以為常的畫上了等號(hào)。
但是,我們使用的軟件真的安全嗎?黑屏事件和棱鏡門事件讓很多樂觀看待或尚未意識(shí)到信息安全問題的人們警醒,我們所使用的國(guó)外軟件并不是安全的,我們的數(shù)據(jù)完全掌握在別人手中。隨著信息安全上升到了國(guó)家戰(zhàn)略的高度,推行自主可控的國(guó)產(chǎn)操作系統(tǒng)勢(shì)在必行。國(guó)產(chǎn)操作系統(tǒng)作為自主可控的基礎(chǔ),市場(chǎng)迅速升溫,受到了社會(huì)各界的高度關(guān)注。
我們有別的選擇嗎?
其實(shí)基于開源軟件Linux二次開發(fā)的操作系統(tǒng),近年來的發(fā)展趨勢(shì)非常迅猛。Linux已經(jīng)有20年歷史,尤其近十年經(jīng)過突飛猛進(jìn)的發(fā)展,Linux桌面操作系統(tǒng)已經(jīng)遠(yuǎn)遠(yuǎn)擺脫了“具備與主流桌面操作系統(tǒng)的可比性”階段,基于擁有眾多優(yōu)秀的開源應(yīng)用軟件的基礎(chǔ),在軟件多樣性、硬件兼容性、用戶體驗(yàn)等各方面做了大量的改進(jìn),現(xiàn)在已經(jīng)可以滿足日常辦公的需求。在歐美,我們不時(shí)聽到一些政府部門將采用Linux桌面辦公:慕尼黑市政府用十年的時(shí)間,成功的“趕走”了微軟;伯明翰市政府、法國(guó)國(guó)會(huì)、瑞士、挪威和南非政府部門也都采用了Linux桌面辦公。
國(guó)產(chǎn)操作系統(tǒng)|Linux下RTMP同屏推送
在發(fā)布國(guó)產(chǎn)操作系統(tǒng)|Linux平臺(tái)的RTMP直播推送SDK之前,大牛直播SDK(官方)的RTMP推送模塊已穩(wěn)定運(yùn)行在Windows、Android和iOS平臺(tái)幾年了。
相對(duì)Windows、Android和iOS平臺(tái),Linux在桌面采集等方面,資料非常少,數(shù)據(jù)采集可以采用調(diào)用XLib相關(guān)接口實(shí)現(xiàn),本Demo實(shí)現(xiàn)的是Linux上實(shí)現(xiàn)桌面和系統(tǒng)聲音采集,然后使用RTMP協(xié)議推出去的一個(gè)SDK. 集成調(diào)用非常簡(jiǎn)單。
相關(guān)實(shí)現(xiàn)
int main(int argc, char *argv[]) {signal(SIGINT, &OnSigIntHandler);//printf("sizeof(NT_SmartPublisherSDKAPI)=%d\n", sizeof(NT_SmartPublisherSDKAPI));LogInit();NT_SmartPublisherSDKAPI push_api;if (!PushSDKInit(push_api)){return 0;}auto push_handle = StartPush(&push_api, "rtmp://192.168.0.154:1935/live/test1", 30);if (!push_handle){fprintf(stderr, "start push failed.\n");push_api.UnInit();return 0;}while (!g_is_exit){sleep(2);}fprintf(stdout, "Skip run loop, is_exit:%d\n", g_is_exit);push_api.StopPublisher(push_handle);push_api.Close(push_handle);push_handle = nullptr;push_api.UnInit();fprintf(stdout, "SDK UnInit..\n");return 0; }相關(guān)初始化
void OnSigIntHandler(int sig){if (SIGINT == sig){g_is_exit = true;}}void LogInit(){SmartLogAPI log_api;memset(&log_api, 0, sizeof(log_api));GetSmartLogAPI(&log_api);log_api.SetLevel(SL_INFO_LEVEL);log_api.SetPath((NT_PVOID)"./");}bool PushSDKInit(NT_SmartPublisherSDKAPI& push_api){memset(&push_api, 0, sizeof(push_api));NT_GetSmartPublisherSDKAPI(&push_api);auto ret = push_api.Init(0, nullptr);if (NT_ERC_OK != ret){fprintf(stderr, "push_api.Init failed!\n");return false;}else{fprintf(stdout, "push_api.Init ok!\n");}return true;}推送接口封裝
NT_HANDLE StartPush(NT_SmartPublisherSDKAPI* push_api, const std::string& rtmp_url, int dst_fps){NT_INT32 pulse_device_number = 0;if (NT_ERC_OK == push_api->GetAuidoInputDeviceNumber(2, &pulse_device_number)){fprintf(stdout, "Pulse device num:%d\n", pulse_device_number);char device_name[512];for (auto i = 0; i < pulse_device_number; ++i){if (NT_ERC_OK == push_api->GetAuidoInputDeviceName(2, i, device_name, 512)){fprintf(stdout, "index:%d name:%s\n", i, device_name);}}}NT_INT32 alsa_device_number = 0;if (pulse_device_number < 1){if (NT_ERC_OK == push_api->GetAuidoInputDeviceNumber(1, &alsa_device_number)){fprintf(stdout, "Alsa device num:%d\n", alsa_device_number);char device_name[512];for (auto i = 0; i < alsa_device_number; ++i){if (NT_ERC_OK == push_api->GetAuidoInputDeviceName(1, i, device_name, 512)){fprintf(stdout, "index:%d name:%s\n", i, device_name);}}}}NT_INT32 capture_speaker_flag = 0;if ( NT_ERC_OK == push_api->IsCanCaptureSpeaker(2, &capture_speaker_flag) ){if (capture_speaker_flag)fprintf(stdout, "Support speaker capture\n");elsefprintf(stdout, "UnSupport speaker capture\n");}NT_INT32 is_support_window_capture = 0;if (NT_ERC_OK == push_api->IsCaptureWindowSupported(NULL, &is_support_window_capture)){if (is_support_window_capture)fprintf(stdout, "Support window capture\n");elsefprintf(stdout, "UnSupport window capture\n");}NT_HANDLE push_handle = nullptr;// if (NT_ERC_OK != push_api->Open(&push_handle, NT_PB_E_VIDEO_OPTION_LAYER, NT_PB_E_AUDIO_OPTION_CAPTURE_SPEAKER, 0, NULL))if (NT_ERC_OK != push_api->Open(&push_handle, NT_PB_E_VIDEO_OPTION_SCREEN, NT_PB_E_AUDIO_OPTION_CAPTURE_SPEAKER, 0, NULL)){return nullptr;}//push_api->SetXDisplayName(push_handle, ":0");//push_api->SetXDisplayName(push_handle, NULL);// 視頻層配置方式//std::vector<std::shared_ptr<nt_pb_sdk::layer_conf_wrapper_base> > layer_confs;//auto index = 0;第0層填充RGBA矩形, 目的是保證幀率, 顏色就填充全黑//auto rgba_layer_c0 = std::make_shared<nt_pb_sdk::RGBARectangleLayerConfigWrapper>(index++, true, 0, 0, 1280, 720);//rgba_layer_c0->conf_.red_ = 0;//rgba_layer_c0->conf_.green_ = 0;//rgba_layer_c0->conf_.blue_ = 0;//rgba_layer_c0->conf_.alpha_ = 255;//layer_confs.push_back(rgba_layer_c0);第一層為桌面層//auto screen_layer_c1 = std::make_shared<nt_pb_sdk::ScreenLayerConfigWrapper>(index++, true, 0, 0, 1280, 720);////screen_layer_c1->conf_.scale_filter_mode_ = 3;//layer_confs.push_back(screen_layer_c1);//std::vector<const NT_PB_LayerBaseConfig* > layer_base_confs;//for (const auto& i : layer_confs)//{// layer_base_confs.push_back(i->getBase());//}//if (NT_ERC_OK != push_api->SetLayersConfig(push_handle, 0, layer_base_confs.data(),// layer_base_confs.size(), 0, nullptr))//{// push_api->Close(push_handle);// push_handle = nullptr;// return nullptr;//}// push_api->SetScreenClip(push_handle, 0, 0, 1280, 720);push_api->SetFrameRate(push_handle, dst_fps); // 幀率設(shè)置push_api->SetVideoBitRate(push_handle, 2000); // 平均碼率2000kbpspush_api->SetVideoQualityV2(push_handle, 26); push_api->SetVideoMaxBitRate(push_handle, 4000); // 最大碼率4000kbpspush_api->SetVideoKeyFrameInterval(push_handle, dst_fps*2); // 關(guān)鍵幀間隔push_api->SetVideoEncoderProfile(push_handle, 3); // h264 baselinepush_api->SetVideoEncoderSpeed(push_handle, 3); // 編碼速度設(shè)置到3if (pulse_device_number > 0){push_api->SetAudioInputLayer(push_handle, 2);push_api->SetAuidoInputDeviceId(push_handle, 0);}else if (alsa_device_number > 0){push_api->SetAudioInputLayer(push_handle, 1);push_api->SetAuidoInputDeviceId(push_handle, 0);}// 音頻配置push_api->SetPublisherAudioCodecType(push_handle, 1);//push_api->SetMute(push_handle, 1);if ( NT_ERC_OK != push_api->SetURL(push_handle, rtmp_url.c_str(), NULL) ){push_api->Close(push_handle);push_handle = nullptr;return nullptr;}if ( NT_ERC_OK != push_api->StartPublisher(push_handle, NULL) ){push_api->Close(push_handle);push_handle = nullptr;return nullptr;}return push_handle;}相關(guān)界面
總結(jié)
實(shí)際測(cè)試下來,以RTMP推送和RTMP播放為例,整體測(cè)試時(shí)延都在毫秒級(jí),可滿足像內(nèi)網(wǎng)無紙化、教育同屏等場(chǎng)景需求。
Linux的RTMP推送接口,和Windows平臺(tái)的相差無幾,通用接口四個(gè)平臺(tái)幾乎一致,不存在集成難度。
國(guó)產(chǎn)操作系統(tǒng)替代windows,也許并不像你想象的那么遙遠(yuǎn),使用習(xí)慣上也并不像想象中那么難,相信在不久的將來,國(guó)產(chǎn)操作系統(tǒng)會(huì)真正被市場(chǎng)廣泛使用。
國(guó)產(chǎn)操作系統(tǒng)下的應(yīng)用生態(tài)的創(chuàng)建,需要國(guó)人一點(diǎn)點(diǎn)建立。
總結(jié)
以上是生活随笔為你收集整理的基于RTMP实现Linux|麒麟操作系统下屏幕|系统声音采集推送的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【深度学习】一文概览神经网络模型
- 下一篇: 【深度学生】使用深度学习阅读和分类扫描文