Skip to content

Commit

Permalink
ios: add video implementation
Browse files Browse the repository at this point in the history
- adds a slightly altered version of the android video implementation,
  as a swift AVFoundation implementation will be used in the ios client
  to enumerate the video input devices.

Change-Id: I7c16fc39c5d22e54fb146881150b6cbcfddb7806
  • Loading branch information
atraczyk committed Jan 12, 2018
1 parent c27d213 commit cbff7d9
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 11 deletions.
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ AC_CONFIG_FILES([Makefile \
src/media/video/v4l2/Makefile \
src/media/video/androidvideo/Makefile \
src/media/video/osxvideo/Makefile \
src/media/video/iosvideo/Makefile \
src/media/video/winvideo/Makefile \
src/security/Makefile \
src/upnp/Makefile \
Expand Down
4 changes: 4 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ if HAVE_OSX
RING_VIDEO_LIBS+= \
./media/video/osxvideo/libosxvideo.la
endif
if HAVE_IOS
RING_VIDEO_LIBS+= \
./media/video/iosvideo/libiosvideo.la
endif
if HAVE_WIN32
RING_VIDEO_LIBS+= \
./media/video/winvideo/libwinvideo.la
Expand Down
2 changes: 1 addition & 1 deletion src/client/videomanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ setDecodingAccelerated(bool state)
#endif
}

#if defined(__ANDROID__) || defined(RING_UWP)
#if defined(__ANDROID__) || defined(RING_UWP) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
void
addVideoDevice(const std::string &node, std::vector<std::map<std::string, std::string>> const * devInfo)
{
Expand Down
6 changes: 5 additions & 1 deletion src/dring/videomanager_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@

#include "dring.h"

#if __APPLE__
#import "TargetConditionals.h"
#endif

namespace DRing {

/* FrameBuffer is a generic video frame container */
Expand Down Expand Up @@ -70,7 +74,7 @@ bool switchInput(const std::string& resource);
bool switchToCamera();
void registerSinkTarget(const std::string& sinkId, const SinkTarget& target);

#if defined(__ANDROID__) || defined(RING_UWP)
#if defined(__ANDROID__) || defined(RING_UWP) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
void addVideoDevice(const std::string &node, const std::vector<std::map<std::string, std::string>>* devInfo=nullptr);
void removeVideoDevice(const std::string &node);
void* obtainFrame(int length);
Expand Down
2 changes: 1 addition & 1 deletion src/media/media_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
class AVFrame;

namespace DRing {
class FrameBuffer; // from dring/videomanager_interface.h
struct FrameBuffer; // from dring/videomanager_interface.h
}

namespace ring {
Expand Down
5 changes: 5 additions & 0 deletions src/media/video/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ SUBDIRS= \
osxvideo
endif

if HAVE_IOS
SUBDIRS= \
iosvideo
endif

if HAVE_WIN32
SUBDIRS= \
winvideo
Expand Down
10 changes: 10 additions & 0 deletions src/media/video/iosvideo/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
include $(top_srcdir)/globals.mk

noinst_LTLIBRARIES = libiosvideo.la

libiosvideo_la_SOURCES = \
video_device_impl.cpp \
video_device_monitor_impl.cpp

#AM_CXXFLAGS = @UDEV_CFLAGS@
#libiosvideo_la_LIBADD = @UDEV_LIBS@
216 changes: 216 additions & 0 deletions src/media/video/iosvideo/video_device_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/*
* Copyright (C) 2015-2017 Savoir-faire Linux Inc.
*
* Author: Rafaël Carré <rafael.carre@savoirfairelinux.com>
* Author: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* This program is free 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <array>

#include "logger.h"
#include "../video_device.h"

#include "client/ring_signal.h"

namespace ring { namespace video {

typedef struct
{
std::string name;
enum VideoPixelFormat ring_format;
} ios_fmt;

static const std::array<ios_fmt, 4> ios_formats
{
ios_fmt { "RGBA", VIDEO_PIXFMT_RGBA },
ios_fmt { "BGRA", VIDEO_PIXFMT_BGRA },
ios_fmt { "YUV420P", VIDEO_PIXFMT_YUV420P }
};

class VideoDeviceImpl
{
public:
VideoDeviceImpl(const std::string& path, const std::vector<std::map<std::string, std::string>>& devInfo);

std::string name;

DeviceParams getDeviceParams() const;

void setDeviceParams(const DeviceParams&);
void selectFormat();

std::vector<VideoSize> getSizeList() const;
std::vector<FrameRate> getRateList() const;

private:

VideoSize getSize(VideoSize size) const;
FrameRate getRate(FrameRate rate) const;

std::vector<std::string> formats_ {};
std::vector<VideoSize> sizes_ {};
std::vector<FrameRate> rates_ {};

const ios_fmt* fmt_ {nullptr};
VideoSize size_ {};
FrameRate rate_ {};

};

void
VideoDeviceImpl::selectFormat()
{
unsigned best = UINT_MAX;
for(auto fmt : formats_) {
auto f = ios_formats.begin();
for (; f != ios_formats.end(); ++f) {
if (f->name == fmt) {
auto pos = std::distance(ios_formats.begin(), f);
if (pos < best)
best = pos;
break;
}
}
if (f == ios_formats.end())
RING_WARN("Video: No format matching %s", fmt.c_str());
}

if (best != UINT_MAX) {
fmt_ = &ios_formats[best];
RING_DBG("Video: picked format %s", fmt_->name.c_str());
}
else {
fmt_ = &ios_formats[0];
RING_ERR("Video: Could not find a known format to use");
}
}

VideoDeviceImpl::VideoDeviceImpl(const std::string& path, const std::vector<std::map<std::string, std::string>>& devInfo)
: name(path)
{
for (auto& setting : devInfo) {
formats_.emplace_back(setting.at("format"));
sizes_.emplace_back(std::stoi(setting.at("width")), std::stoi(setting.at("height")));
rates_.emplace_back(std::stoi(setting.at("rate")), 1);
}
selectFormat();
}

VideoSize
VideoDeviceImpl::getSize(VideoSize size) const
{
for (const auto &iter : sizes_) {
if (iter == size)
return iter;
}

return sizes_.empty() ? VideoSize{0, 0} : sizes_.back();
}

FrameRate
VideoDeviceImpl::getRate(FrameRate rate) const
{
for (const auto &iter : rates_) {
if (iter == rate)
return iter;
}

return rates_.empty() ? FrameRate{0, 0} : rates_.back();
}

std::vector<VideoSize>
VideoDeviceImpl::getSizeList() const
{
return sizes_;
}

std::vector<FrameRate>
VideoDeviceImpl::getRateList() const
{
return rates_;
}

DeviceParams
VideoDeviceImpl::getDeviceParams() const
{
DeviceParams params;
std::stringstream ss1, ss2;

ss1 << fmt_->ring_format;
ss1 >> params.format;

params.name = name;
params.input = name;
params.channel = 0;
params.width = size_.first;
params.height = size_.second;
params.framerate = rate_;

return params;
}

void
VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
{
size_ = getSize({params.width, params.height});
rate_ = getRate(params.framerate);
emitSignal<DRing::VideoSignal::ParametersChanged>(name);
}

VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>& devInfo)
: deviceImpl_(new VideoDeviceImpl(path, devInfo))
{
node_ = path;
name = deviceImpl_->name;
}

DeviceParams
VideoDevice::getDeviceParams() const
{
return deviceImpl_->getDeviceParams();
}

void
VideoDevice::setDeviceParams(const DeviceParams& params)
{
return deviceImpl_->setDeviceParams(params);
}

std::vector<std::string>
VideoDevice::getChannelList() const
{
return {"default"};
}

std::vector<VideoSize>
VideoDevice::getSizeList(const std::string& channel) const
{
return deviceImpl_->getSizeList();
}

std::vector<FrameRate>
VideoDevice::getRateList(const std::string& channel, VideoSize size) const
{
return deviceImpl_->getRateList();
}

VideoDevice::~VideoDevice()
{}

}} // namespace ring::video

96 changes: 96 additions & 0 deletions src/media/video/iosvideo/video_device_monitor_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (C) 2015-2017 Savoir-faire Linux Inc.
*
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
* Author: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com>
*
* This program is free 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <mutex>
#include <thread>

#include "../video_device_monitor.h"
#include "logger.h"
#include "noncopyable.h"

namespace ring { namespace video {

class VideoDeviceMonitorImpl
{
public:
/*
* This is the only restriction to the pImpl design:
* as the Linux implementation has a thread, it needs a way to notify
* devices addition and deletion.
*
* This class should maybe inherit from VideoDeviceMonitor instead of
* being its pImpl.
*/
VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor);
~VideoDeviceMonitorImpl();

void start();

private:
NON_COPYABLE(VideoDeviceMonitorImpl);

VideoDeviceMonitor* monitor_;

void run();

mutable std::mutex mutex_;
bool probing_;
std::thread thread_;
};

VideoDeviceMonitorImpl::VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor)
: monitor_(monitor)
, mutex_()
, thread_()
{}

void
VideoDeviceMonitorImpl::start()
{
probing_ = true;
thread_ = std::thread(&VideoDeviceMonitorImpl::run, this);
}

VideoDeviceMonitorImpl::~VideoDeviceMonitorImpl()
{
probing_ = false;
if (thread_.joinable())
thread_.join();
}

void
VideoDeviceMonitorImpl::run()
{
}

VideoDeviceMonitor::VideoDeviceMonitor()
: preferences_()
, devices_()
, monitorImpl_(new VideoDeviceMonitorImpl(this))
{
monitorImpl_->start();
}

VideoDeviceMonitor::~VideoDeviceMonitor()
{}

}} // namespace ring::video

Loading

0 comments on commit cbff7d9

Please sign in to comment.