From cf6623cfc8a50a9d1fdd3e7293ccd13abc23c198 Mon Sep 17 00:00:00 2001 From: Andrew Novikov Date: Sun, 20 Dec 2015 22:17:14 +0300 Subject: [PATCH 1/4] Implemented enumeration of video devices. --- qtox.pro | 8 ++++-- src/platform/camera/avfoundation.h | 37 +++++++++++++++++++++++++ src/platform/camera/avfoundation.mm | 42 +++++++++++++++++++++++++++++ src/video/cameradevice.cpp | 7 +++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/platform/camera/avfoundation.h create mode 100644 src/platform/camera/avfoundation.mm diff --git a/qtox.pro b/qtox.pro index 2cc0f86ec..cad757550 100644 --- a/qtox.pro +++ b/qtox.pro @@ -159,7 +159,7 @@ win32 { ICON = img/icons/qtox.icns QMAKE_INFO_PLIST = osx/info.plist QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 - LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -mmacosx-version-min=10.7 + LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -framework AVFoundation -framework Foundation -mmacosx-version-min=10.7 LIBS += -lqrencode -lsqlcipher contains(DEFINES, QTOX_PLATFORM_EXT) { LIBS += -framework IOKit -framework CoreFoundation } contains(DEFINES, QTOX_FILTER_AUDIO) { LIBS += -lfilteraudio } @@ -462,7 +462,11 @@ macx { src/platform/install_osx.cpp HEADERS += \ - src/platform/install_osx.h + src/platform/install_osx.h \ + src/platform/camera/avfoundation.h + + OBJECTIVE_SOURCES += \ + src/platform/camera/avfoundation.mm } SOURCES += \ diff --git a/src/platform/camera/avfoundation.h b/src/platform/camera/avfoundation.h new file mode 100644 index 000000000..942074eca --- /dev/null +++ b/src/platform/camera/avfoundation.h @@ -0,0 +1,37 @@ +/* + Copyright © 2015 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ +#ifndef AVFOUNDATION_H +#define AVFOUNDATION_H + +#include +#include +#include +#include "src/video/videomode.h" + +#ifndef Q_OS_MACX +#error "This file is only meant to be compiled for Mac OS X targets" +#endif + +namespace avfoundation +{ + QVector getDeviceModes(QString devName); + QVector> getDeviceList(); +} + +#endif // AVFOUNDATION_H diff --git a/src/platform/camera/avfoundation.mm b/src/platform/camera/avfoundation.mm new file mode 100644 index 000000000..ce008b9e7 --- /dev/null +++ b/src/platform/camera/avfoundation.mm @@ -0,0 +1,42 @@ +/* + Copyright (c) 2014 Thilo Borgmann + Copyright © 2015 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . + */ + +#include "avfoundation.h" + +#import + +QVector > avfoundation::getDeviceList() +{ + QVector > result; + + NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + for (AVCaptureDevice* device in devices) { + result.append({ QString::number([devices indexOfObject:device]), [[device localizedName] UTF8String] }); + } + + return result; +} + +QVector avfoundation::getDeviceModes(QString devName) +{ + QVector result; + + return result; +} diff --git a/src/video/cameradevice.cpp b/src/video/cameradevice.cpp index 96c1ec3fa..23869f2c9 100644 --- a/src/video/cameradevice.cpp +++ b/src/video/cameradevice.cpp @@ -34,6 +34,9 @@ extern "C" { #ifdef Q_OS_LINUX #include "src/platform/camera/v4l2.h" #endif +#ifdef Q_OS_OSX +#include "src/platform/camera/avfoundation.h" +#endif QHash CameraDevice::openDevices; QMutex CameraDevice::openDeviceLock, CameraDevice::iformatLock; @@ -281,6 +284,10 @@ QVector> CameraDevice::getDeviceList() #ifdef Q_OS_LINUX else if (iformat->name == QString("video4linux2,v4l2")) devices += v4l2::getDeviceList(); +#endif +#ifdef Q_OS_OSX + else if (iformat->name == QString("avfoundation")) + devices += avfoundation::getDeviceList(); #endif else devices += getRawDeviceListGeneric(); From 1dac0d09c8fe172e73325d52f79bd5d1fa32ee76 Mon Sep 17 00:00:00 2001 From: Andrew Novikov Date: Sun, 20 Dec 2015 22:22:56 +0300 Subject: [PATCH 2/4] Rearranged link dependencies. --- qtox.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qtox.pro b/qtox.pro index cad757550..19b2817eb 100644 --- a/qtox.pro +++ b/qtox.pro @@ -159,7 +159,8 @@ win32 { ICON = img/icons/qtox.icns QMAKE_INFO_PLIST = osx/info.plist QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 - LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -framework AVFoundation -framework Foundation -mmacosx-version-min=10.7 + LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -mmacosx-version-min=10.7 + LIBS += -framework AVFoundation -framework Foundation LIBS += -lqrencode -lsqlcipher contains(DEFINES, QTOX_PLATFORM_EXT) { LIBS += -framework IOKit -framework CoreFoundation } contains(DEFINES, QTOX_FILTER_AUDIO) { LIBS += -lfilteraudio } From 9d430626397bb66021949985d9ebbd099870cdea Mon Sep 17 00:00:00 2001 From: Andrew Novikov Date: Mon, 21 Dec 2015 00:44:53 +0300 Subject: [PATCH 3/4] Changed the type of VideoMode::FPS to float: this is necessary for Mac OS X which uses frame rates like 29.97 --- src/video/videomode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/videomode.h b/src/video/videomode.h index ff76c063b..d3e17f98b 100644 --- a/src/video/videomode.h +++ b/src/video/videomode.h @@ -25,7 +25,7 @@ struct VideoMode { unsigned short width, height; ///< Displayed video resolution (NOT frame resolution) - unsigned short FPS; ///< Max frames per second supported by the device at this resolution + float FPS; ///< Max frames per second supported by the device at this resolution /// All zeros means a default/unspecified mode operator bool() const From cc64db3f275563dd83225cf61bcc7eac6cf85cba Mon Sep 17 00:00:00 2001 From: Andrew Novikov Date: Mon, 21 Dec 2015 00:50:51 +0300 Subject: [PATCH 4/4] Implemented listing and setting video modes on Mac OS X --- qtox.pro | 2 +- src/platform/camera/avfoundation.mm | 30 ++++++++++++++++++++++++++++- src/video/cameradevice.cpp | 11 +++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/qtox.pro b/qtox.pro index 19b2817eb..960a78412 100644 --- a/qtox.pro +++ b/qtox.pro @@ -160,7 +160,7 @@ win32 { QMAKE_INFO_PLIST = osx/info.plist QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -mmacosx-version-min=10.7 - LIBS += -framework AVFoundation -framework Foundation + LIBS += -framework AVFoundation -framework Foundation -framework CoreMedia LIBS += -lqrencode -lsqlcipher contains(DEFINES, QTOX_PLATFORM_EXT) { LIBS += -framework IOKit -framework CoreFoundation } contains(DEFINES, QTOX_FILTER_AUDIO) { LIBS += -lfilteraudio } diff --git a/src/platform/camera/avfoundation.mm b/src/platform/camera/avfoundation.mm index ce008b9e7..5f625e17e 100644 --- a/src/platform/camera/avfoundation.mm +++ b/src/platform/camera/avfoundation.mm @@ -28,7 +28,7 @@ QVector > avfoundation::getDeviceList() NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice* device in devices) { - result.append({ QString::number([devices indexOfObject:device]), [[device localizedName] UTF8String] }); + result.append({ QString::fromUtf8([[device uniqueID] UTF8String]), QString::fromUtf8([[device localizedName] UTF8String]) }); } return result; @@ -38,5 +38,33 @@ QVector avfoundation::getDeviceModes(QString devName) { QVector result; + NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + AVCaptureDevice* device = nil; + + for (AVCaptureDevice* dev in devices) { + if (devName == QString::fromUtf8([[dev uniqueID] UTF8String])) { + device = dev; + break; + } + } + if (device == nil) { + return result; + } + + for (AVCaptureDeviceFormat* format in [device formats]) { + CMFormatDescriptionRef formatDescription; + CMVideoDimensions dimensions; + formatDescription = (CMFormatDescriptionRef)[format performSelector:@selector(formatDescription)]; + dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription); + + for (AVFrameRateRange* range in format.videoSupportedFrameRateRanges) { + VideoMode mode; + mode.width = dimensions.width; + mode.height = dimensions.height; + mode.FPS = range.maxFrameRate; + result.append(mode); + } + } + return result; } diff --git a/src/video/cameradevice.cpp b/src/video/cameradevice.cpp index 23869f2c9..d9cab566a 100644 --- a/src/video/cameradevice.cpp +++ b/src/video/cameradevice.cpp @@ -165,6 +165,13 @@ CameraDevice* CameraDevice::open(QString devName, VideoMode mode) av_dict_set(&options, "video_size", QString("%1x%2").arg(mode.width).arg(mode.height).toStdString().c_str(), 0); av_dict_set(&options, "framerate", QString().setNum(mode.FPS).toStdString().c_str(), 0); } +#endif +#ifdef Q_OS_OSX + else if (iformat->name == QString("avfoundation") && mode) + { + av_dict_set(&options, "video_size", QString("%1x%2").arg(mode.width).arg(mode.height).toStdString().c_str(), 0); + av_dict_set(&options, "framerate", QString().setNum(mode.FPS).toStdString().c_str(), 0); + } #endif else if (mode) { @@ -331,6 +338,10 @@ QVector CameraDevice::getVideoModes(QString devName) #ifdef Q_OS_LINUX else if (iformat->name == QString("video4linux2,v4l2")) return v4l2::getDeviceModes(devName); +#endif +#ifdef Q_OS_OSX + else if (iformat->name == QString("avfoundation")) + return avfoundation::getDeviceModes(devName); #endif else qWarning() << "Video mode listing not implemented for input "<name;