From c314178e7aa06fd4ed84b6521d592ea12e1d6851 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 19 Sep 2016 19:51:10 +0300 Subject: [PATCH] highgui/osx: backport AVFoundation support --- CMakeLists.txt | 20 +++++++------ cmake/OpenCVFindLibsVideo.cmake | 23 +++++++-------- modules/highgui/CMakeLists.txt | 9 ++++-- modules/highgui/src/cap_avfoundation_mac.mm | 32 +++++++++++++++++++++ 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c52ab5c458..007b80d4da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,7 @@ endif() # Optional 3rd party components # =================================================== OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS) +OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS/Mac)" ON IF APPLE) OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE ) OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT IOS) ) OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS AND NOT CMAKE_CROSSCOMPILING) ) @@ -162,7 +162,8 @@ OCV_OPTION(WITH_PVAPI "Include Prosilica GigE support" ON OCV_OPTION(WITH_GIGEAPI "Include Smartek GigE support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_QT "Build with Qt Backend support" OFF IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_WIN32UI "Build with Win32 UI Backend support" ON IF WIN32 ) -OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O insted of QTKit" OFF IF APPLE ) +OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O" OFF IF APPLE ) +OCV_OPTION(WITH_QTKIT "Use QTKit Video I/O backend" OFF IF APPLE ) OCV_OPTION(WITH_TBB "Include Intel TBB support" OFF IF (NOT IOS) ) OCV_OPTION(WITH_OPENMP "Include OpenMP support" OFF) OCV_OPTION(WITH_CSTRIPES "Include C= support" OFF IF WIN32 ) @@ -879,10 +880,6 @@ if(ANDROID) endif() endif() -if(DEFINED WITH_AVFOUNDATION) - status(" AVFoundation:" WITH_AVFOUNDATION THEN YES ELSE NO) -endif(DEFINED WITH_AVFOUNDATION) - if(DEFINED WITH_FFMPEG) if(WIN32) status(" FFMPEG:" WITH_FFMPEG THEN "YES (prebuilt binaries)" ELSE NO) @@ -923,10 +920,15 @@ if(DEFINED WITH_GIGEAPI) status(" GigEVisionSDK:" HAVE_GIGE_API THEN YES ELSE NO) endif(DEFINED WITH_GIGEAPI) -if(DEFINED WITH_QUICKTIME) +if(DEFINED APPLE) + status(" AVFoundation:" HAVE_AVFOUNDATION THEN YES ELSE NO) + if(WITH_QUICKTIME OR HAVE_QUICKTIME) status(" QuickTime:" HAVE_QUICKTIME THEN YES ELSE NO) - status(" QTKit:" HAVE_QTKIT THEN YES ELSE NO) -endif(DEFINED WITH_QUICKTIME) + endif() + if(WITH_QTKIT OR HAVE_QTKIT) + status(" QTKit:" HAVE_QTKIT THEN "YES (deprecated)" ELSE NO) + endif() +endif(DEFINED APPLE) if(DEFINED WITH_UNICAP) status(" UniCap:" HAVE_UNICAP THEN "YES (ver ${ALIASOF_libunicap_VERSION})" ELSE NO) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 514aa5cd3d..5430759f39 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -273,19 +273,18 @@ if(WIN32) endif() endif(WIN32) -# --- Apple AV Foundation --- -if(WITH_AVFOUNDATION) - set(HAVE_AVFOUNDATION YES) -endif() - -# --- QuickTime --- -if (NOT IOS) - if(WITH_QUICKTIME) - set(HAVE_QUICKTIME YES) - elseif(APPLE) - set(HAVE_QTKIT YES) +if(APPLE) + if(WITH_AVFOUNDATION) + set(HAVE_AVFOUNDATION YES) endif() -endif() + if(NOT IOS) + if(WITH_QUICKTIME) + set(HAVE_QUICKTIME YES) + elseif(WITH_QTKIT) + set(HAVE_QTKIT YES) + endif() + endif() +endif(APPLE) # --- Intel Perceptual Computing SDK --- if(WITH_INTELPERC) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index 44cf98c613..789232141e 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -215,8 +215,13 @@ if(HAVE_IMAGEIO AND IOS) endif() if(HAVE_AVFOUNDATION) - list(APPEND highgui_srcs src/cap_avfoundation.mm) - list(APPEND HIGHGUI_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") + if(IOS) + list(APPEND highgui_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation.mm) + list(APPEND HIGHGUI_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") + else() + list(APPEND highgui_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_avfoundation_mac.mm) + list(APPEND HIGHGUI_LIBRARIES "-framework Cocoa" "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore") + endif() endif() if(HAVE_QUICKTIME) diff --git a/modules/highgui/src/cap_avfoundation_mac.mm b/modules/highgui/src/cap_avfoundation_mac.mm index 8c30506400..a7b889522f 100644 --- a/modules/highgui/src/cap_avfoundation_mac.mm +++ b/modules/highgui/src/cap_avfoundation_mac.mm @@ -155,7 +155,9 @@ private: uint8_t *mOutImagedata; IplImage *mOutImage; size_t currSize; +/* int mMode; +*/ int mFormat; bool setupReadingAt(CMTime position); @@ -677,7 +679,9 @@ CvCaptureFile::CvCaptureFile(const char* filename) { mOutImage = NULL; mOutImagedata = NULL; currSize = 0; +/* mMode = CV_CAP_MODE_BGR; +*/ mFormat = CV_8UC3; mCurrentSampleBuffer = NULL; mGrabbedPixels = NULL; @@ -741,12 +745,15 @@ bool CvCaptureFile::setupReadingAt(CMTime position) { // Capture in a pixel format that can be converted efficiently to the output mode. OSType pixelFormat; +/* if (mMode == CV_CAP_MODE_BGR || mMode == CV_CAP_MODE_RGB) { +*/ // For CV_CAP_MODE_BGR, read frames as BGRA (AV Foundation's YUV->RGB conversion is slightly faster than OpenCV's CV_YUV2BGR_YV12) // kCVPixelFormatType_32ABGR is reportedly faster on OS X, but OpenCV doesn't have a CV_ABGR2BGR conversion. // kCVPixelFormatType_24RGB is significanly slower than kCVPixelFormatType_32BGRA. pixelFormat = kCVPixelFormatType_32BGRA; mFormat = CV_8UC3; +/* } else if (mMode == CV_CAP_MODE_GRAY) { // For CV_CAP_MODE_GRAY, read frames as 420v (faster than 420f or 422 -- at least for H.264 files) pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; @@ -759,6 +766,7 @@ bool CvCaptureFile::setupReadingAt(CMTime position) { fprintf(stderr, "VIDEOIO ERROR: AVF Mac: Unsupported mode: %d\n", mMode); return false; } +*/ NSDictionary *settings = @{ @@ -848,8 +856,11 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { // Output image paramaters. int outChannels; +/* if (mMode == CV_CAP_MODE_BGR || mMode == CV_CAP_MODE_RGB) { +*/ outChannels = 3; +/* } else if (mMode == CV_CAP_MODE_GRAY) { outChannels = 1; } else if (mMode == CV_CAP_MODE_YUYV) { @@ -861,6 +872,7 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { mGrabbedPixels = NULL; return 0; } +*/ if ( currSize != width*outChannels*height ) { currSize = width*outChannels*height; @@ -888,8 +900,11 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { if ( pixelFormat == kCVPixelFormatType_32BGRA ) { deviceChannels = 4; +/* if (mMode == CV_CAP_MODE_BGR) { +*/ cvtCode = CV_BGRA2BGR; +/* } else if (mMode == CV_CAP_MODE_RGB) { cvtCode = CV_BGRA2RGB; } else if (mMode == CV_CAP_MODE_GRAY) { @@ -901,11 +916,15 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); return 0; } +*/ } else if ( pixelFormat == kCVPixelFormatType_24RGB ) { deviceChannels = 3; +/* if (mMode == CV_CAP_MODE_BGR) { +*/ cvtCode = CV_RGB2BGR; +/* } else if (mMode == CV_CAP_MODE_RGB) { cvtCode = 0; } else if (mMode == CV_CAP_MODE_GRAY) { @@ -917,11 +936,15 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); return 0; } +*/ } else if ( pixelFormat == kCVPixelFormatType_422YpCbCr8 ) { // 422 (2vuy, UYVY) deviceChannels = 2; +/* if (mMode == CV_CAP_MODE_BGR) { +*/ cvtCode = CV_YUV2BGR_UYVY; +/* } else if (mMode == CV_CAP_MODE_RGB) { cvtCode = CV_YUV2RGB_UYVY; } else if (mMode == CV_CAP_MODE_GRAY) { @@ -935,6 +958,7 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); return 0; } +*/ } else if ( pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || // 420v pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ) { // 420f // cvCvtColor(CV_YUV2GRAY_420) is expecting a single buffer with both the Y plane and the CrCb planes. @@ -942,8 +966,11 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { height = height * 3 / 2; deviceChannels = 1; +/* if (mMode == CV_CAP_MODE_BGR) { +*/ cvtCode = CV_YUV2BGR_YV12; +/* } else if (mMode == CV_CAP_MODE_RGB) { cvtCode = CV_YUV2RGB_YV12; } else if (mMode == CV_CAP_MODE_GRAY) { @@ -955,6 +982,7 @@ IplImage* CvCaptureFile::retrieveFramePixelBuffer() { fprintf(stderr, "OpenCV: unsupported pixel conversion mode\n"); return 0; } +*/ } else { fprintf(stderr, "OpenCV: unsupported pixel format 0x%08X\n", pixelFormat); CVPixelBufferUnlockBaseAddress(mGrabbedPixels, 0); @@ -1020,8 +1048,10 @@ double CvCaptureFile::getProperty(int property_id) const{ return round((t.value * mAssetTrack.nominalFrameRate) / double(t.timescale)); case CV_CAP_PROP_FORMAT: return mFormat; +/* case CV_CAP_PROP_MODE: return mMode; +*/ default: break; } @@ -1054,6 +1084,7 @@ bool CvCaptureFile::setProperty(int property_id, double value) { setupReadingAt(t); retval = true; break; +/* case CV_CAP_PROP_MODE: int mode; mode = cvRound(value); @@ -1076,6 +1107,7 @@ bool CvCaptureFile::setProperty(int property_id, double value) { } } break; +*/ default: break; }