多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > php教程 > WebRTC學(xué)習(xí)之九:攝像頭的捕捉和顯示

WebRTC學(xué)習(xí)之九:攝像頭的捕捉和顯示

來源:程序員人生   發(fā)布時(shí)間:2017-02-03 14:56:40 閱讀次數(shù):5964次

           較新的WebRTC源碼中已沒有了與VoiceEngine結(jié)構(gòu)對應(yīng)的VidoeEngine了,取而代之的是MeidaEngine。MediaEngine包括了MediaEngineInterface接口及其實(shí)現(xiàn)CompositeMediaEngine,CompositeMediaEngine本身也是個(gè)模板類,兩個(gè)模板參數(shù)分別是音頻引擎和視頻引擎。CompositeMediaEngine派生類WebRtcMediaEngine依賴的模板參數(shù)是WebRtcVoiceEngine和WebRtcVideoEngine2。
        上圖中base目錄中是1些抽象類,engine目錄中是對應(yīng)抽象類的實(shí)現(xiàn),使用時(shí)直接調(diào)用engine目錄中的接口便可。WebRtcVoiceEngine實(shí)際上是VoiceEngine的再次封裝,它使用VoiceEngine進(jìn)行音頻處理。注意命名,WebRtcVideoEngine2帶了個(gè)2字,不用想,這肯定是個(gè)升級版本的VideoEngine,還有個(gè)WebRtcVideoEngine類。WebRtcVideoEngine2比WebRtcVideoEngine改進(jìn)的地方在于將視頻流1分為2:發(fā)送流(WebRtcVideoSendStream)和接收流(WebRtcVideoReceiveStream),從而結(jié)構(gòu)上更公道,源碼更清晰。
       本文的實(shí)現(xiàn)主要是使用了WebRtcVideoEngine2中WebRtcVideoCapturer類。
1.環(huán)境
參考上篇:WebRTC學(xué)習(xí)之3:錄音和播放
2.實(shí)現(xiàn)
        打開WebRtcVideoCapturer的頭文件webrtcvideocapture.h,公有的函數(shù)基本上都是base目錄中VideoCapturer類的實(shí)現(xiàn),用于初始化裝備和啟動(dòng)捕捉。私有函數(shù)OnIncomingCapturedFrame和OnCaptureDelayChanged會(huì)在攝像頭收集模塊VideoCaptureModeule中回調(diào),將收集的圖象傳給OnIncomingCapturedFrame,并將收集的延時(shí)變化傳給OnCaptureDelayChanged。
        WebRTC中也實(shí)現(xiàn)了類似Qt中的信號和槽機(jī)制,詳見WebRTC學(xué)習(xí)之7:精煉的信號和槽機(jī)制 。但是就像在該文中提到的,sigslot.h中的emit函數(shù)名會(huì)和Qt中的emit宏沖突,我將sigslot.h中的emit改成了Emit,固然改完以后,需要重新編譯rtc_base工程。
       VideoCapturer類有兩個(gè)信號sigslot::signal2<VideoCapturer*, CaptureState> SignalStateChange和sigslot::signal2<VideoCapturer*, const CapturedFrame*, sigslot::multi_threaded_local> SignalFrameCaptured,從SignalFrameCaptured的參數(shù)可以看出我們只要實(shí)現(xiàn)對應(yīng)的槽函數(shù)就可以獲得到CapturedFrame,在槽函數(shù)中將 CapturedFrame進(jìn)行轉(zhuǎn)換顯示便可。SignalStateChange信號的參數(shù)CaptureState是個(gè)枚舉,標(biāo)識(shí)捕捉的狀態(tài)(停止、開始、正在進(jìn)行、失?。?。
        信號SignalFrameCaptured正是在回調(diào)函數(shù)OnIncomingCapturedFrame中發(fā)射出去的。OnIncomingCapturedFrame里面用到了函數(shù)的異步履行,詳見WebRTC學(xué)習(xí)之8:函數(shù)的異步履行。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>

#include <map>
#include <memory>
#include <string>

#include "webrtc/base/sigslot.h"
#include "webrtc/modules/video_capture/video_capture.h"
#include "webrtc/modules/video_capture/video_capture_factory.h"
#include "webrtc/media/base/videocapturer.h"
#include "webrtc/media/engine/webrtcvideocapturer.h"
#include "webrtc/media/engine/webrtcvideoframe.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow,public sigslot::has_slots<>
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void OnFrameCaptured(cricket::VideoCapturer* capturer, const cricket::CapturedFrame* frame);
    void OnStateChange(cricket::VideoCapturer* capturer, cricket::CaptureState state);

private slots:
    void on_pushButtonOpen_clicked();

private:
     void getDeviceList();

private:
    Ui::MainWindow *ui;
    cricket::WebRtcVideoCapturer *videoCapturer;
    cricket::WebRtcVideoFrame *videoFrame;
    std::unique_ptr<uint8_t[]> videoImage;
    QStringList deviceNameList;
    QStringList deviceIDList;
};

#endif // MAINWINDOW_H
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    videoCapturer(new cricket::WebRtcVideoCapturer()),
    videoFrame(new cricket::WebRtcVideoFrame())
{
   ui->setupUi(this);
   getDeviceList();
}

MainWindow::~MainWindow()
{
    delete ui;
    videoCapturer->SignalFrameCaptured.disconnect(this);
    videoCapturer->SignalStateChange.disconnect(this);
    videoCapturer->Stop();
}

