之前有一个MJPG格式的usb摄像头老是获取不到数据,我以为是captuer的问题,于是就考虑从自定义captuer入手,结果后来还是从webrtc内部结局了,这个capture就没用了
特此开源,里面用到了opencv
头文件
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** rtspvideocapturer.h
**
** -------------------------------------------------------------------------*/
#pragma once
#include
#include
#include
#include
#include
#include
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "webrtc/base/thread.h"
#include "webrtc/media/base/codec.h"
#include "webrtc/media/base/videocapturer.h"
#include "webrtc/media/engine/internaldecoderfactory.h"
#include "webrtc/video_decoder.h"
using namespace cv;
class OpenvcCameraCallback
{
public:
virtual void onData(Mat frame)=0;
int width;
int height;
};
class CaptureThread:public rtc::Thread
{
public:
CaptureThread();
OpenvcCameraCallback* callback;
void Run();
};
class USBVideoCapturer : public cricket::VideoCapturer, public OpenvcCameraCallback, public rtc::Thread
{
public:
USBVideoCapturer(const std::string & uri, const std::map<std::string,std::string> & opts);
virtual ~USBVideoCapturer();
// overide rtc::Thread
virtual void Run();
void onData(Mat frame);
// overide cricket::VideoCapturer
virtual cricket::CaptureState Start(const cricket::VideoFormat& format);
virtual void Stop();
virtual bool GetPreferredFourccs(std::vector<unsigned int>* fourccs);
virtual bool IsScreencast() const { return false; };
virtual bool IsRunning() { return this->capture_state() == cricket::CS_RUNNING; }
void ConvertThread();
private:
CaptureThread* captureThread;
};
源文件
/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** rtspvideocapturer.cpp
**
** -------------------------------------------------------------------------*/
#include
#include "webrtc/base/timeutils.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/video_coding/h264_sprop_parameter_sets.h"
#include "webrtc/api/video/i420_buffer.h"
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "libyuv/video_common.h"
#include "libyuv/convert.h"
#include "usbvideocapturer.h"
#include
#include
//OpenvcCameraCallback
CaptureThread::CaptureThread()
{
callback=NULL;
}
void CaptureThread::Run()
{
VideoCapture capture(0);//如果是笔记本,0打开的是自带的摄像头,1 打开外接的相机
int w = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int h = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
callback->width=w;
callback->height=h;
cv::Mat frame;
while (capture.isOpened())
{
capture >> frame;
callback->onData(frame);
}
}
USBVideoCapturer::USBVideoCapturer(const std::string & uri, const std::map<std::string,std::string> & opts)
{
captureThread=new CaptureThread();
captureThread->callback=this;
}
USBVideoCapturer::~USBVideoCapturer()
{
}
void USBVideoCapturer::onData(Mat frame)
{
qDebug()<<QString("reveive data,width is:%1,height is:%2").arg(width).arg(height);
int stride_y = width;
int stride_uv = (width + 1) / 2;
int target_width = width;
int target_height = height;
qDebug()<<"in onData 1";
// Setting absolute height (in case it was negative).
// In Windows, the image starts bottom left, instead of top left.
// Setting a negative source height, inverts the image (within LibYuv).
// TODO(nisse): Use a pool?
rtc::scoped_refptr<webrtc::I420Buffer> buffer = webrtc::I420Buffer::Create(
target_width, abs(target_height), stride_y, stride_uv, stride_uv);
qDebug()<<"in onData 2";
/*cv::Mat rgbImg(cy, cx,CV_8UC3);
memcpy(frame.data, rgbImg.data, width*height);
cv::cvtColor(yuvImg, rgbImg, CV_M);*/
int conversionResult = webrtc::ConvertToI420(webrtc::kARGB, (uint8_t*)frame.data, 0, 0, // No cropping
width, height, (size_t)width*height,webrtc::kVideoRotation_0, buffer.get());
qDebug()<<"in onData 3";
if (conversionResult < 0)
{
qDebug()<< "Failed to convert capture frame from type to I420.";
}
qDebug()<<"in onData 4";
webrtc::VideoFrame captureFrame(buffer, 0, rtc::TimeMillis(),webrtc::kVideoRotation_0);
qDebug()<<"in onData 5";
//captureFrame.set_ntp_time_ms(captureTime);
this->OnFrame(captureFrame, width, height);
}
cricket::CaptureState USBVideoCapturer::Start(const cricket::VideoFormat& format)
{
SetCaptureFormat(&format);
SetCaptureState(cricket::CS_RUNNING);
rtc::Thread::Start();
return cricket::CS_RUNNING;
}
void USBVideoCapturer::Stop()
{
rtc::Thread::Stop();
SetCaptureFormat(NULL);
SetCaptureState(cricket::CS_STOPPED);
}
void USBVideoCapturer::Run()
{
captureThread->Start();
}
bool USBVideoCapturer::GetPreferredFourccs(std::vector<unsigned int>* fourccs)
{
return true;
}