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_;*/
};
效果圖