Commit 024cdc72 authored by Adrien Béraud's avatar Adrien Béraud Committed by Guillaume Roguez

video: don't use a map to handle parameters

Refs #66381

Change-Id: If3e1a9a3d9b988e2adf84fc284ccb47cadd6c836
parent b989749f
......@@ -109,14 +109,14 @@ getDefaultDevice()
void
setDefaultDevice(const std::string& name)
{
RING_DBG("Setting device to %s", name.c_str());
RING_DBG("Setting default device to %s", name.c_str());
videoManager.videoDeviceMonitor.setDefaultDevice(name);
}
std::map<std::string, std::string>
getSettings(const std::string& name)
{
return videoManager.videoDeviceMonitor.getSettings(name);
return videoManager.videoDeviceMonitor.getSettings(name).to_map();
}
void
......
......@@ -27,6 +27,7 @@ noinst_HEADERS = \
media_decoder.h \
media_encoder.h \
media_io_handle.h \
media_device.h \
media_codec.h \
system_codec_container.h
......
......@@ -41,6 +41,8 @@
#include "media_encoder.h"
#include "media_decoder.h"
#include "media_io_handle.h"
#include "media_device.h"
#include "audio/audiobuffer.h"
#include "audio/ringbufferpool.h"
#include "audio/resampler.h"
......
......@@ -203,21 +203,5 @@ struct MediaDescription {
CryptoAttribute crypto {};
};
/**
* DeviceParams
* Parameters used by MediaDecoder and MediaEncoder
* to open a LibAV device/stream
*/
struct DeviceParams {
std::string input {};
std::string format {};
unsigned width {}, height {};
unsigned framerate {};
std::string video_size {};
std::string channel {};
std::string loop {};
std::string sdp_flags {};
};
}//namespace ring
#endif // __MEDIA_CODEC_H__
......@@ -31,7 +31,7 @@
#include "libav_deps.h" // MUST BE INCLUDED FIRST
#include "media_decoder.h"
#include "media_codec.h"
#include "media_device.h"
#include "media_buffer.h"
#include "media_io_handle.h"
#include "audio/audiobuffer.h"
......@@ -76,9 +76,15 @@ int MediaDecoder::openInput(const DeviceParams& params)
if (!iformat)
RING_WARN("Cannot find format \"%s\"", params.format.c_str());
av_dict_set(&options_, "framerate", ring::to_string(params.framerate).c_str(), 0);
av_dict_set(&options_, "video_size", params.video_size.c_str(), 0);
av_dict_set(&options_, "channel", params.channel.c_str(), 0);
if (params.width and params.height) {
std::stringstream ss;
ss << params.width << "x" << params.height;
av_dict_set(&options_, "video_size", ss.str().c_str(), 0);
}
if (params.framerate)
av_dict_set(&options_, "framerate", ring::to_string(params.framerate).c_str(), 0);
if (params.channel)
av_dict_set(&options_, "channel", ring::to_string(params.channel).c_str(), 0);
av_dict_set(&options_, "loop", params.loop.c_str(), 0);
av_dict_set(&options_, "sdp_flags", params.sdp_flags.c_str(), 0);
......
/*
* Copyright (C) 2015 Savoir-Faire Linux Inc.
* Author: Adrien Béraud <adrien.beraud@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.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#ifndef __MEDIA_DEVICE_H__
#define __MEDIA_DEVICE_H__
#include <string>
namespace ring {
/**
* DeviceParams
* Parameters used by MediaDecoder and MediaEncoder
* to open a LibAV device/stream
*/
struct DeviceParams {
std::string input {}; // Device path (e.g. /dev/video0)
std::string format {};
unsigned width {}, height {};
unsigned framerate {};
unsigned channel {}; // Channel number
std::string loop {};
std::string sdp_flags {};
};
}
#endif // __MEDIA_DEVICE_H__
......@@ -30,6 +30,7 @@
*/
#include "libav_deps.h" // MUST BE INCLUDED FIRST
#include "media_device.h"
#include "media_codec.h"
#include "media_encoder.h"
#include "media_buffer.h"
......
......@@ -38,7 +38,7 @@
int main ()
{
ring::video::VideoDeviceMonitor monitor;
ring::video::VideoRtpSession session("test", {});
ring::video::VideoRtpSession session("test", monitor.getDeviceParams(monitor.getDefaultDevice()));
ring::MediaDescription local {};
local.addr = {AF_INET};
......
......@@ -66,7 +66,7 @@ class VideoV4l2Size {
*/
void getFrameRates(int fd, unsigned int pixel_format);
std::vector<std::string> getRateList() const;
float getRate(const std::string &name) const;
float getRate(unsigned rate) const;
unsigned width;
unsigned height;
......@@ -120,6 +120,8 @@ class VideoDeviceImpl {
VideoSettings getSettings() const;
void applySettings(VideoSettings settings);
DeviceParams getDeviceParams() const;
private:
std::vector<VideoV4l2Channel> channels_;
const VideoV4l2Channel& getChannel(const std::string& name) const;
......@@ -265,12 +267,10 @@ void VideoV4l2Size::getFrameRates(int fd, unsigned int pixel_format)
}
float
VideoV4l2Size::getRate(const string &name) const
VideoV4l2Size::getRate(unsigned rate) const
{
for (const auto& item : rates_) {
stringstream ss;
ss << item;
if (ss.str() == name)
if (item == rate)
return item;
}
......@@ -498,56 +498,37 @@ void
VideoDeviceImpl::applySettings(VideoSettings settings)
{
// Set preferences or fallback to defaults.
channel_ = getChannel(settings["channel"]);
size_ = channel_.getSize(settings["size"]);
rate_ = size_.getRate(settings["rate"]);
channel_ = getChannel(settings.channel);
size_ = channel_.getSize(settings.video_size);
rate_ = size_.getRate(settings.framerate);
}
template <class T>
static inline string to_string(const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
/*
* FIXME the result map has duplicated value, for backward compatibility with
* old methods getPreferences() and getSettings().
*
* A VideoSettings struct might be created with eventually a to_map() method.
*/
VideoSettings
VideoDeviceImpl::getSettings() const
{
VideoSettings settings;
settings["name"] = name;
// Device path (e.g. /dev/video0)
settings["input"] = device;
// Channel number
settings["channel_num"] = to_string(channel_.idx);
settings["channel"] = channel_.name;
// Video size
settings["width"] = to_string(size_.width);
settings["height"] = to_string(size_.height);
settings.name = name;
settings.channel = channel_.name;
stringstream video_size;
video_size << settings["width"];
video_size << "x";
video_size << settings["height"];
settings["video_size"] = video_size.str();
settings["size"] = video_size.str();
// Frame rate
settings["framerate"] = to_string(rate_);
settings["rate"] = to_string(rate_);
video_size << size_.width << "x" << size_.height;
settings.video_size = video_size.str();
settings.framerate = rate_;
return settings;
}
DeviceParams
VideoDeviceImpl::getDeviceParams() const
{
DeviceParams params;
params.input = device;
params.format = "video4linux2";
params.channel = channel_.idx;
params.width = size_.width;
params.height = size_.height;
params.framerate = rate_;
return params;
}
VideoDevice::VideoDevice(const string& path) :
deviceImpl_(new VideoDeviceImpl(path))
{
......@@ -567,6 +548,12 @@ VideoDevice::getSettings() const
return deviceImpl_->getSettings();
}
DeviceParams
VideoDevice::getDeviceParams() const
{
return deviceImpl_->getDeviceParams();
}
DRing::VideoCapabilities
VideoDevice::getCapabilities() const
{
......
/*
* Copyright (C) 2013 Savoir-Faire Linux Inc.
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
* Author: Adrien Béraud <adrien.beraud@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
......@@ -32,6 +33,7 @@
#include "libav_deps.h" // MUST BE INCLUDED FIRST
#include "video_base.h"
#include "media_buffer.h"
#include "string_utils.h"
#include "logger.h"
#include <cassert>
......@@ -83,4 +85,73 @@ VideoGenerator::obtainLastFrame()
return lastFrame_;
}
/*=== VideoSettings =========================================================*/
static std::string
extractString(const std::map<std::string, std::string>& settings, const std::string& key) {
auto i = settings.find(key);
if (i != settings.cend())
return i->second;
return {};
}
static unsigned
extractInt(const std::map<std::string, std::string>& settings, const std::string& key) {
auto i = settings.find(key);
if (i != settings.cend())
return std::stoi(i->second);
return 0;
}
VideoSettings::VideoSettings(const std::map<std::string, std::string>& settings)
{
name = extractString(settings, "name");
channel = extractString(settings, "channel");
video_size = extractString(settings, "size");
framerate = extractInt(settings, "rate");
}
std::map<std::string, std::string>
VideoSettings::to_map() const
{
return {
{"name", name},
{"size", video_size},
{"channel", channel},
{"rate", ring::to_string(framerate)}
};
}
}} // namespace ring::video
namespace YAML {
Node
convert<ring::video::VideoSettings>::encode(const ring::video::VideoSettings& rhs) {
Node node;
node["name"] = rhs.name;
node["video_size"] = rhs.video_size;
node["channel"] = rhs.channel;
node["framerate"] = ring::to_string(rhs.framerate);
return node;
}
bool
convert<ring::video::VideoSettings>::decode(const Node& node, ring::video::VideoSettings& rhs) {
if (not node.IsMap()) {
RING_WARN("Can't decode VideoSettings YAML node");
return false;
}
rhs.name = node["name"].as<std::string>();
rhs.video_size = node["video_size"].as<std::string>();
rhs.channel = node["channel"].as<std::string>();
rhs.framerate = node["framerate"].as<unsigned>();
return true;
}
Emitter& operator << (Emitter& out, const ring::video::VideoSettings& v) {
out << convert<ring::video::VideoSettings>::encode(v);
return out;
}
} // namespace YAML
/*
* Copyright (C) 2013 Savoir-Faire Linux Inc.
* Copyright (C) 2013-2015 Savoir-Faire Linux Inc.
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
* Author: Adrien Béraud <adrien.beraud@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
......@@ -33,6 +34,8 @@
#include "noncopyable.h"
#include <yaml-cpp/yaml.h>
#include <cstdlib>
#include <cstdint>
#include <memory>
......@@ -162,4 +165,28 @@ private:
std::mutex mutex_ = {}; // lock writableFrame_/lastFrame_ access
};
struct VideoSettings
{
VideoSettings() {}
VideoSettings(const std::map<std::string, std::string>& settings);
std::map<std::string, std::string> to_map() const;
std::string name {};
std::string video_size {};
std::string channel {};
unsigned framerate {};
};
}} // namespace ring::video
namespace YAML {
template<>
struct convert<ring::video::VideoSettings> {
static Node encode(const ring::video::VideoSettings& rhs);
static bool decode(const Node& node, ring::video::VideoSettings& rhs);
};
Emitter& operator << (Emitter& out, const ring::video::VideoSettings& v);
} // namespace YAML
......@@ -31,6 +31,9 @@
#ifndef __VIDEO_DEVICE_H__
#define __VIDEO_DEVICE_H__
#include "media/media_device.h"
#include "video_base.h"
#include <map>
#include <memory>
#include <string>
......@@ -39,9 +42,6 @@
namespace ring { namespace video {
typedef std::map<std::string, std::string> VideoSettings;
// FIXME move VideoSettings in video_base since video_decoder (and encoder?) may use it.
class VideoDeviceImpl;
class VideoDevice {
......@@ -76,12 +76,7 @@ public:
DRing::VideoCapabilities getCapabilities() const;
/*
* Get the string/string map of settings for the device.
* The keys are:
* - "channel"
* - "size"
* - "rate"
* - TODO ...
* Get the settings for the device.
*/
VideoSettings getSettings() const;
......@@ -94,6 +89,11 @@ public:
*/
void applySettings(VideoSettings settings);
/**
* Returns the parameters needed for actual use of the device
*/
DeviceParams getDeviceParams() const;
private:
/*
......
......@@ -106,11 +106,19 @@ void
VideoDeviceMonitor::setDefaultDevice(const string& name)
{
const auto it = findDeviceByName(name);
if (it != devices_.end())
defaultDevice_ = it->name;
}
DeviceParams
VideoDeviceMonitor::getDeviceParams(const std::string& name) const
{
const auto itd = findDeviceByName(name);
if (itd == devices_.cend())
return DeviceParams();
return itd->getDeviceParams();
}
static int
getNumber(const string &name, size_t *sharp)
{
......@@ -253,22 +261,17 @@ VideoDeviceMonitor::findDeviceByNode(const string& node) const
vector<VideoSettings>::iterator
VideoDeviceMonitor::findPreferencesByName(const string& name)
{
vector<VideoSettings>::iterator it;
for (it = preferences_.begin(); it != preferences_.end(); ++it)
if ((*it)["name"] == name)
break;
return it;
for (auto it = preferences_.begin(); it != preferences_.end(); ++it)
if (it->name == name) return it;
return preferences_.end();
}
void
VideoDeviceMonitor::overwritePreferences(VideoSettings settings)
{
auto it = findPreferencesByName(settings["name"]);
auto it = findPreferencesByName(settings.name);
if (it != preferences_.end())
preferences_.erase(it);
preferences_.push_back(settings);
}
......@@ -286,21 +289,19 @@ VideoDeviceMonitor::unserialize(const YAML::Node &in)
const auto &node = in[CONFIG_LABEL];
/* load the device list from the "video" YAML section */
auto tmp = preferences_;
yaml_utils::parseValue(node, "devices", tmp);
for (const auto &iter : tmp) {
VideoSettings pref = iter;
const auto& devices = node["devices"];
for (const auto& dev : devices) {
VideoSettings pref = dev.as<VideoSettings>();
if (pref.name.empty())
continue; // discard malformed section
overwritePreferences(pref);
// Restore the device preferences if present
auto itd = findDeviceByName(pref["name"]);
auto itd = findDeviceByName(pref.name);
if (itd != devices_.end())
itd->applySettings(pref);
}
// Restore the default device if present, or select the first one
const string pref = preferences_.empty() ? "" : preferences_[0]["name"];
const string pref = preferences_.empty() ? "" : preferences_[0].name;
const string first = devices_.empty() ? "" : devices_[0].name;
if (findDeviceByName(pref) != devices_.end())
defaultDevice_ = pref;
......
......@@ -2,6 +2,7 @@
* Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Author: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
* Author: Adrien Béraud <adrien.beraud@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
......@@ -68,6 +69,11 @@ class VideoDeviceMonitor : public Serializable
void addDevice(const std::string &node);
void removeDevice(const std::string &node);
/**
* Params for libav
*/
DeviceParams getDeviceParams(const std::string& name) const;
/*
* Interface to load from/store to the (YAML) configuration file.
*/
......
......@@ -41,6 +41,7 @@
#include <map>
#include <string>
#include <sstream>
#include <cassert>
#include <unistd.h>
......@@ -190,18 +191,7 @@ VideoInput::deleteDecoder()
bool
VideoInput::initCamera(const std::string& device)
{
auto map = DRing::getSettings(device);
if (map.empty())
return false;
clearOptions();
decOpts_.input = map["input"];
decOpts_.format = "video4linux2";
decOpts_.channel = map["channel_num"];
decOpts_.framerate = std::stoi(map["framerate"]);
decOpts_.video_size = map["video_size"];
decOpts_ = ring::getVideoDeviceMonitor().getDeviceParams(device);
return true;
}
......@@ -215,11 +205,15 @@ VideoInput::initX11(std::string display)
decOpts_.framerate = 25;
if (space != std::string::npos) {
decOpts_.video_size = display.substr(space + 1);
std::istringstream iss(display.substr(space + 1));
char sep;
iss >> decOpts_.width >> sep >> decOpts_.height;
decOpts_.input = display.erase(space);
} else {
decOpts_.input = display;
decOpts_.video_size = "vga";
//decOpts_.video_size = "vga";
decOpts_.width = 640;
decOpts_.height = 480;
}
return true;
......
......@@ -37,7 +37,7 @@
#include "noncopyable.h"
#include "shm_sink.h"
#include "threadloop.h"
#include "media/media_codec.h" // DeviceParams
#include "media/media_device.h" // DeviceParams
#include <map>
#include <atomic>
......
......@@ -34,6 +34,7 @@
#include "media_codec.h"
#include "media_io_handle.h"
#include "media_device.h"
#include "shm_sink.h"
#include "threadloop.h"
#include "noncopyable.h"
......
......@@ -33,6 +33,7 @@
#define __VIDEO_RTP_SESSION_H__
#include "media/rtp_session.h"
#include "media/media_device.h"
#include "video_base.h"
......
......@@ -53,6 +53,7 @@
#endif
#ifdef RING_VIDEO
#include "client/videomanager.h"
#include "video/video_rtp_session.h"
#include "dring/videomanager_interface.h"
#include <chrono>
......@@ -64,26 +65,8 @@ namespace ring {
static DeviceParams
getVideoSettings()
{
const auto& settings_map = ::DRing::getSettings(DRing::getDefaultDevice());
DeviceParams params;
const auto& input = settings_map.find("input");
if (input != settings_map.cend())
params.input = input->second;
const auto& width = settings_map.find("width");
if (width != settings_map.cend())
params.width = std::stoi(width->second);
const auto& height = settings_map.find("height");
if (height != settings_map.cend())
params.height = std::stoi(height->second);
const auto& framerate = settings_map.find("framerate");
if (framerate != settings_map.cend())
params.framerate = std::stoi(framerate->second);
return params;
const auto& videomon = ring::getVideoDeviceMonitor();
return videomon.getDeviceParams(videomon.getDefaultDevice());
}
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment