版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GG_SiMiDa/article/details/82347030
上一节中我们给出了播放引擎接口类HVideoPlayer,下面我们给出基于OpenCV的VideoCapture类实现的播放引擎实现类HVideoCapture
HVideoCapture
首先播放引擎类从媒体源中获取帧,解码,push到缓存区等工作我们放到另外一个线程中做,以免阻塞GUI线程,为此HVideoPlayer多重继承自HVideoPlayer和HThread
头文件:
#ifndef HVIDEOCAPTURE_H
#define HVIDEOCAPTURE_H
#include "hvideoplayer.h"
#include "hthread.h"
#include "opencv2/opencv.hpp"
class HVideoCapture : public HVideoPlayer, public HThread
{
public:
HVideoCapture() : HVideoPlayer(), HThread() {}
virtual int start();
virtual int stop();
virtual int pause() {return HThread::pause();}
virtual int resume() {return HThread::resume();}
virtual void doTask();
protected:
cv::VideoCapture vc;
};
#endif // HVIDEOCAPTURE_H
源文件:
#include "hvideocapture.h"
#include "opencv_util.h"
#include "qtheaders.h"
int HVideoCapture::start(){
switch (media.type) {
case MEDIA_TYPE_CAPTURE:
vc.open(media.index, cv::CAP_DSHOW);
break;
case MEDIA_TYPE_FILE:
case MEDIA_TYPE_NETWORK:
vc.open(media.src.c_str(), cv::CAP_FFMPEG);
break;
default:
return -10;
}
if (!vc.isOpened())
return -20;
vc.set(cv::CAP_PROP_FPS, 25);
return HThread::start();
}
int HVideoCapture::stop(){
HThread::stop();
vc.release();
return 0;
}
void HVideoCapture::doTask(){
cv::Mat mat;
if (!vc.read(mat))
return;
//...ALG
HFrame frame;
Mat2HFrame(mat, frame);
push_frame(&frame);
}
代码很简单,利用VideoCapture类open打开媒体源,read获取视频帧;
而后我们使用Mat2HFrame将cv::Mat赋值给我们定义的帧结构体HFrame,然后push_frame到帧缓存中;
PIMPL
至此,我们就可以将HVideoWidget中的HVideoPlayer* pImpl = new HVideoCapture;
,实现一个完整的播放器了。
类似的,你也可以实现一个基于FFmpeg的视频引擎类HFFmpegPlayer : public HVideoPlayer, public HThread
,有兴趣的小伙伴可以尝试下。这是我们采用了PIMPL设计模式带来的灵活性,即一套接口,多种实现。接口定义的通用性和可扩展性自然不言而喻了。