Windows上实现桌面采集资料多,方案也多. Linux这方面的资料较少,不过Linux上也可以实现桌面采集,调用XLib相关接口就可以.
最近写了一个Linux上实现桌面和系统声音采集, 然后使用rtmp协议推出去的一个SDK. 集成调用非常简单,下面是集成调用代码:
namespace
{
volatile bool g_is_exit = false;
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");
else
fprintf(stdout, "UnSupport speaker capture\n");
}
NT_HANDLE push_handle = nullptr;
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->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;
}
}
int main(int argc, char *argv[])
{
signal(SIGINT, &OnSigIntHandler);
LogInit();
NT_SmartPublisherSDKAPI push_api;
if (!PushSDKInit(push_api))
{
return 0;
}
auto push_handle = StartPush(&push_api, "rtmp://192.168.1.99:1935/live/test", 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;
}
下面是采集Ubuntu 14屏幕,然后在Windows上的播放效果:
上图可以看到,延时也就几十毫秒,这个延时做无纸化办公,电子教室等场景的采集和播放很理想.
更多问题可以联系qq: 1130758427, github