Linux系统上采集摄像头,可以使用V4L2相关接口,Linux上的摄像头设备文件是/dev/videoxx, 采集和控制摄像头只要调用open("/dev/videoxx", flag) 打开文件,然后对文件进行读写等控制操作即可.
最近在Linux推送SDK也增加了摄像头采集和预览功能,集成调用非常简单,几行C++代码就可以完成.
class CameraInfo
{
public:
std::string name_;
std::string id_;
std::vector<NT_PB_VideoCaptureCapability> capabilities_;
};
void GetCameraInfo(NT_SmartPublisherSDKAPI* push_api, std::vector<CameraInfo>& cameras)
{
NT_INT32 device_number = 0;
if (NT_ERC_OK != push_api->GetVideoCaptureDeviceNumber(&device_number))
{
return;
}
if (device_number < 1)
{
return;
}
for (auto i = 0; i < device_number; ++i)
{
CameraInfo info;
char name[256] = { 0 };
char id[1024] = { 0 };
if (NT_ERC_OK != push_api->GetVideoCaptureDeviceInfo(i,
name, sizeof(name) / sizeof(char),
id, sizeof(id) / sizeof(char)))
{
continue;
}
info.name_ = name;
info.id_ = id;
NT_INT32 capability_number = 0;
if (NT_ERC_OK != push_api->GetVideoCaptureDeviceCapabilityNumber(
id, &capability_number))
{
continue;
}
auto is_failed = false;
//capability_number = 1;
for (auto i = 0; i < capability_number; ++i)
{
NT_PB_VideoCaptureCapability capability = { 0, 0, 0 };
if (NT_ERC_OK != push_api->GetVideoCaptureDeviceCapability(
id, i, &capability))
{
is_failed = true;
break;
}
info.capabilities_.push_back(capability);
}
if (!is_failed)
{
cameras.push_back(info);
}
}
}
NT_HANDLE StartPush(NT_SmartPublisherSDKAPI* push_api, const std::string& rtmp_url, int dst_fps)
{
std::vector<CameraInfo> cameras;
GetCameraInfo(push_api, cameras);
if (!cameras.empty())
{
fprintf(stdout, "cameras count:%d\n", (int)cameras.size());
for (const auto& c : cameras)
{
fprintf(stdout, "camera name:%s, id:%s, cap_num:%d\n", c.name_.c_str(), c.id_.c_str(), (int)c.capabilities_.size());
for (const auto& i : c.capabilities_)
{
fprintf(stdout, "cap w:%d, h:%d, fps:%d\n", i.width_, i.height_, i.max_frame_rate_);
}
}
}
NT_UINT32 auido_option = NT_PB_E_AUDIO_OPTION_NO_AUDIO;
NT_UINT32 video_option = NT_PB_E_VIDEO_OPTION_SCREEN;
if (!cameras.empty())
{
video_option = NT_PB_E_VIDEO_OPTION_CAMERA;
}
NT_HANDLE push_handle = nullptr;
if (NT_ERC_OK != push_api->Open(&push_handle, video_option, auido_option, 0, NULL))
{
return nullptr;
}
if (video_option == NT_PB_E_VIDEO_OPTION_CAMERA)
{
if (!cameras.empty())
{
// 设置摄像头id,和要采集的摄像头分辨率
push_api->SetVideoCaptureDeviceBaseParameter(push_handle, cameras.front().id_.c_str(),
640, 480);
//push_api->FlipVerticalCamera(push_handle, 1); // 摄像头垂直翻转
//push_api->FlipHorizontalCamera(push_handle, 1); // 摄像头水平翻转
//push_api->RotateCamera(push_handle, 0); // 摄像头旋转
}
}
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 high
push_api->SetVideoEncoderSpeed(push_handle, 3); // 编码速度设置到3
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;
}
// 下面是启动预览的代码
{
push_api.SetPreviewXWindow(push_handle, NULL, sub_wid); // 传入用来显示图像的窗口
push_api.StartPreview(push_handle, 0, nullptr);
}
下面是在Ubuntu 14上摄像头预览, 然后推送播放的效果, 左边窗口是播放器,右边是预览窗口.
除了基本的采集功能,SDK还支持摄像头水平/垂直翻转, 支持90, 180, 270度旋转,也支持层叠加模式,可以和屏幕叠加组合. 下面是和屏幕叠加组合的效果:
Linux和Windows一样,摄像头也不能同时打开多次,另外虚拟机上跑的Linux系统,如果USB摄像头不能正常吐图像,可以试下改变USB兼容选项,可能就好了。对于更多问题可以联系qq: 1130758427, github