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