void MainWindow::OnFrameCaptured(cricket::VideoCapturer* capturer,const cricket::CapturedFrame* frame)
{

    videoFrame->Init(frame, frame->width, frame->height,true);
    //將視頻圖象轉(zhuǎn)成RGB格式
    videoFrame->ConvertToRgbBuffer(cricket::FOURCC_ARGB,
                                  videoImage.get(),
                                  videoFrame->width()*videoFrame->height()*32/8,
                                  videoFrame->width()*32/8);

    QImage image(videoImage.get(), videoFrame->width(), videoFrame->height(), QImage::Format_RGB32);
    ui->label->setPixmap(QPixmap::fromImage(image));
}


void MainWindow::OnStateChange(cricket::VideoCapturer* capturer, cricket::CaptureState state)
{

}

void MainWindow::getDeviceList()
{
    deviceNameList.clear();
    deviceIDList.clear();
    webrtc::VideoCaptureModule::DeviceInfo *info=webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
    int deviceNum=info->NumberOfDevices();

    for (int i = 0; i < deviceNum; ++i)
    {
        const uint32_t kSize = 256;
        char name[kSize] = {0};
        char id[kSize] = {0};
        if (info->GetDeviceName(i, name, kSize, id, kSize) != ⑴)
        {
            deviceNameList.append(QString(name));
            deviceIDList.append(QString(id));
            ui->comboBoxDeviceList->addItem(QString(name));
        }
    }

    if(deviceNum==0)
    {
        ui->pushButtonOpen->setEnabled(false);
    }
}

void MainWindow::on_pushButtonOpen_clicked()
{
    static bool flag=true;
    if(flag)
    {
         ui->pushButtonOpen->setText(QStringLiteral("關(guān)閉"));

        const std::string kDeviceName = ui->comboBoxDeviceList->currentText().toStdString();
        const std::string kDeviceId = deviceIDList.at(ui->comboBoxDeviceList->currentIndex()).toStdString();

        videoCapturer->Init(cricket::Device(kDeviceName, kDeviceId));
        int width=videoCapturer->GetSupportedFormats()->at(0).width;
        int height=videoCapturer->GetSupportedFormats()->at(0).height;
        cricket::VideoFormat format(videoCapturer->GetSupportedFormats()->at(0));
        //開始捕捉
        if(cricket::CS_STARTING == videoCapturer->Start(format))
        {
            qDebug()<<"Capture is started";
        }
        //連接WebRTC的信號和槽
        videoCapturer->SignalFrameCaptured.connect(this,&MainWindow::OnFrameCaptured);
        videoCapturer->SignalStateChange.connect(this,&MainWindow::OnStateChange);

        if(videoCapturer->IsRunning())
        {
            qDebug()<<"Capture is running";
        }

        videoImage.reset(new uint8_t[width*height*32/8]);

    }
    else
    {
        ui->pushButtonOpen->setText(QStringLiteral("打開"));
        //重復(fù)連接會(huì)報(bào)錯(cuò),需要先斷開,才能再次連接
        videoCapturer->SignalFrameCaptured.disconnect(this);
        videoCapturer->SignalStateChange.disconnect(this);
        videoCapturer->Stop();
        if(!videoCapturer->IsRunning())
        {
            qDebug()<<"Capture is stoped";
        }
        ui->label->clear();
    }
    flag=!flag;
}
main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    while(true)
    {
        //WebRTC消息循環(huán)
        rtc::Thread::Current()->ProcessMessages(0);
        rtc::Thread::Current()->SleepMs(1);
        //Qt消息循環(huán)
        a.processEvents( );
    }
}
注意main函數(shù)中對WebRTC和Qt消息循環(huán)的處理,這是用Qt調(diào)用WebRTC進(jìn)行攝像頭捕捉和顯示的關(guān)鍵。

3.效果







生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产精品久久久久久麻豆一区 | 最近最新中文字幕在线第一页 | 羞羞色院91蜜桃在线观看 | 爱爱欧美 | 国产成人一区二区三区精品久久 | 欧美久久超级碰碰碰二区三区 | 一区二区三区欧美日韩国产 | 欧美人与动人物姣配xxxx | 免费成人视屏 | 国产美女亚洲精品久久久久久 | 一级毛片大全免费播放 | 国产内地激情精品毛片在线一 | 亚洲日韩精品欧美一区二区 | 亚洲精品国产男人的天堂 | 国产在线观看成人免费视频 | 欧美一区二区在线播放 | 亚洲视频在线观 | 亚洲人成伊人成综合网久久久 | 琪琪jav| 激情影院网站 | 国产精品永久免费视频 | 最近中文字幕经典版在线 | 国产成人不卡亚洲精品91 | 国产v欧美v日本v精品 | 亚洲福利视频一区 | 国产精品va在线观看手机版 | 一级毛片在播放免费 | jizzjizz中国丝袜美女 | 欧美一区二区视频三区 | 黄大片日本一级在线a | 亚洲 中文 欧美 日韩 在线人 | 男女很舒服爽视频免费 | 伊人网在线观看 | 天堂69亚洲精品中文字幕 | 操人网站 | 亚洲国产精品久久网午夜 | 波多野结衣久久精品免费播放 | 动漫美女毛片 | 午夜羞羞影院 | 欧美福利精品 | 欧美一级毛片高清视频 |