上一節中我們給出了播放引擎接口類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設計模式帶來的靈活性,即一套接口,多種實現。接口定義的通用性和可擴展性自然不言而喻了。