From eb8366bb0a75819f286c7f4d3452999c10dc9cf1 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 8 Jul 2014 12:21:54 +0400 Subject: [PATCH] DShow camera as IVideoCapture object --- modules/highgui/src/cap.cpp | 30 ++--- modules/highgui/src/cap_dshow.cpp | 256 +++++++++++++++----------------------- modules/highgui/src/cap_dshow.hpp | 49 ++++++++ 3 files changed, 163 insertions(+), 172 deletions(-) create mode 100644 modules/highgui/src/cap_dshow.hpp diff --git a/modules/highgui/src/cap.cpp b/modules/highgui/src/cap.cpp index 9311694..17cbf61 100644 --- a/modules/highgui/src/cap.cpp +++ b/modules/highgui/src/cap.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "cap_intelperc.hpp" +#include "cap_dshow.hpp" #if defined _M_X64 && defined _MSC_VER && !defined CV_ICC #pragma optimize("",off) @@ -115,9 +116,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) { int domains[] = { -#ifdef HAVE_DSHOW - CV_CAP_DSHOW, -#endif #ifdef HAVE_MSMF CV_CAP_MSMF, #endif @@ -175,8 +173,7 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) // try every possibly installed camera API for (int i = 0; domains[i] >= 0; i++) { -#if defined(HAVE_DSHOW) || \ - defined(HAVE_MSMF) || \ +#if defined(HAVE_MSMF) || \ defined(HAVE_TYZX) || \ defined(HAVE_VFW) || \ defined(HAVE_LIBV4L) || \ @@ -205,13 +202,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) switch (domains[i]) { -#ifdef HAVE_DSHOW - case CV_CAP_DSHOW: - capture = cvCreateCameraCapture_DShow (index); - if (capture) - return capture; - break; -#endif #ifdef HAVE_MSMF case CV_CAP_MSMF: capture = cvCreateCameraCapture_MSMF (index); @@ -589,6 +579,9 @@ Ptr VideoCapture::createCameraCapture(int index) { int domains[] = { +#ifdef HAVE_DSHOW + CV_CAP_DSHOW, +#endif #ifdef HAVE_INTELPERC CV_CAP_INTELPERC, #endif @@ -607,18 +600,26 @@ Ptr VideoCapture::createCameraCapture(int index) // try every possibly installed camera API for (int i = 0; domains[i] >= 0; i++) { -#if defined(HAVE_INTELPERC) || \ +#if defined(HAVE_DSHOW) || \ + defined(HAVE_INTELPERC) || \ (0) Ptr capture; switch (domains[i]) { +#ifdef HAVE_DSHOW + case CV_CAP_DSHOW: + capture = Ptr(new cv::VideoCapture_DShow(index)); + if (capture) + return capture; + break; // CV_CAP_DSHOW +#endif #ifdef HAVE_INTELPERC case CV_CAP_INTELPERC: capture = Ptr(new cv::VideoCapture_IntelPerC()); if (capture) return capture; - break; // CV_CAP_INTEL_PERC + break; // CV_CAP_INTEL_PERC #endif } #endif @@ -628,7 +629,6 @@ Ptr VideoCapture::createCameraCapture(int index) return Ptr(); } - VideoWriter::VideoWriter() {} diff --git a/modules/highgui/src/cap_dshow.cpp b/modules/highgui/src/cap_dshow.cpp index 90ffa00..337ed6d 100644 --- a/modules/highgui/src/cap_dshow.cpp +++ b/modules/highgui/src/cap_dshow.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #if (defined WIN32 || defined _WIN32) && defined HAVE_DSHOW +#include "cap_dshow.hpp" /* DirectShow-based Video Capturing module is based on @@ -455,13 +456,7 @@ class videoDevice{ }; - - - ////////////////////////////////////// VIDEO INPUT ///////////////////////////////////// - - - class videoInput{ public: @@ -3098,131 +3093,53 @@ HRESULT videoInput::routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter * return hr; } - -/********************* Capturing video from camera via DirectShow *********************/ - -class CvCaptureCAM_DShow : public CvCapture -{ -public: - CvCaptureCAM_DShow(); - virtual ~CvCaptureCAM_DShow(); - - virtual bool open( int index ); - virtual void close(); - virtual double getProperty(int); - virtual bool setProperty(int, double); - virtual bool grabFrame(); - virtual IplImage* retrieveFrame(int); - virtual int getCaptureDomain() { return CV_CAP_DSHOW; } // Return the type of the capture object: CV_CAP_VFW, etc... - -protected: - void init(); - - int index, width, height,fourcc; - int widthSet, heightSet; - IplImage* frame; - static videoInput VI; -}; - - struct SuppressVideoInputMessages { SuppressVideoInputMessages() { videoInput::setVerbose(false); } }; static SuppressVideoInputMessages do_it; -videoInput CvCaptureCAM_DShow::VI; -CvCaptureCAM_DShow::CvCaptureCAM_DShow() +namespace cv +{ +videoInput VideoCapture_DShow::g_VI; + +VideoCapture_DShow::VideoCapture_DShow(int index) + : m_index(-1) + , m_frame(0) + , m_width(-1) + , m_height(-1) + , m_fourcc(-1) + , m_widthSet(-1) + , m_heightSet(-1) { - index = -1; - frame = 0; - width = height = fourcc = -1; - widthSet = heightSet = -1; CoInitialize(0); + open(index); } - -CvCaptureCAM_DShow::~CvCaptureCAM_DShow() +VideoCapture_DShow::~VideoCapture_DShow() { close(); CoUninitialize(); } -void CvCaptureCAM_DShow::close() -{ - if( index >= 0 ) - { - VI.stopDevice(index); - index = -1; - cvReleaseImage(&frame); - } - widthSet = heightSet = width = height = -1; -} - -// Initialize camera input -bool CvCaptureCAM_DShow::open( int _index ) -{ - int devices = 0; - - close(); - devices = VI.listDevices(true); - if (devices == 0) - return false; - if (_index < 0 || _index > devices-1) - return false; - VI.setupDevice(_index); - if( !VI.isDeviceSetup(_index) ) - return false; - index = _index; - return true; -} - -bool CvCaptureCAM_DShow::grabFrame() -{ - return true; -} - - -IplImage* CvCaptureCAM_DShow::retrieveFrame(int) -{ - if( !frame || VI.getWidth(index) != frame->width || VI.getHeight(index) != frame->height ) - { - if (frame) - cvReleaseImage( &frame ); - int w = VI.getWidth(index), h = VI.getHeight(index); - frame = cvCreateImage( cvSize(w,h), 8, 3 ); - } - - if (VI.getPixels( index, (uchar*)frame->imageData, false, true )) - return frame; - else - return NULL; -} - -double CvCaptureCAM_DShow::getProperty( int property_id ) +double VideoCapture_DShow::getProperty(int propIdx) { - long min_value,max_value,stepping_delta,current_value,flags,defaultValue; + long min_value, max_value, stepping_delta, current_value, flags, defaultValue; - // image format proprrties - switch( property_id ) + switch (propIdx) { + // image format properties case CV_CAP_PROP_FRAME_WIDTH: - return VI.getWidth(index); - + return g_VI.getWidth(m_index); case CV_CAP_PROP_FRAME_HEIGHT: - return VI.getHeight(index); - + return g_VI.getHeight(m_index); case CV_CAP_PROP_FOURCC: - return VI.getFourcc(index); - + return g_VI.getFourcc(m_index); case CV_CAP_PROP_FPS: - return VI.getFPS(index); - } + return g_VI.getFPS(m_index); // video filter properties - switch( property_id ) - { case CV_CAP_PROP_BRIGHTNESS: case CV_CAP_PROP_CONTRAST: case CV_CAP_PROP_HUE: @@ -3233,12 +3150,10 @@ double CvCaptureCAM_DShow::getProperty( int property_id ) case CV_CAP_PROP_WHITE_BALANCE_BLUE_U: case CV_CAP_PROP_BACKLIGHT: case CV_CAP_PROP_GAIN: - if (VI.getVideoSettingFilter(index,VI.getVideoPropertyFromCV(property_id),min_value,max_value,stepping_delta,current_value,flags,defaultValue) ) return (double)current_value; - } + if (g_VI.getVideoSettingFilter(m_index, g_VI.getVideoPropertyFromCV(propIdx), min_value, max_value, stepping_delta, current_value, flags, defaultValue)) + return (double)current_value; // camera properties - switch( property_id ) - { case CV_CAP_PROP_PAN: case CV_CAP_PROP_TILT: case CV_CAP_PROP_ROLL: @@ -3246,33 +3161,33 @@ double CvCaptureCAM_DShow::getProperty( int property_id ) case CV_CAP_PROP_EXPOSURE: case CV_CAP_PROP_IRIS: case CV_CAP_PROP_FOCUS: - if (VI.getVideoSettingCamera(index,VI.getCameraPropertyFromCV(property_id),min_value,max_value,stepping_delta,current_value,flags,defaultValue) ) return (double)current_value; - + if (g_VI.getVideoSettingCamera(m_index, g_VI.getCameraPropertyFromCV(propIdx), min_value, max_value, stepping_delta, current_value, flags, defaultValue)) + return (double)current_value; } // unknown parameter or value not available return -1; } - -bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) +bool VideoCapture_DShow::setProperty(int propIdx, double propVal) { // image capture properties bool handled = false; - switch( property_id ) + switch (propIdx) { case CV_CAP_PROP_FRAME_WIDTH: - width = cvRound(value); + m_width = cvRound(propVal); handled = true; break; case CV_CAP_PROP_FRAME_HEIGHT: - height = cvRound(value); + m_height = cvRound(propVal); handled = true; break; case CV_CAP_PROP_FOURCC: - fourcc = (int)(unsigned long)(value); - if ( fourcc == -1 ) { + m_fourcc = (int)(unsigned long)(propVal); + if (-1 == m_fourcc) + { // following cvCreateVideo usage will pop up caprturepindialog here if fourcc=-1 // TODO - how to create a capture pin dialog } @@ -3280,38 +3195,38 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) break; case CV_CAP_PROP_FPS: - int fps = cvRound(value); - if (fps != VI.getFPS(index)) + int fps = cvRound(propVal); + if (fps != g_VI.getFPS(m_index)) { - VI.stopDevice(index); - VI.setIdealFramerate(index,fps); - if (widthSet > 0 && heightSet > 0) - VI.setupDevice(index, widthSet, heightSet); + g_VI.stopDevice(m_index); + g_VI.setIdealFramerate(m_index, fps); + if (m_widthSet > 0 && m_heightSet > 0) + g_VI.setupDevice(m_index, m_widthSet, m_heightSet); else - VI.setupDevice(index); + g_VI.setupDevice(m_index); } - return VI.isDeviceSetup(index); - + return g_VI.isDeviceSetup(m_index); } - if ( handled ) { + if (handled) + { // a stream setting - if( width > 0 && height > 0 ) + if (m_width > 0 && m_height > 0) { - if( width != VI.getWidth(index) || height != VI.getHeight(index) )//|| fourcc != VI.getFourcc(index) ) + if (m_width != g_VI.getWidth(m_index) || m_height != g_VI.getHeight(m_index) )//|| fourcc != VI.getFourcc(index) ) { - int fps = static_cast(VI.getFPS(index)); - VI.stopDevice(index); - VI.setIdealFramerate(index, fps); - VI.setupDeviceFourcc(index, width, height, fourcc); + int fps = static_cast(g_VI.getFPS(m_index)); + g_VI.stopDevice(m_index); + g_VI.setIdealFramerate(m_index, fps); + g_VI.setupDeviceFourcc(m_index, m_width, m_height, m_fourcc); } - bool success = VI.isDeviceSetup(index); + bool success = g_VI.isDeviceSetup(m_index); if (success) { - widthSet = width; - heightSet = height; - width = height = fourcc = -1; + m_widthSet = m_width; + m_heightSet = m_height; + m_width = m_height = m_fourcc = -1; } return success; } @@ -3319,13 +3234,14 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) } // show video/camera filter dialog - if ( property_id == CV_CAP_PROP_SETTINGS ) { - VI.showSettingsWindow(index); + if (propIdx == CV_CAP_PROP_SETTINGS ) + { + g_VI.showSettingsWindow(m_index); return true; } //video Filter properties - switch( property_id ) + switch (propIdx) { case CV_CAP_PROP_BRIGHTNESS: case CV_CAP_PROP_CONTRAST: @@ -3337,11 +3253,11 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) case CV_CAP_PROP_WHITE_BALANCE_BLUE_U: case CV_CAP_PROP_BACKLIGHT: case CV_CAP_PROP_GAIN: - return VI.setVideoSettingFilter(index,VI.getVideoPropertyFromCV(property_id),(long)value); + return g_VI.setVideoSettingFilter(m_index, g_VI.getVideoPropertyFromCV(propIdx), (long)propVal); } //camera properties - switch( property_id ) + switch (propIdx) { case CV_CAP_PROP_PAN: case CV_CAP_PROP_TILT: @@ -3350,30 +3266,56 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) case CV_CAP_PROP_EXPOSURE: case CV_CAP_PROP_IRIS: case CV_CAP_PROP_FOCUS: - return VI.setVideoSettingCamera(index,VI.getCameraPropertyFromCV(property_id),(long)value); + return g_VI.setVideoSettingCamera(m_index, g_VI.getCameraPropertyFromCV(propIdx), (long)propVal); } return false; } +bool VideoCapture_DShow::grabFrame() +{ + return true; +} +bool VideoCapture_DShow::retrieveFrame(int, OutputArray frame) +{ + frame.create(Size(g_VI.getWidth(m_index), g_VI.getHeight(m_index)), CV_8UC3); + cv::Mat mat = frame.getMat(); + return g_VI.getPixels(m_index, mat.ptr(), false, true ); +} +int VideoCapture_DShow::getCaptureDomain() +{ + return CV_CAP_DSHOW; +} +bool VideoCapture_DShow::isOpened() const +{ + return (-1 != m_index); +} -CvCapture* cvCreateCameraCapture_DShow( int index ) +void VideoCapture_DShow::open(int index) { - CvCaptureCAM_DShow* capture = new CvCaptureCAM_DShow; + close(); + int devices = g_VI.listDevices(true); + if (0 == devices) + return; + if (index < 0 || index > devices-1) + return; + g_VI.setupDevice(index); + if (!g_VI.isDeviceSetup(index)) + return; + m_index = index; +} - try - { - if( capture->open( index )) - return capture; - } - catch(...) +void VideoCapture_DShow::close() +{ + if (m_index >= 0) { - delete capture; - throw; + g_VI.stopDevice(m_index); + m_index = -1; + cvReleaseImage(&m_frame); } + m_widthSet = m_heightSet = m_width = m_height = -1; +} - delete capture; - return 0; } #endif diff --git a/modules/highgui/src/cap_dshow.hpp b/modules/highgui/src/cap_dshow.hpp new file mode 100644 index 0000000..c4ab571 --- /dev/null +++ b/modules/highgui/src/cap_dshow.hpp @@ -0,0 +1,49 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2014, Itseez, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +//M*/ + +#ifndef _CAP_DSHOW_HPP_ +#define _CAP_DSHOW_HPP_ + +#include "precomp.hpp" + +#ifdef HAVE_DSHOW + +class videoInput; +namespace cv +{ + +class VideoCapture_DShow : public IVideoCapture +{ +public: + VideoCapture_DShow(int index); + virtual ~VideoCapture_DShow(); + + virtual double getProperty(int propIdx); + virtual bool setProperty(int propIdx, double propVal); + + virtual bool grabFrame(); + virtual bool retrieveFrame(int outputType, OutputArray frame); + virtual int getCaptureDomain(); + bool isOpened() const; +protected: + void open(int index); + void close(); + + int m_index, m_width, m_height, m_fourcc; + int m_widthSet, m_heightSet; + IplImage* m_frame; + static videoInput g_VI; +}; + +} + +#endif //HAVE_DSHOW +#endif //_CAP_DSHOW_HPP_ \ No newline at end of file -- 2.7.4