blob: f1ed03c0ebff2f87fc12de013b669179b276c3c9 [file] [log] [blame]
Alexandre Lisionbe732d42015-02-18 11:48:42 -05001/*
Guillaume Roguez5236ab02015-09-21 12:44:55 -04002 * Copyright (C) 2015 Savoir-faire Linux Inc.
3 *
Alexandre Lisionbe732d42015-02-18 11:48:42 -05004 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Alexandre Lisionbe732d42015-02-18 11:48:42 -050019 */
20
21#include <algorithm>
22#include <cassert>
23#include <climits>
24#include <map>
25#include <string>
26#include <sstream>
27#include <stdexcept>
28#include <string>
29#include <vector>
30
31#include "logger.h"
32#include "../video_device.h"
33
34#import <AVFoundation/AVFoundation.h>
35
36namespace ring { namespace video {
37
38class VideoDeviceImpl {
39 public:
40 /**
41 * @throw std::runtime_error
42 */
43 VideoDeviceImpl(const std::string& path);
44
45 std::string device;
46 std::string name;
47
48 std::vector<std::string> getChannelList() const;
49 std::vector<std::string> getSizeList(const std::string& channel) const;
50 std::vector<std::string> getSizeList() const;
51 std::vector<std::string> getRateList(const std::string& channel, const std::string& size) const;
52 float getRate(unsigned rate) const;
53
54 VideoSettings getSettings() const;
55 void applySettings(VideoSettings settings);
56
57 DeviceParams getDeviceParams() const;
58
59 private:
60 AVCaptureDevice* avDevice_;
61};
62
63VideoDeviceImpl::VideoDeviceImpl(const std::string& uniqueID)
64 : device(uniqueID)
65 , avDevice_([AVCaptureDevice deviceWithUniqueID:
66 [NSString stringWithCString:uniqueID.c_str() encoding:[NSString defaultCStringEncoding]]])
67{
68 name = [[avDevice_ localizedName] UTF8String];
69 // Set default settings
70 applySettings(VideoSettings());
71}
72
73void
74VideoDeviceImpl::applySettings(VideoSettings settings)
75{
76//TODO: not supported for now on OSX
77// Set preferences or fallback to defaults.
78// channel_ = getChannel(settings["channel"]);
79// size_ = channel_.getSize(settings["size"]);
80// rate_ = size_.getRate(settings["rate"]);
81}
82
83DeviceParams
84VideoDeviceImpl::getDeviceParams() const
85{
86 DeviceParams params;
87 params.input = "[" + device + "]";
88 params.format = "avfoundation";
89// No channel support for now
90// params.channel = channel_.idx;
91 auto format = [avDevice_ activeFormat];
92 CMVideoDimensions dimensions =
93 CMVideoFormatDescriptionGetDimensions(format.formatDescription);
94 params.width = dimensions.width;
95 params.height = dimensions.height;
96 auto frameRate = (AVFrameRateRange*)
97 [format.videoSupportedFrameRateRanges objectAtIndex:0];
98 params.framerate = frameRate.maxFrameRate;
99 return params;
100}
101
102VideoSettings
103VideoDeviceImpl::getSettings() const
104{
105 VideoSettings settings;
106
107 settings.name = [[avDevice_ localizedName] UTF8String];
108
109 return settings;
110}
111
112VideoDevice::VideoDevice(const std::string& path) :
113 deviceImpl_(new VideoDeviceImpl(path))
114{
115 node_ = path;
116 name = deviceImpl_->name;
117}
118
119DeviceParams
120VideoDevice::getDeviceParams() const
121{
122 return deviceImpl_->getDeviceParams();
123}
124
125void
126VideoDevice::applySettings(VideoSettings settings)
127{
128 deviceImpl_->applySettings(settings);
129}
130
131VideoSettings
132VideoDevice::getSettings() const
133{
134 return deviceImpl_->getSettings();
135}
136
137std::vector<std::string>
138VideoDeviceImpl::getSizeList() const
139{
140 return getSizeList("default");
141}
142
143std::vector<std::string>
144VideoDeviceImpl::getRateList(const std::string& channel, const std::string& size) const
145{
146 auto format = [avDevice_ activeFormat];
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500147 std::vector<std::string> v;
Alexandre Lision4bb2a502015-03-25 15:49:27 -0400148
149 for (AVFrameRateRange* frameRateRange in format.videoSupportedFrameRateRanges) {
150 std::stringstream ss;
151 ss << frameRateRange.maxFrameRate;
152 v.push_back(ss.str());
153 }
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500154 return v;
155}
156
157std::vector<std::string>
158VideoDeviceImpl::getSizeList(const std::string& channel) const
159{
160 std::vector<std::string> v;
161
Alexandre Lision4bb2a502015-03-25 15:49:27 -0400162 for (AVCaptureDeviceFormat* format in avDevice_.formats) {
163 std::stringstream ss;
164 auto dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
165 ss << dimensions.width << "x" << dimensions.height;
166 v.push_back(ss.str());
167 }
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500168 return v;
169}
170
171std::vector<std::string> VideoDeviceImpl::getChannelList() const
172{
173 return {"default"};
174}
175
176DRing::VideoCapabilities
177VideoDevice::getCapabilities() const
178{
179 DRing::VideoCapabilities cap;
180
181 for (const auto& chan : deviceImpl_->getChannelList())
182 for (const auto& size : deviceImpl_->getSizeList(chan))
183 cap[chan][size] = deviceImpl_->getRateList(chan, size);
184
185 return cap;
186}
187
188VideoDevice::~VideoDevice()
189{}
190
191}} // namespace ring::video