Windows操做系统自问世以来,以其简单易用的图形化界面操做受到大众追捧,为计算机的普及、科技的发展作出了不可磨灭的功绩,也慢慢的成为人们最依赖的操做系统。在中国,90%以上的办公环境都是Windows,学校和各类培训班的培训内容也都是Windows,Windows操做系统已经渗入到各行各业,人们已经习惯了Windows的界面和操做习惯,IT计算机和Windows已经被习觉得常的画上了等号。windows
可是,咱们使用的软件真的安全吗?黑屏事件和棱镜门事件让不少乐观看待或还没有意识到信息安全问题的人们警醒,咱们所使用的国外软件并非安全的,咱们的数据彻底掌握在别人手中。随着信息安全上升到了国家战略的高度,推行自主可控的国产操做系统势在必行。国产操做系统做为自主可控的基础,市场迅速升温,受到了社会各界的高度关注。api
咱们有别的选择吗?安全
其实基于开源软件Linux二次开发的操做系统,近年来的发展趋势很是迅猛。Linux已经有20年历史,尤为近十年通过日新月异的发展,Linux桌面操做系统已经远远摆脱了“具有与主流桌面操做系统的可比性”阶段,基于拥有众多优秀的开源应用软件的基础,在软件多样性、硬件兼容性、用户体验等各方面作了大量的改进,如今已经能够知足平常办公的需求。在欧美,咱们不时听到一些政府部门将采用Linux桌面办公:慕尼黑市政府用十年的时间,成功的“赶走”了微软;伯明翰市政府、法国国会、瑞士、挪威和南非政府部门也都采用了Linux桌面办公。app
在发布国产操做系统|Linux平台的RTMP直播推送SDK以前,大牛直播SDK(官方)的RTMP推送模块已稳定运行在Windows、Android和iOS平台几年了。ide
相对Windows、Android和iOS平台,Linux在桌面采集等方面,资料很是少,数据采集能够采用调用XLib相关接口实现,本Demo实现的是Linux上实现桌面和系统声音采集,而后使用RTMP协议推出去的一个SDK. 集成调用很是简单。oop
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; }
相关初始化测试
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; }
推送接口封装ui
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"); else fprintf(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"); else fprintf(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); // 帧率设置 push_api->SetVideoBitRate(push_handle, 2000); // 平均码率2000kbps push_api->SetVideoQualityV2(push_handle, 26); push_api->SetVideoMaxBitRate(push_handle, 4000); // 最大码率4000kbps push_api->SetVideoKeyFrameInterval(push_handle, dst_fps*2); // 关键帧间隔 push_api->SetVideoEncoderProfile(push_handle, 3); // h264 baseline push_api->SetVideoEncoderSpeed(push_handle, 3); // 编码速度设置到3 if (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; }
相关界面编码
实际测试下来,以RTMP推送和RTMP播放为例,总体测试时延都在毫秒级,可知足像内网无纸化、教育同屏等场景需求。url
Linux的RTMP推送接口,和Windows平台的相差无几,通用接口四个平台几乎一致,不存在集成难度。
国产操做系统替代windows,也许并不像你想象的那么遥远,使用习惯上也并不像想象中那么难,相信在不久的未来,国产操做系统会真正被市场普遍使用。
国产操做系统下的应用生态,须要国人一点点创建。