void rtcDevice::GetDeviceList()
{
//获取到系统下所有的设备信息
std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(webrtc::VideoCaptureFactory::CreateDeviceInfo());
if (info == nullptr)
{
return;
}
for (int i = 0 ; i < info->NumberOfDevices();++i)
{
char devName[256] = { 0 };
char uniqueName[256] = {0};
//保存所有的设备名称
if (info->GetDeviceName(i, devName, 256, uniqueName, 256) != -1)
{
ui.m_cbDevList->addItem(devName,QString(uniqueName));
}
}
}
首先通过webrtc::VideoCaptureFactory::CreateDeviceInfo() 获取到当前系统下所有的设备,并保存
然后打开设备(cricket::WebRtcVideoCapturer),在其OnFrame回调中绘制信息
void rtcDevice::OnPbClicked()
{
std::string devName = ui.m_cbDevList->currentText().toUtf8().data();
/*std::string devId = ui.m_cbDevList->currentData().toString().toUtf8().data();*/
//初始化捕获类
videoCap_->Init(cricket::Device(devName, 0));
int width = videoCap_->GetSupportedFormats()->at(0).width;
int height = videoCap_->GetSupportedFormats()->at(0).height;
cricket::VideoFormat format(videoCap_->GetSupportedFormats()->at(0));
//开始捕获图像,在videoCap_ OnFrame回调函数中返回图像信息
videoCap_->Start(format);
//videoCap_->OnFrame();
//videoCap_->SignalStateChange.connect(this, &MainWindow::OnStateChange);
}
//cricket::WebRtcVideoCapturer 子类的onFrame回调处理图像信息,将cricket::WebRtcVideoCapturer 捕获的frame信息取出,并保存到QImage中,然后回调给注册的界面类,以供界面类进行绘制
class MyCap :public cricket::WebRtcVideoCapturer
{
public:
//注册回调绘制窗体
void AddWindget(RenderWidget *widget)
{
auto it = std::find(widgetObs_.begin(),widgetObs_.end(),widget);
if (it == widgetObs_.end())
{
widgetObs_.emplace_back(widget);
}
}
//捕获到的图像信息到来,处理转换成QImage,并回调给注册的界面类绘制
void OnFrame(const webrtc::VideoFrame& video_frame) override
{
rtc::scoped_refptr<webrtc::I420BufferInterface> buffer(
video_frame.video_frame_buffer()->ToI420());
if (video_frame.rotation() != webrtc::kVideoRotation_0)
{
buffer = webrtc::I420Buffer::Rotate(*buffer, video_frame.rotation());
}
std::lock_guard<std::mutex> lock(imge_mutex_);
image_.reset(new uint8_t[buffer->width()*buffer->height()*4]);
libyuv::I420ToARGB(buffer->DataY(), buffer->StrideY(), buffer->DataU(),
buffer->StrideU(), buffer->DataV(), buffer->StrideV(),
image_.get(),
buffer->width() * 4,
buffer->width(), buffer->height());
QImage iamge((uchar*)image_.get(), buffer->width(), buffer->height(), QImage::Format_ARGB32);
for (auto var:widgetObs_)
{
var->OnImage(iamge);
}
}
private:
std::unique_ptr<uint8_t[]> image_;
std::vector<RenderWidget*> widgetObs_;
};
//界面类进行绘制
extern std::mutex imge_mutex_;
class RenderWidget :public QWidget
{
public:
explicit RenderWidget(QWidget *parent = nullptr)
:QWidget(parent) {}
virtual void OnImage(const QImage &image)
{
//std::lock_guard < std::mutex> guard(mutex_);
image_ = image;
update();
}
protected:
virtual void paintEvent(QPaintEvent *event) override
{
std::lock_guard <std::mutex> guard(imge_mutex_);
QWidget::paintEvent(event);
QPainter p(this);
p.drawImage(QRect(5, 5, this->width() - 10, this->height() - 10), image_);
}
private:
QImage image_;
/*std::mutex mutex_;*/
};
效果图