blob: 5fc7774e8b008aa6e039601bed7e85c97f93e336 [file] [log] [blame]
Alexandre Lisionbe732d42015-02-18 11:48:42 -05001/*
Guillaume Rogueza5ded292017-01-03 14:55:42 -05002 * Copyright (C) 2015-2017 Savoir-faire Linux Inc.
Guillaume Roguez5236ab02015-09-21 12:44:55 -04003 *
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;
Adrien Béraudbdd139c2016-02-17 13:52:44 -050049 std::vector<VideoSize> getSizeList(const std::string& channel) const;
50 std::vector<VideoSize> getSizeList() const;
51 std::vector<FrameRate> getRateList(const std::string& channel, VideoSize size) const;
Alexandre Lisionbe732d42015-02-18 11:48:42 -050052
53 DeviceParams getDeviceParams() const;
Adrien Béraudbdd139c2016-02-17 13:52:44 -050054 void setDeviceParams(const DeviceParams&);
Alexandre Lisionbe732d42015-02-18 11:48:42 -050055
56 private:
Adrien Béraudbdd139c2016-02-17 13:52:44 -050057 VideoSize extractSize(VideoSize) const;
Alexandre Lisione0676bf2015-12-08 10:35:27 -050058
Alexandre Lisionbe732d42015-02-18 11:48:42 -050059 AVCaptureDevice* avDevice_;
Adrien Béraudbdd139c2016-02-17 13:52:44 -050060 std::vector<VideoSize> available_sizes_;
61 VideoSize current_size_;
Alexandre Lisionbe732d42015-02-18 11:48:42 -050062};
63
64VideoDeviceImpl::VideoDeviceImpl(const std::string& uniqueID)
65 : device(uniqueID)
Alexandre Lisione0676bf2015-12-08 10:35:27 -050066 , current_size_(-1, -1)
Alexandre Lisionbe732d42015-02-18 11:48:42 -050067 , avDevice_([AVCaptureDevice deviceWithUniqueID:
68 [NSString stringWithCString:uniqueID.c_str() encoding:[NSString defaultCStringEncoding]]])
69{
70 name = [[avDevice_ localizedName] UTF8String];
Alexandre Lisione0676bf2015-12-08 10:35:27 -050071
Adrien Béraudbdd139c2016-02-17 13:52:44 -050072 available_sizes_.reserve(avDevice_.formats.count);
Alexandre Lisione0676bf2015-12-08 10:35:27 -050073 for (AVCaptureDeviceFormat* format in avDevice_.formats) {
Alexandre Lisione0676bf2015-12-08 10:35:27 -050074 auto dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
Adrien Béraudbdd139c2016-02-17 13:52:44 -050075 available_sizes_.emplace_back(dimensions.width, dimensions.height);
Alexandre Lisione0676bf2015-12-08 10:35:27 -050076 }
Alexandre Lisionbe732d42015-02-18 11:48:42 -050077}
78
Adrien Béraudbdd139c2016-02-17 13:52:44 -050079VideoSize
80VideoDeviceImpl::extractSize(VideoSize size) const
Alexandre Lisione0676bf2015-12-08 10:35:27 -050081{
82 for (const auto item : available_sizes_) {
Adrien Béraudbdd139c2016-02-17 13:52:44 -050083 if (item.first == size.first && item.second == size.second)
Alexandre Lisione0676bf2015-12-08 10:35:27 -050084 return item;
85 }
86
87 // fallback to last size
88 if (!available_sizes_.empty()) {
89 return available_sizes_.back();
90 }
Adrien Béraudbdd139c2016-02-17 13:52:44 -050091 return VideoSize(0, 0);
Alexandre Lisione0676bf2015-12-08 10:35:27 -050092}
93
Alexandre Lisionbe732d42015-02-18 11:48:42 -050094DeviceParams
95VideoDeviceImpl::getDeviceParams() const
96{
97 DeviceParams params;
Adrien Béraudbdd139c2016-02-17 13:52:44 -050098 params.name = [[avDevice_ localizedName] UTF8String];
Alexandre Lisiond0cb3372016-05-11 14:33:19 -040099 params.input = device;
philippegorley14084832017-09-25 14:35:17 -0400100 params.format = "avfoundation";
Alexandre Lisione0676bf2015-12-08 10:35:27 -0500101
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500102 params.width = current_size_.first;
103 params.height = current_size_.second;
Alexandre Lisione0676bf2015-12-08 10:35:27 -0500104
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500105 auto format = [avDevice_ activeFormat];
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500106 auto frameRate = (AVFrameRateRange*)
107 [format.videoSupportedFrameRateRanges objectAtIndex:0];
108 params.framerate = frameRate.maxFrameRate;
109 return params;
110}
111
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500112void
113VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500114{
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500115//TODO: add framerate
116// rate_ = size_.getRate(settings["rate"]);
117 current_size_ = extractSize({params.width, params.height});
118}
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500119
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500120std::vector<VideoSize>
121VideoDeviceImpl::getSizeList() const
122{
123 return getSizeList("default");
124}
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500125
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500126std::vector<FrameRate>
127VideoDeviceImpl::getRateList(const std::string& channel, VideoSize size) const
128{
Alexandre Lisiona6d408f2016-02-08 15:29:03 -0500129 auto format = [avDevice_ activeFormat];
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500130 std::vector<FrameRate> v;
131 v.reserve(format.videoSupportedFrameRateRanges.count);
132 for (AVFrameRateRange* frameRateRange in format.videoSupportedFrameRateRanges)
133 v.emplace_back(frameRateRange.maxFrameRate);
134 return v;
135}
Alexandre Lisiona6d408f2016-02-08 15:29:03 -0500136
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500137std::vector<VideoSize>
138VideoDeviceImpl::getSizeList(const std::string& channel) const
139{
140 return available_sizes_;
141}
142
143std::vector<std::string>
144VideoDeviceImpl::getChannelList() const
145{
146 return {"default"};
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500147}
148
atraczyka1b8b132016-12-28 11:51:56 -0500149VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>&) :
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500150 deviceImpl_(new VideoDeviceImpl(path))
151{
152 node_ = path;
153 name = deviceImpl_->name;
154}
155
156DeviceParams
157VideoDevice::getDeviceParams() const
158{
159 return deviceImpl_->getDeviceParams();
160}
161
162void
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500163VideoDevice::setDeviceParams(const DeviceParams& params)
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500164{
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500165 return deviceImpl_->setDeviceParams(params);
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500166}
167
168std::vector<std::string>
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500169VideoDevice::getChannelList() const
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500170{
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500171 return deviceImpl_->getChannelList();
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500172}
173
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500174std::vector<VideoSize>
175VideoDevice::getSizeList(const std::string& channel) const
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500176{
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500177 return deviceImpl_->getSizeList(channel);
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500178}
179
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500180std::vector<FrameRate>
181VideoDevice::getRateList(const std::string& channel, VideoSize size) const
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500182{
Adrien Béraudbdd139c2016-02-17 13:52:44 -0500183 return deviceImpl_->getRateList(channel, size);
Alexandre Lisionbe732d42015-02-18 11:48:42 -0500184}
185
186VideoDevice::~VideoDevice()
187{}
188
189}} // namespace ring::video