Commit a52f3203 authored by Sébastien Blin's avatar Sébastien Blin Committed by Kateryna Kostiuk

api: add new media api

Migrate all media API to new models.

Gitlab: #394
Change-Id: Ida00feb0afefa4f0ce39091811da12097f03ba4d
Reviewed-by: Kateryna Kostiuk<kateryna.kostiuk@savoirfairelinux.com>
parent 5082d678
......@@ -358,6 +358,9 @@ SET( libringclient_LIB_SRCS
src/callbackshandler.cpp
src/behaviorcontroller.cpp
src/datatransfermodel.cpp
src/newvideo.cpp
src/shmrenderer.cpp
src/directrenderer.cpp
#Data collections
src/transitionalpersonbackend.cpp
......@@ -410,16 +413,6 @@ SET( libringclient_LIB_SRCS
src/extensions/securityevaluationextension.cpp
)
IF(${ENABLE_LIBWRAP} MATCHES true)
SET(libringclient_LIB_SRCS ${libringclient_LIB_SRCS}
src/private/directrenderer.cpp
)
ELSE()
SET(libringclient_LIB_SRCS ${libringclient_LIB_SRCS}
src/private/shmrenderer.cpp
)
ENDIF(${ENABLE_LIBWRAP} MATCHES true)
# Public API
SET( libringclient_LIB_HDRS
src/account.h
......@@ -511,6 +504,8 @@ SET( libringclient_LIB_HDRS
src/usage_statistics.h
src/bannedcontactmodel.h
src/vcard.h
src/shmrenderer.h
src/directrenderer.h
)
SET(libringclient_api_LIB_HDRS
......@@ -531,6 +526,7 @@ SET(libringclient_api_LIB_HDRS
src/api/behaviorcontroller.h
src/api/datatransfermodel.h
src/api/datatransfer.h
src/api/newvideo.h
)
......
......@@ -34,9 +34,9 @@ namespace lrc
namespace api
{
class NewCallModel;
class ContactModel;
class ConversationModel;
class NewCallModel;
class NewAccountModel;
class NewDeviceModel;
class NewCodecModel;
......@@ -219,9 +219,9 @@ struct Info
bool valid = true;
std::string registeredName;
Status status = account::Status::INVALID;
std::unique_ptr<lrc::api::NewCallModel> callModel;
std::unique_ptr<lrc::api::ContactModel> contactModel;
std::unique_ptr<lrc::api::ConversationModel> conversationModel;
std::unique_ptr<lrc::api::NewCallModel> callModel;
std::unique_ptr<lrc::api::NewDeviceModel> deviceModel;
std::unique_ptr<lrc::api::NewCodecModel> codecModel;
NewAccountModel* accountModel {nullptr};
......
/****************************************************************************
* Copyright (C) 2018 Savoir-faire Linux *
* Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> *
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
......@@ -20,16 +21,19 @@
// std
#include <memory>
#include <string>
#include <vector>
// Qt
#include <qobject.h>
// LRC
#include "api/newvideo.h"
#include "typedefs.h"
namespace lrc
{
class CallbacksHandler;
class AVModelPimpl;
namespace api
......@@ -38,8 +42,110 @@ namespace api
class LIB_EXPORT AVModel : public QObject {
Q_OBJECT
public:
AVModel();
AVModel(const CallbacksHandler& callbacksHandler);
~AVModel();
/**
* Get if hardware decoding is enabled
* @return hardware decoding enabled
*/
bool getDecodingAccelerated() const;
/**
* Enable/disable hardware decoding
* @param if hardware decoding enabled
*/
void setDecodingAccelerated(bool accelerate);
/**
* Get video devices
* @return list of devices
*/
std::vector<std::string> getDevices() const;
/**
* Retrieve current default video device
* @return current default video device name
*/
std::string getDefaultDeviceName() const;
/**
* Set new default video device
* @param name of the device
*/
void setDefaultDevice(const std::string& name);
/**
* Retrieve current framerate/resolution/etc of a device
* @param name of the device
* @return settings of the device
*/
video::Settings getDeviceSettings(const std::string& name) const;
/**
* Set device settings
* @param video::Settings
*/
void setDeviceSettings(video::Settings& settings);
/**
* Retrieve all framerate/resolution/etc possibilities of a device
* @param name of the device
* @return possibilities of the device
*/
video::Capabilities getDeviceCapabilities(const std::string& name) const;
/**
* Get supported audio managers
* @return supported audio managers
*/
std::vector<std::string> getSupportedAudioManagers() const;
/**
* Get current audio manager
* @return current audio manager
*/
std::string getAudioManager() const;
/**
* Get current audio outputs
* @return audio outputs
*/
std::vector<std::string> getAudioOutputDevices() const;
/**
* Get current audio inputs
* @return audio inputs
*/
std::vector<std::string> getAudioInputDevices() const;
/**
* Get current ringtone device
* @return current ringtone device
*/
std::string getRingtoneDevice() const;
/**
* Get current output device
* @return current output device
*/
std::string getOutputDevice() const;
/**
* Get current input device
* @return current input device
*/
std::string getInputDevice() const;
/**
* Set current audio manager
* @param name of the new audio manager
* @return if the operation is successful
*/
bool setAudioManager(const std::string& name);
/**
* Set current ringtone device
* @param name of the new ringtone device
*/
void setRingtoneDevice(const std::string& name);
/**
* Set current output device
* @param name of the new output device
*/
void setOutputDevice(const std::string& name);
/**
* Set current input device
* @param name of the new input device
*/
void setInputDevice(const std::string& name);
/**
* Stop local record at given path
* @param path
......@@ -51,6 +157,69 @@ public:
*/
std::string startLocalRecorder(const bool& audioOnly) const;
/**
* Start preview renderer. This will start the camera
*/
void startPreview();
/**
* Stop preview renderer and the camera.
*/
void stopPreview();
/**
* Get a renderer from a call
* @param id the callid or "local"
* @return the linked renderer
* @throw std::out_of_range if not found
*/
const video::Renderer& getRenderer(const std::string& id) const;
/**
* Render a file
* @param uri the path of the file
*/
void setInputFile(const std::string& uri);
/**
* Change the current device rendered
* @param id of the camera
* @note render a black frame if device not found
*/
void switchInputTo(const std::string& id);
/**
* Render the current display
* @param idx of the display
* @param x top left of the area
* @param y top up of the area
* @param w width of the area
* @param h height of the area
*/
void setDisplay(int idx, int x, int y, int w, int h);
/**
* Get informations on the rendered device
* @param call_id linked call to the renderer
* @return the device rendered
*/
video::RenderedDevice getCurrentRenderedDevice(const std::string& call_id) const;
// TODO remove this, this is just to avoid dual rendering.
void deactivateOldVideoModels();
Q_SIGNALS:
/**
* Emitted when a renderer is started
* @param id of the renderer
*/
void rendererStarted(const std::string& id);
/**
* Emitted when a renderer is stopped
* @param id of the renderer
*/
void rendererStopped(const std::string& id);
/**
* Emitted when a new frame is ready
* @param id
*/
void frameUpdated(const std::string& id);
private:
std::unique_ptr<AVModelPimpl> pimpl_;
};
......
/****************************************************************************
* Copyright (C) 2018 Savoir-faire Linux *
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#pragma once
// Std
#include <map>
#include <memory>
#include <string>
#include <vector>
// Qt
#include <qobject.h>
// Lrc
#include "typedefs.h"
// Qt
#include <QObject>
#include <QThread>
namespace lrc
{
class RendererPimpl;
namespace api
{
namespace video
{
constexpr static const char PREVIEW_RENDERER_ID[] = "local";
using Channel = std::string;
using Resolution = std::string;
using Framerate = uint64_t;
using FrameratesList = std::vector<Framerate>;
using Capabilities = std::map<Channel, std::map<Resolution, FrameratesList>>;
/**
* This class is used by Renderer class to expose video data frame
* that could be owned by instances of this class or shared.
* If an instance carries data, "storage.size()" is greater than 0
* and equals to "size", "ptr" is equals to "storage.data()".
* If shared data is carried, only "ptr" and "size" are set.
*/
struct Frame {
uint8_t* ptr { nullptr };
std::size_t size { 0 };
std::vector<uint8_t> storage { };
// Next variables are currently used with DirectRenderer only
unsigned int height { 0 };
unsigned int width { 0 };
};
enum DeviceType
{
CAMERA,
DISPLAY,
FILE,
INVALID
};
/**
* This class describes the current rendered device
*/
struct RenderedDevice
{
std::string name;
DeviceType type = INVALID;
};
/**
* This class describes current video settings
*/
struct Settings
{
Channel channel = "";
std::string name = "";
Framerate rate = 0;
Resolution size = "";
};
class LIB_EXPORT Renderer : public QObject {
Q_OBJECT
public:
Renderer(const std::string& id, Settings videoSettings,
const std::string& shmPath = "");
~Renderer();
/**
* Start the renderer in its own thread
*/
void initThread();
/**
* Update size and shmPath of a renderer
* @param res new resolution "wxh"
* @param shmPath new shmPath
*/
void update(const std::string& res, const std::string& shmPath);
/**
* Stop renderer and thread
*/
void quit();
// Getters
/**
* @return if renderer is rendering
*/
bool isRendering() const;
/**
* @return renderer's id
*/
std::string getId() const;
/**
* @return current rendered frame
*/
Frame currentFrame() const;
/**
* @return current size
*/
QSize size() const; // TODO convert into std format!
// Utils
/**
* Start rendering
*/
void startRendering();
/**
* Stop rendering
*/
void stopRendering();
Q_SIGNALS:
/**
* Emitted when a new frame is ready
* @param id
*/
void frameUpdated(const std::string& id);
private:
std::unique_ptr<RendererPimpl> pimpl_;
};
} // namespace video
} // namespace api
} // namespace lrc
/****************************************************************************
* Copyright (C) 2018 Savoir-faire Linux *
* Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> *
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
......@@ -19,18 +20,32 @@
// Std
#include <chrono>
#include <csignal>
#include <iomanip> // for std::put_time
#include <fstream>
#include <mutex>
#include <thread>
#include <string>
#include <sstream>
// Qt
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include <QUrl>
// Ring daemon
#include <media_const.h>
// LRC
#include "api/call.h"
#include "callbackshandler.h"
#include "dbus/callmanager.h"
#include "dbus/configurationmanager.h"
#include "dbus/videomanager.h"
// TODO(sblin) remove this as soon as all clients use this class
#include <private/videorenderermanager.h>
namespace lrc
{
......@@ -40,30 +55,442 @@ class AVModelPimpl: public QObject
{
Q_OBJECT
public:
AVModelPimpl(AVModel& linked);
AVModelPimpl(AVModel& linked, const CallbacksHandler& callbacksHandler);
const CallbacksHandler& callbacksHandler;
std::string getRecordingPath() const;
static const std::string recorderSavesSubdir;
AVModel& linked_;
std::mutex renderers_mtx_;
std::map<std::string, std::unique_ptr<video::Renderer>> renderers_;
// store if a renderers is for a finished call
std::map<std::string, bool> finishedRenderers_;
#ifndef ENABLE_LIBWRAP
// TODO: Init Video Renderers from daemon (see: https://git.ring.cx/savoirfairelinux/ring-daemon/issues/59)
static void stopCameraAndQuit(int);
static uint32_t SIZE_RENDERER;
#endif
/**
* Get device via its type
* @param type
* @return the device name
*/
std::string getDevice(int type) const;
// This method is temporary and has to be removed when videorenderermanager will be deleted
void init();
public Q_SLOTS:
/**
* Listen from CallbacksHandler when a renderer starts
* @param id
* @param shmPath
* @param width
* @param height
*/
void startedDecoding(const std::string& id, const std::string& shmPath, int width, int height);
/**
* Listen from CallbacksHandler when a renderer stops
* @param id
* @param shmPath
*/
void stoppedDecoding(const std::string& id, const std::string& shmPath);
/**
* Listen from CallbacksHandler when a call got a new state
* @param id
* @param state the new state
* @param code unused
*/
void slotCallStateChanged(const std::string& id, const std::string &state, int code);
/**
* Detect when the current frame is updated
* @param id
*/
void slotFrameUpdated(const std::string& id);
};
const std::string AVModelPimpl::recorderSavesSubdir = "sent_data";
#ifndef ENABLE_LIBWRAP
uint32_t AVModelPimpl::SIZE_RENDERER = 0;
#endif
AVModel::AVModel()
AVModel::AVModel(const CallbacksHandler& callbacksHandler)
: QObject()
, pimpl_(std::make_unique<AVModelPimpl>(*this))
, pimpl_(std::make_unique<AVModelPimpl>(*this, callbacksHandler))
{
#ifndef ENABLE_LIBWRAP
// Because the client uses DBUS, if a crash occurs, the daemon will not
// be able to know it. So, stop the camera if the user was just previewing.
std::signal(SIGSEGV, AVModelPimpl::stopCameraAndQuit);
std::signal(SIGINT, AVModelPimpl::stopCameraAndQuit);
#endif
}
AVModel::~AVModel()
{
}
AVModelPimpl::AVModelPimpl(AVModel& linked)
bool
AVModel::getDecodingAccelerated() const
{
bool result = VideoManager::instance().getDecodingAccelerated();
return result;
}
void
AVModel::setDecodingAccelerated(bool accelerate)
{
VideoManager::instance().setDecodingAccelerated(accelerate);
}
std::vector<std::string>
AVModel::getDevices() const
{
QStringList devices = VideoManager::instance()
.getDeviceList();
std::vector<std::string> result;
for (const auto& manager : devices) {
result.emplace_back(manager.toStdString());
}
return result;
}
std::string
AVModel::getDefaultDeviceName() const
{
QString name = VideoManager::instance().getDefaultDevice();
return name.toStdString();
}
void
AVModel::setDefaultDevice(const std::string& name)
{
VideoManager::instance().setDefaultDevice(name.c_str());
}
video::Settings
AVModel::getDeviceSettings(const std::string& name) const
{
MapStringString settings = VideoManager::instance()
.getSettings(name.c_str());
if (settings["name"].toStdString() != name) {
throw std::out_of_range("Device " + name + " not found");
}
video::Settings result;
result.name = settings["name"].toStdString();
result.channel = settings["channel"].toStdString();
result.size = settings["size"].toStdString();
result.rate = settings["rate"].toUInt();
return result;
}
video::Capabilities
AVModel::getDeviceCapabilities(const std::string& name) const
{
// Channel x Resolution x Framerate
QMap<QString, QMap<QString, QVector<QString>>> capabilites =
VideoManager::instance().getCapabilities(name.c_str());
video::Capabilities result;
for (auto& channel : capabilites.toStdMap()) {
std::map<video::Resolution, video::FrameratesList> channelCapabilities;
for (auto& resToRates : channel.second.toStdMap()) {
video::FrameratesList rates;
QVectorIterator<QString> itRates(resToRates.second);
while (itRates.hasNext()) {
rates.emplace_back(itRates.next().toUInt());
}
channelCapabilities.insert(
std::make_pair(resToRates.first.toStdString(), rates));
}
result.insert(
std::make_pair(channel.first.toStdString(), channelCapabilities));
}
return result;
}
void
AVModel::setDeviceSettings(video::Settings& settings)
{
MapStringString newSettings;
newSettings["channel"] = settings.channel.c_str();
newSettings["name"] = settings.name.c_str();
newSettings["rate"] = QString::number(settings.rate);
newSettings["size"] = settings.size.c_str();
VideoManager::instance().applySettings(settings.name.c_str(), newSettings);
// If the preview is running, reload it
// doing this during a call will cause re-invite, this is unwanted
if (pimpl_->renderers_[video::PREVIEW_RENDERER_ID]) {
if (pimpl_->renderers_[video::PREVIEW_RENDERER_ID]->isRendering() &&
pimpl_->renderers_.size() == 1) {
stopPreview();
startPreview();