webrtc c++ (一) 打開攝像頭設備並顯示

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

 

 

效果圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章