From c186dbb4353c93e5cd02a79f4e4306b5881d1698 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> Date: Tue, 3 Jun 2014 22:38:05 +0200 Subject: [PATCH] [ #49034 ] Refactor the video configuration code to be safer (1/3) This commit implement the new daemon video getcapabilities() to load the whole device configuration when using the video module for the first time. This prevent the back and forth between the various layers of both the client and the daemon. Those, created a feedback loop that could crash the daemon or corrupt the Qt models. While it will take a while to get to a stable point again, this code is much more robust than the previous implementation. The next few commits will replace the last bits of the old code path by the new one. --- src/dbus/metatypes.h | 11 +- src/dbus/videomanager-introspec.xml | 59 ++++++-- src/typedefs.h | 1 + src/videodevice.cpp | 213 ++++++++++++++++++---------- src/videodevice.h | 109 +++++++++++--- src/videodevicemodel.cpp | 104 +++++--------- src/videodevicemodel.h | 25 +++- src/videomodel.cpp | 38 ++++- src/videomodel.h | 5 +- src/videorenderer.cpp | 18 +-- src/videorenderer.h | 50 +++---- 11 files changed, 413 insertions(+), 220 deletions(-) diff --git a/src/dbus/metatypes.h b/src/dbus/metatypes.h index 01d22f50..ba3c85fb 100644 --- a/src/dbus/metatypes.h +++ b/src/dbus/metatypes.h @@ -30,18 +30,27 @@ typedef QMap<QString, QString> MapStringString; typedef QMap<QString, int> MapStringInt; typedef QVector<int> VectorInt; typedef QVector< QMap<QString, QString> > VectorMapStringString; +typedef QVector< QString > VectorString; +typedef QMap< QString, QMap< QString, QVector<QString> > > MapStringMapStringVectorString; +typedef QMap< QString, QVector<QString> > MapStringVectorString; Q_DECLARE_METATYPE(MapStringString) Q_DECLARE_METATYPE(MapStringInt) Q_DECLARE_METATYPE(VectorMapStringString) +Q_DECLARE_METATYPE(MapStringMapStringVectorString) Q_DECLARE_METATYPE(VectorInt) +Q_DECLARE_METATYPE(VectorString) +Q_DECLARE_METATYPE(MapStringVectorString) static bool dbus_metaTypeInit = false; inline void registerCommTypes() { qDBusRegisterMetaType<MapStringString>(); qDBusRegisterMetaType<MapStringInt>(); qDBusRegisterMetaType<VectorMapStringString>(); - qDBusRegisterMetaType<VectorInt>(); + qDBusRegisterMetaType<MapStringMapStringVectorString>(); + qDBusRegisterMetaType<VectorInt>(); + qDBusRegisterMetaType<VectorString>(); + qDBusRegisterMetaType<MapStringVectorString>(); dbus_metaTypeInit = true; } #pragma GCC diagnostic pop diff --git a/src/dbus/videomanager-introspec.xml b/src/dbus/videomanager-introspec.xml index 7feb2cfd..4dc4f890 100644 --- a/src/dbus/videomanager-introspec.xml +++ b/src/dbus/videomanager-introspec.xml @@ -5,14 +5,14 @@ <method name="getDeviceList" tp:name-for-bindings="getDeviceList"> <tp:docstring>Returns a list of the detected v4l2 devices</tp:docstring> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="as" name="list" direction="out"> </arg> </method> <method name="getDeviceChannelList" tp:name-for-bindings="getDeviceChannelList"> <tp:docstring>Returns a list of the channels available for a given v4l2 device</tp:docstring> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="s" name="device" direction="in"> </arg> <arg type="as" name="list" direction="out"> @@ -21,7 +21,7 @@ <method name="getDeviceSizeList" tp:name-for-bindings="getDeviceSizeList"> <tp:docstring>Returns a list of the resolutions available for a given channel of a given v4l2 device</tp:docstring> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="s" name="device" direction="in"> </arg> <arg type="s" name="channel" direction="in"> @@ -32,7 +32,7 @@ <method name="getDeviceRateList" tp:name-for-bindings="getDeviceRateList"> <tp:docstring>Returns a list of the framerates available for a given resolution of a given channel of a given v4l2 device</tp:docstring> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="s" name="device" direction="in"> </arg> <arg type="s" name="channel" direction="in"> @@ -43,9 +43,18 @@ </arg> </method> + <method name="getCapabilities" tp:name-for-bindings="getCapabilities"> + <tp:docstring>Returns a map of map of array of strings, containing the capabilities (channel, size, rate) of a device</tp:docstring> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringMapStringVectorString"/> + <arg type="s" name="name" direction="in"> + </arg> + <arg type="a{sa{sas}}" name="cap" direction="out"> + </arg> + </method> + <method name="getSettingsFor" tp:name-for-bindings="getSettingsFor"> <tp:docstring>Returns a map of settings for the given device name</tp:docstring> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> <arg type="s" name="device" direction="in"> </arg> <arg type="a{ss}" name="map" direction="out"> @@ -54,7 +63,7 @@ <method name="getPreferences" tp:name-for-bindings="getPreferences"> <tp:docstring>Returns a map of user preferences for the given device name</tp:docstring> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> <arg type="s" name="name" direction="in"> </arg> <arg type="a{ss}" name="map" direction="out"> @@ -65,7 +74,7 @@ <tp:docstring>Set the preferences of a given device name</tp:docstring> <arg type="s" name="name" direction="in"> </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="MapStringString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> <arg type="a{ss}" name="pref" direction="in"> </arg> </method> @@ -75,18 +84,48 @@ </arg> </method> + <method name="getActiveDeviceChannel" tp:name-for-bindings="getActiveDeviceChannel"> + <arg type="s" name="channel" direction="out"> + </arg> + </method> + + <method name="getActiveDeviceSize" tp:name-for-bindings="getActiveDeviceSize"> + <arg type="s" name="size" direction="out"> + </arg> + </method> + + <method name="getActiveDeviceRate" tp:name-for-bindings="getActiveDeviceRate"> + <arg type="s" name="rate" direction="out"> + </arg> + </method> + <method name="setActiveDevice" tp:name-for-bindings="setActiveDevice"> <arg type="s" name="device" direction="in"> </arg> </method> + <method name="setActiveDeviceChannel" tp:name-for-bindings="setActiveDeviceChannel"> + <arg type="s" name="channel" direction="in"> + </arg> + </method> + + <method name="setActiveDeviceSize" tp:name-for-bindings="setActiveDeviceSize"> + <arg type="s" name="size" direction="in"> + </arg> + </method> + + <method name="setActiveDeviceRate" tp:name-for-bindings="setActiveDeviceRate"> + <arg type="s" name="rate" direction="in"> + </arg> + </method> + <!-- Video Codec related methods --> <method name="getCodecs" tp:name-for-bindings="getCodecs"> <tp:docstring>Gets the hashtable describing all the codecs and their parameters for a given account</tp:docstring> <arg type="s" name="accountID" direction="in"> </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> <arg type="aa{ss}" name="details" direction="out"> </arg> </method> @@ -95,7 +134,7 @@ <tp:docstring>Sets a vector of hashtables describing codecs and their parameters for a given account, one hashtable per codec</tp:docstring> <arg type="s" name="accountID" direction="in"> </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorMapStringString"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="VectorMapStringString"/> <arg type="aa{ss}" name="details" direction="in"> </arg> </method> @@ -125,7 +164,7 @@ </method> <method name="hasCameraStarted" tp:name-for-bindings="hasCameraStarted"> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="Bool"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="Bool"/> <arg type="b" name="started" direction="out"> <tp:docstring>Returns true if the camera has already started, false otherwise</tp:docstring> </arg> diff --git a/src/typedefs.h b/src/typedefs.h index d3fb6b18..ff77e33c 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -28,6 +28,7 @@ typedef QMap<QString, QString> MapStringString; typedef QVector< QMap<QString, QString> > VectorMapStringString; +typedef QMap< QString, QMap< QString, QVector<QString> > > MapStringMapStringVectorString; typedef QMap<QString, int> MapStringInt; template<class T, class E> diff --git a/src/videodevice.cpp b/src/videodevice.cpp index fcaf69c6..6ef8faf6 100644 --- a/src/videodevice.cpp +++ b/src/videodevice.cpp @@ -19,15 +19,17 @@ #include "dbus/videomanager.h" -Resolution::Resolution(uint _width, uint _height):QSize(_width,_height) +Resolution::Resolution(uint _width, uint _height):QSize(_width,_height), +m_pCurrentRate(nullptr),m_pChannel(nullptr) { } -Resolution::Resolution() : QSize() +Resolution::Resolution() : QSize(),m_pCurrentRate(nullptr),m_pChannel(nullptr) { } -Resolution::Resolution(const QString& size) +Resolution::Resolution(const QString& size, VideoChannel* chan) +: m_pCurrentRate(nullptr),m_pChannel(chan) { if (size.split('x').size() == 2) { setWidth(size.split('x')[0].toInt()); @@ -35,24 +37,50 @@ Resolution::Resolution(const QString& size) } } -Resolution::Resolution(const Resolution& res):QSize(res.width(),res.height()) +Resolution::Resolution(const Resolution& res):QSize(res.width(),res.height()), +m_pCurrentRate(nullptr),m_pChannel(nullptr) { } -Resolution::Resolution(const QSize& size):QSize(size) +Resolution::Resolution(const QSize& size):QSize(size), +m_pCurrentRate(nullptr),m_pChannel(nullptr) { } -const QString Resolution::toString() const +const QString Resolution::name() const { return QString::number(width())+'x'+QString::number(height()); } ///Constructor -VideoDevice::VideoDevice(const QString &id) : QObject(nullptr), m_DeviceId(id),m_Resolution("0x0") +VideoDevice::VideoDevice(const QString &id) : QObject(nullptr), m_DeviceId(id), +m_pCurrentChannel(nullptr) { - + VideoManagerInterface& interface = DBus::VideoManager::instance(); + MapStringMapStringVectorString cap = interface.getCapabilities(id); + QMapIterator<QString, MapStringVectorString> channels(cap); + qDebug() << "\n\n\n\nCAP" << id << cap.size(); + while (channels.hasNext()) { + channels.next(); + + VideoChannel* chan = new VideoChannel(this,channels.key()); + m_lChannels << chan; + + QMapIterator<QString, VectorString> resolutions(channels.value()); + while (resolutions.hasNext()) { + resolutions.next(); + + Resolution* res = new Resolution(resolutions.key(),chan); + chan->m_lValidResolutions << res; + + foreach(const QString& rate, resolutions.value()) { + VideoRate* r = new VideoRate(res,rate); + res->m_lValidRates << r; + } + } + } + Q_UNUSED(cap) } ///Destructor @@ -60,104 +88,145 @@ VideoDevice::~VideoDevice() { } -///Get the valid rates for this device -const QStringList VideoDevice::rateList(const VideoChannel& channel, const Resolution& resolution) -{ - VideoManagerInterface& interface = DBus::VideoManager::instance(); - return interface.getDeviceRateList(m_DeviceId,channel,resolution.toString()); -} - ///Get the valid channel list -const QList<VideoChannel> VideoDevice::channelList() +QList<VideoChannel*> VideoDevice::channelList() const { - VideoManagerInterface& interface = DBus::VideoManager::instance(); - return interface.getDeviceChannelList(m_DeviceId); + return m_lChannels; } -///Set the current device rate -void VideoDevice::setRate(const VideoRate& rate) +///Save the current settings +void VideoDevice::save() { - m_Rate = rate; + //In case new (unsupported) fields are added, merge with existing VideoManagerInterface& interface = DBus::VideoManager::instance(); MapStringString pref = interface.getPreferences(m_DeviceId); - pref[PreferenceNames::RATE] = rate; + pref[VideoDevice::PreferenceNames::CHANNEL] = activeChannel()->name(); + pref[VideoDevice::PreferenceNames::SIZE ] = activeChannel()->activeResolution()->name(); + pref[VideoDevice::PreferenceNames::RATE ] = activeChannel()->activeResolution()->activeRate()->name(); interface.setPreferences(m_DeviceId,pref); } -///Set the current resolution -void VideoDevice::setResolution(const Resolution& resolution) //??? No device +///Get the device id +const QString VideoDevice::id() const { - m_Resolution = resolution; - VideoManagerInterface& interface = DBus::VideoManager::instance(); - MapStringString pref = interface.getPreferences(m_DeviceId); - pref[PreferenceNames::SIZE] = resolution.toString(); - interface.setPreferences(m_DeviceId,pref); + return m_DeviceId; } -///Set the current device channel -void VideoDevice::setChannel(const VideoChannel& channel) //??? No device +///Get the device name +const QString VideoDevice::name() const { - m_Channel = channel; VideoManagerInterface& interface = DBus::VideoManager::instance(); - MapStringString pref = interface.getPreferences(m_DeviceId); - pref[PreferenceNames::CHANNEL] = channel; - interface.setPreferences(m_DeviceId,pref); + return QMap<QString,QString>(interface.getPreferences(m_DeviceId))[PreferenceNames::NAME];; } -///Get the current resolution -const Resolution VideoDevice::resolution() +///Is this device the default one +bool VideoDevice::isActive() const { - VideoManagerInterface& interface = DBus::VideoManager::instance(); - if ((!m_Resolution.isValid()) || m_Resolution == QSize(0,0)) - m_Resolution = Resolution(QMap<QString,QString>(interface.getPreferences(m_DeviceId))[PreferenceNames::SIZE]); - return m_Resolution; + return QString(DBus::VideoManager::instance().getActiveDevice()) == m_DeviceId; } -///Get the current channel -const VideoChannel VideoDevice::channel() //??? No device +Resolution* VideoChannel::activeResolution() { - VideoManagerInterface& interface = DBus::VideoManager::instance(); - if (m_Channel.isEmpty()) - m_Channel = QMap<QString,QString>(interface.getPreferences(m_DeviceId))[PreferenceNames::CHANNEL]; - return m_Channel; + //If it is the current device, then there is "current" resolution + if ((!m_pCurrentResolution) && m_pDevice->isActive()) { + VideoManagerInterface& interface = DBus::VideoManager::instance(); + const QString res = QMap<QString,QString>(interface.getPreferences(m_pDevice->id()))[VideoDevice::PreferenceNames::SIZE]; + foreach(Resolution* r, validResolutions()) { + if (r->name() == res) { + m_pCurrentResolution = r; + break; + } + } + } + //If it isn't the current _or_ the current res is invalid, pick the first valid one + if (!m_pCurrentResolution && validResolutions().size()) { + m_pCurrentResolution = validResolutions()[0]; + } + + return m_pCurrentResolution; } -///Get the current rate -const VideoRate VideoDevice::rate() -{ - VideoManagerInterface& interface = DBus::VideoManager::instance(); - if (m_Rate.isEmpty()) - m_Rate = QMap<QString,QString>(interface.getPreferences(m_DeviceId))[PreferenceNames::RATE]; - return m_Rate; +bool VideoChannel::setActiveResolution(Resolution* res) { + if ((!res) || m_lValidResolutions.indexOf(res) == -1 || res->name().isEmpty()) { + qWarning() << "Invalid active resolution" << (res?res->name():"NULL"); + return false; + } + m_pCurrentResolution = res; + m_pDevice->save(); + return true; } -///Get a list of valid resolution -const QList<Resolution> VideoDevice::resolutionList(const VideoChannel& channel) +VideoRate* Resolution::activeRate() { - QList<Resolution> toReturn; - VideoManagerInterface& interface = DBus::VideoManager::instance(); - const QStringList list = interface.getDeviceSizeList(m_DeviceId,channel); - foreach(const QString& res,list) { - toReturn << Resolution(res); + if (!m_pChannel) { + qWarning() << "Trying to get the active rate of an unattached resolution"; + return nullptr; + } + if (!m_pCurrentRate && m_pChannel && m_pChannel->device()->isActive()) { + VideoManagerInterface& interface = DBus::VideoManager::instance(); + const QString rate = QMap<QString,QString>( + interface.getPreferences(m_pChannel->device()->id()))[VideoDevice::PreferenceNames::RATE]; + foreach(VideoRate* r, m_lValidRates) { + if (r->name() == rate) { + m_pCurrentRate = r; + break; + } + } } - return toReturn; + if ((!m_pCurrentRate) && m_lValidRates.size()) + m_pCurrentRate = m_lValidRates[0]; + + return m_pCurrentRate; } -///Get the device id -const QString VideoDevice::id() const +int Resolution::index() const { - return m_DeviceId; + return m_pChannel?m_pChannel->validResolutions().indexOf(const_cast<Resolution*>(this)):-1; } -///Get the device name -const QString VideoDevice::name() +int VideoChannel::index() { + return m_pDevice->channelList().indexOf(this); +} + +int VideoRate::index() { + return m_pResolution->validRates().indexOf(this); +} + +bool VideoDevice::setActiveChannel(VideoChannel* chan) { - VideoManagerInterface& interface = DBus::VideoManager::instance(); - return QMap<QString,QString>(interface.getPreferences(m_DeviceId))[PreferenceNames::NAME];; + if (!chan || !m_lChannels.indexOf(chan)) { + qWarning() << "Trying to set an invalid channel" << (chan?chan->name():"NULL") << "for" << id(); + return false; + } + m_pCurrentChannel = chan; + save(); + return true; } -///Is this device the default one -bool VideoDevice::isActive() +VideoChannel::VideoChannel(VideoDevice* dev,const QString& name) : + m_Name(name),m_pCurrentResolution(nullptr),m_pDevice(dev) { - return QString(DBus::VideoManager::instance().getActiveDevice()) == m_DeviceId; + m_pCurrentResolution = nullptr; + m_pCurrentResolution = nullptr; + m_pCurrentResolution = nullptr; + m_pCurrentResolution = nullptr; + m_pCurrentResolution = nullptr; } + +VideoChannel* VideoDevice::activeChannel() const +{ + if (!m_pCurrentChannel) { + VideoManagerInterface& interface = DBus::VideoManager::instance(); + const QString chan = QMap<QString,QString>(interface.getPreferences(m_DeviceId))[VideoDevice::PreferenceNames::CHANNEL]; + foreach(VideoChannel* c, m_lChannels) { + if (c->name() == chan) { + const_cast<VideoDevice*>(this)->m_pCurrentChannel = c; + break; + } + } + } + if (!m_pCurrentChannel && m_lChannels.size()) { + const_cast<VideoDevice*>(this)->m_pCurrentChannel = m_lChannels[0]; + } + return m_pCurrentChannel; +} \ No newline at end of file diff --git a/src/videodevice.h b/src/videodevice.h index 35a2d742..34e8a8d4 100644 --- a/src/videodevice.h +++ b/src/videodevice.h @@ -26,25 +26,90 @@ //SFLPhone class VideoRenderer; +class Resolution; +class VideoRate; +class VideoChannel; +class VideoDevice; ///@typedef VideoChannel A channel available in a Device -typedef QString VideoChannel; +class LIB_EXPORT VideoChannel +{ + //Only VideoDevice can add resolutions + friend class VideoDevice; +public: + QString name() const { + return m_Name; + } + Resolution* activeResolution(); + QList<Resolution*> validResolutions() const { + return m_lValidResolutions; + } + VideoDevice* device() const { + return m_pDevice; + } + int index(); + + bool setActiveResolution(Resolution* res); + +private: + VideoChannel(VideoDevice* dev,const QString& name); + virtual ~VideoChannel() {} + QString m_Name; + QList<Resolution*> m_lValidResolutions; + Resolution* m_pCurrentResolution; + VideoDevice* m_pDevice; +}; ///@typedef VideoRate The rate for a device -typedef QString VideoRate; +class LIB_EXPORT VideoRate +{ + //Can only be created by VideoDevice + friend class VideoDevice; + +public: + virtual ~VideoRate() {} + QString name() const { + return m_Name; + } + int index(); +private: + VideoRate(const Resolution* res,const QString& name) : + m_Name(name),m_pResolution(res) {} + QString m_Name; + const Resolution* m_pResolution; +}; ///@struct Resolution Equivalent of "640x480" class LIB_EXPORT Resolution : public QSize { + //Only VideoDevice can add validated rates + friend class VideoDevice; public: //Constructor Resolution(uint _width, uint _height); - Resolution(const QString& size = QString()); + Resolution(const QString& size = QString(), VideoChannel* chan = nullptr); Resolution(const Resolution& res); Resolution(const QSize& size); explicit Resolution(); //Getter - const QString toString() const; - + const QString name() const; + const QList<VideoRate*> validRates() const { + return m_lValidRates; + } + int index() const; + VideoRate* activeRate(); + bool setActiveRate(VideoRate* rate) { + if (!rate || (m_lValidRates.indexOf(rate) != -1)) { + qWarning() << "Trying to set an invalid rate"; + return false; + } + return true; + } +private: + + //Attributes + QList<VideoRate*> m_lValidRates; + VideoRate* m_pCurrentRate; + VideoChannel* m_pChannel; }; class VideoModel; @@ -54,27 +119,25 @@ class LIB_EXPORT VideoDevice : public QObject { Q_OBJECT friend class VideoModel; friend class VideoDeviceModel; + + //Need to access the PreferenceNames table + friend class VideoChannel; + friend class Resolution; public: //Constants constexpr static const char* NONE = ""; //Getter - const QStringList rateList(const VideoChannel& channel, const Resolution& resolution); - const QList<Resolution> resolutionList(const VideoChannel& channel); - const QList<VideoChannel> channelList (); - const Resolution resolution (); - const VideoChannel channel (); - const VideoRate rate (); - const QString id () const; - const QString name (); - bool isActive (); + QList<VideoChannel*> channelList () const; + VideoChannel* activeChannel () const; + const QString id () const; + const QString name () const; + bool isActive () const; //Static getter //Setter - void setRate ( const VideoRate& rate ); - void setResolution ( const Resolution& resolution ); - void setChannel ( const VideoChannel& channel ); + bool setActiveChannel(VideoChannel* chan); private: //Constructor @@ -82,10 +145,12 @@ class LIB_EXPORT VideoDevice : public QObject { ~VideoDevice(); //Attributes - QString m_DeviceId; - QString m_Rate; - QString m_Channel; - Resolution m_Resolution; + QString m_DeviceId ; + VideoChannel* m_pCurrentChannel ; + QList<VideoChannel*> m_lChannels ; + + //Helper + void save(); class PreferenceNames { public: @@ -95,7 +160,7 @@ class LIB_EXPORT VideoDevice : public QObject { constexpr static const char* SIZE = "size" ; }; - signals: + Q_SIGNALS: void renderingStarted(VideoRenderer*); void renderingStopped(VideoRenderer*); void renderStateChanged(bool state); diff --git a/src/videodevicemodel.cpp b/src/videodevicemodel.cpp index 71d1febd..07bd35ea 100644 --- a/src/videodevicemodel.cpp +++ b/src/videodevicemodel.cpp @@ -193,7 +193,7 @@ VideoDeviceResolutionModel* VideoDeviceModel::resolutionModel() const QVariant VideoDeviceResolutionModel::data( const QModelIndex& idx, int role) const { if(idx.column() == 0 && role == Qt::DisplayRole) - return QVariant(m_lResolutions[idx.row()]->toString()); + return QVariant(VideoDeviceModel::instance()->activeDevice()->activeChannel()->validResolutions()[idx.row()]->name()); return QVariant(); } @@ -201,7 +201,7 @@ QVariant VideoDeviceResolutionModel::data( const QModelIndex& idx, int role) con int VideoDeviceResolutionModel::rowCount( const QModelIndex& par ) const { Q_UNUSED(par) - return m_lResolutions.size(); + return VideoDeviceModel::instance()->activeDevice()->activeChannel()->validResolutions().size(); } ///Items flag @@ -233,19 +233,20 @@ VideoDeviceResolutionModel::~VideoDeviceResolutionModel() } -Resolution VideoDeviceResolutionModel::activeResolution() const +Resolution* VideoDeviceResolutionModel::activeResolution() const { - return VideoDeviceModel::instance()->activeDevice()->resolution(); + return VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution(); } ///Save the current model over dbus void VideoDeviceResolutionModel::setActive(const QModelIndex& idx) { if (idx.isValid()) { - QSize s1(*m_lResolutions[idx.row()]),s2(VideoDeviceModel::instance()->activeDevice()->resolution()); + Resolution* r = VideoDeviceModel::instance()->activeDevice()->activeChannel()->validResolutions()[idx.row()]; + QSize s1(*r),s2(*VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()); if (s1 == s2) return; - VideoDeviceModel::instance()->activeDevice()->setResolution(m_lResolutions[idx.row()]->toString()); + VideoDeviceModel::instance()->activeDevice()->activeChannel()->setActiveResolution(r); emit changed(); emit currentIndexChanged(idx.row()); } @@ -262,32 +263,15 @@ void VideoDeviceResolutionModel::setActive(const int idx) void VideoDeviceResolutionModel::reload() { QHash<QString,Resolution*> devicesHash; - VideoManagerInterface& interface = DBus::VideoManager::instance(); VideoDevice* active = VideoDeviceModel::instance()->activeDevice(); if (active) { - const QStringList deviceList = interface.getDeviceSizeList(active->id(), - VideoDeviceModel::instance()->rateModel()->activeRate()); - if (deviceList.size() == m_hResolutions.size()) { - m_lResolutions = m_hResolutions.values(); - } - foreach(const QString& deviceName,deviceList) { - if (!m_hResolutions.contains(deviceName)) { - devicesHash[deviceName] = new Resolution(deviceName); - } - else { - devicesHash[deviceName] = m_hResolutions[deviceName]; - } - } - m_hResolutions.clear(); - m_hResolutions = devicesHash; - m_lResolutions = m_hResolutions.values(); emit layoutChanged(); VideoDeviceModel::instance()->rateModel()->reload(); emit changed(); - emit currentIndexChanged(m_lResolutions.indexOf(m_hResolutions[activeResolution().toString()])); + emit currentIndexChanged(activeResolution()->index()); } else { m_hResolutions.clear(); @@ -298,15 +282,7 @@ void VideoDeviceResolutionModel::reload() int VideoDeviceResolutionModel::currentIndex() const { - const Resolution& res = activeResolution(); - for (int i=0;i<m_lResolutions.size();i++) { - Resolution* availableRes = m_lResolutions[i]; - if (res.width() == availableRes->width() && res.height() == availableRes->height()) { - return i; - } - } - qWarning() << "Invalid resolution"; - return -1; + return VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->index(); } @@ -324,16 +300,16 @@ VideoDeviceChannelModel* VideoDeviceModel::channelModel() const } -QString VideoDeviceChannelModel::activeChannel() const +VideoChannel* VideoDeviceChannelModel::activeChannel() const { - return VideoDeviceModel::instance()->activeDevice()->channel(); + return VideoDeviceModel::instance()->activeDevice()->activeChannel(); } ///Get data from the model QVariant VideoDeviceChannelModel::data( const QModelIndex& idx, int role) const { if(idx.column() == 0 && role == Qt::DisplayRole) - return QVariant(m_lChannels[idx.row()]); + return QVariant(activeChannel()->name()); return QVariant(); } @@ -341,7 +317,7 @@ QVariant VideoDeviceChannelModel::data( const QModelIndex& idx, int role) const int VideoDeviceChannelModel::rowCount( const QModelIndex& par ) const { Q_UNUSED(par) - return m_lChannels.size(); + return VideoDeviceModel::instance()->activeDevice()->channelList().size(); } ///Items flag @@ -375,7 +351,8 @@ VideoDeviceChannelModel::~VideoDeviceChannelModel() void VideoDeviceChannelModel::setActive(const QModelIndex& idx) { if (idx.isValid()) { - VideoDeviceModel::instance()->activeDevice()->setChannel(m_lChannels[idx.row()]); + VideoChannel* c = VideoDeviceModel::instance()->activeDevice()->channelList()[idx.row()]; + VideoDeviceModel::instance()->activeDevice()->setActiveChannel(c); emit changed(); emit currentIndexChanged(idx.row()); } @@ -389,29 +366,23 @@ void VideoDeviceChannelModel::setActive(const int idx) void VideoDeviceChannelModel::reload() { - QHash<QString,QString> devicesHash; - VideoManagerInterface& interface = DBus::VideoManager::instance(); VideoDevice* active = VideoDeviceModel::instance()->activeDevice(); if (active) { - const QStringList deviceList = interface.getDeviceChannelList(active->id()); - m_lChannels = deviceList; emit layoutChanged(); VideoDeviceModel::instance()->resolutionModel()->reload(); - setActive(m_lChannels.indexOf(activeChannel())); + setActive(activeChannel()->index()); } else { - //There is no channel when there is no devices - m_lChannels.clear(); emit layoutChanged(); } } int VideoDeviceChannelModel::currentIndex() const { - return m_lChannels.indexOf(activeChannel()); + return activeChannel()->index(); } @@ -427,16 +398,16 @@ VideoDeviceRateModel* VideoDeviceModel::rateModel() const return m_pRateModel; } -QString VideoDeviceRateModel::activeRate() const +VideoRate* VideoDeviceRateModel::activeRate() const { - return VideoDeviceModel::instance()->activeDevice()->rate(); + return VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->activeRate(); } ///Get data from the model QVariant VideoDeviceRateModel::data( const QModelIndex& idx, int role) const { - if(idx.isValid() && idx.column() == 0 && role == Qt::DisplayRole && idx.row() < m_lRates.size()) - return QVariant(m_lRates[idx.row()]); + if(idx.isValid() && idx.column() == 0 && role == Qt::DisplayRole) + return QVariant(VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->validRates()[idx.row()]->name()); return QVariant(); } @@ -444,7 +415,7 @@ QVariant VideoDeviceRateModel::data( const QModelIndex& idx, int role) const int VideoDeviceRateModel::rowCount( const QModelIndex& par ) const { Q_UNUSED(par) - return m_lRates.size(); + return VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->validRates().size(); } ///Items flag @@ -478,7 +449,8 @@ VideoDeviceRateModel::~VideoDeviceRateModel() void VideoDeviceRateModel::setActive(const QModelIndex& idx) { if (idx.isValid()) { - VideoDeviceModel::instance()->activeDevice()->setRate(m_lRates[idx.row()]); + VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->setActiveRate( + VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->validRates()[idx.row()]); emit changed(); emit currentIndexChanged(idx.row()); } @@ -495,27 +467,19 @@ void VideoDeviceRateModel::setActive(const int idx) void VideoDeviceRateModel::reload() { QHash<QString,VideoDevice*> devicesHash; - VideoManagerInterface& interface = DBus::VideoManager::instance(); VideoDevice* active = VideoDeviceModel::instance()->activeDevice(); if (active) { - const QStringList deviceList = interface.getDeviceRateList(active->id (), - VideoDeviceModel::instance()->channelModel()->activeChannel (), - VideoDeviceModel::instance()->resolutionModel()->activeResolution().toString() - ); - m_lRates = deviceList; emit layoutChanged(); - const int currentRate = m_lRates.indexOf(activeRate()); - setActive(currentRate==-1?0:currentRate); + setActive(activeRate()->index()); } else { - m_lRates.clear(); emit layoutChanged(); } } int VideoDeviceRateModel::currentIndex() const { - return m_lRates.indexOf(activeRate()); + return activeRate()->index(); } @@ -542,19 +506,19 @@ QVariant ExtendedVideoDeviceModel::data( const QModelIndex& index, int role ) co case ExtendedDeviceList::NONE: switch(role) { case Qt::DisplayRole: - return "NONE"; + return tr("NONE"); }; break; case ExtendedDeviceList::SCREEN: switch(role) { case Qt::DisplayRole: - return "SCREEN"; + return tr("SCREEN"); }; break; case ExtendedDeviceList::FILE: switch(role) { case Qt::DisplayRole: - return "FILE"; + return tr("FILE"); }; break; default: @@ -600,16 +564,18 @@ void ExtendedVideoDeviceModel::switchTo(const int idx) { switch (idx) { case ExtendedDeviceList::NONE: - DBus::VideoManager::instance().switchInput(""); + DBus::VideoManager::instance().switchInput(ProtocolPrefix::NONE); break; case ExtendedDeviceList::SCREEN: - DBus::VideoManager::instance().switchInput("display://0:100x100"); + DBus::VideoManager::instance().switchInput( QString(ProtocolPrefix::DISPLAY)+"0:100x100"); break; case ExtendedDeviceList::FILE: - DBus::VideoManager::instance().switchInput(!m_CurrentFile.isEmpty()?"file://"+m_CurrentFile.path():""); + DBus::VideoManager::instance().switchInput( + !m_CurrentFile.isEmpty()?+ProtocolPrefix::FILE+m_CurrentFile.path():ProtocolPrefix::NONE + ); break; default: - DBus::VideoManager::instance().switchInput("v4l2://"+ + DBus::VideoManager::instance().switchInput(ProtocolPrefix::V4L2 + VideoDeviceModel::instance()->index(idx-ExtendedDeviceList::__COUNT,0).data(Qt::DisplayRole).toString()); break; }; diff --git a/src/videodevicemodel.h b/src/videodevicemodel.h index 2308ccfb..cbd0359c 100644 --- a/src/videodevicemodel.h +++ b/src/videodevicemodel.h @@ -29,6 +29,7 @@ //SFLPhone class VideoDevice; +//DEPRECATED ///Abstract model for managing account video codec list class LIB_EXPORT VideoDeviceResolutionModel : public QAbstractListModel { #pragma GCC diagnostic push @@ -47,13 +48,14 @@ public: Qt::ItemFlags flags ( const QModelIndex& index ) const; virtual bool setData ( const QModelIndex& index, const QVariant &value, int role) ; - Resolution activeResolution() const; + Resolution* activeResolution() const; int currentIndex() const; private: + //Attrbutes QHash<QString,Resolution*> m_hResolutions ; - QList<Resolution*> m_lResolutions; +// QList<Resolution*> m_lResolutions; static VideoDeviceResolutionModel* m_spInstance; public Q_SLOTS: @@ -67,6 +69,7 @@ Q_SIGNALS: }; Q_DECLARE_METATYPE(VideoDeviceResolutionModel*) +//DEPRECATED ///Abstract model for managing account video codec list class LIB_EXPORT VideoDeviceChannelModel : public QAbstractListModel { #pragma GCC diagnostic push @@ -87,12 +90,12 @@ public: static VideoDeviceChannelModel* instance(); - QString activeChannel() const; + VideoChannel* activeChannel() const; int currentIndex() const; private: //Attrbutes - QList<QString> m_lChannels; +// QList<QString> m_lChannels; public Q_SLOTS: @@ -126,6 +129,15 @@ public: //Singleton static ExtendedVideoDeviceModel* instance(); private: + //Constants + class ProtocolPrefix { + public: + constexpr static const char* NONE = "" ; + constexpr static const char* DISPLAY = "display://"; + constexpr static const char* FILE = "file://" ; + constexpr static const char* V4L2 = "v4l2://" ; + }; + struct Display { Display() : res("0x0"),point(0,0),index(0){} Resolution res ; /* Resolution 0x0 for native */ @@ -144,6 +156,7 @@ public Q_SLOTS: void setDisplay(int index, Resolution res = Resolution("0x0"), QPoint point = QPoint(0,0)); }; +//DEPRECATED ///Abstract model for managing account video codec list class LIB_EXPORT VideoDeviceRateModel : public QAbstractListModel { #pragma GCC diagnostic push @@ -162,12 +175,12 @@ public: Qt::ItemFlags flags ( const QModelIndex& index ) const; virtual bool setData ( const QModelIndex& index, const QVariant &value, int role) ; - QString activeRate() const; + VideoRate* activeRate() const; int currentIndex() const; private: //Attrbutes - QList<QString> m_lRates; +// QList<QString> m_lRates; public Q_SLOTS: void setActive(const QModelIndex& idx); diff --git a/src/videomodel.cpp b/src/videomodel.cpp index c97986d2..f33915b3 100644 --- a/src/videomodel.cpp +++ b/src/videomodel.cpp @@ -32,7 +32,8 @@ VideoModel* VideoModel::m_spInstance = nullptr; ///Constructor -VideoModel::VideoModel():QThread(),m_BufferSize(0),m_ShmKey(0),m_SemKey(0),m_PreviewState(false),m_SSMutex(new QMutex()) +VideoModel::VideoModel():QThread(),m_BufferSize(0),m_ShmKey(0),m_SemKey(0),m_PreviewState(false),m_SSMutex(new QMutex()), +m_pActiveDevice(nullptr) { VideoManagerInterface& interface = DBus::VideoManager::instance(); connect( &interface , SIGNAL(deviceEvent()) , this, SLOT(deviceEvent()) ); @@ -69,7 +70,8 @@ VideoRenderer* VideoModel::getRenderer(const Call* call) const VideoRenderer* VideoModel::previewRenderer() { if (!m_lRenderers["local"]) { - m_lRenderers["local"] = new VideoRenderer("local","", VideoDeviceModel::instance()->activeDevice()->resolution()); + m_lRenderers["local"] = new VideoRenderer("local","", + VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()); } return m_lRenderers["local"]; } @@ -109,13 +111,41 @@ void VideoModel::deviceEvent() } +VideoDevice* VideoModel::activeDevice() const +{ + if (!m_pActiveDevice) { + VideoManagerInterface& interface = DBus::VideoManager::instance(); + const QString activeDeviceId = interface.getActiveDevice(); + foreach(VideoDevice* dev, m_hDevices) { + if (dev->id() == activeDeviceId) { + const_cast<VideoModel*>(this)->m_pActiveDevice = dev; + break; + } + } + } + if (!m_pActiveDevice) { + qWarning() << "No active devices"; + } + return m_pActiveDevice; +} + ///A video is not being rendered void VideoModel::startedDecoding(const QString& id, const QString& shmPath, int width, int height) { Q_UNUSED(id) + Resolution* res; + if (VideoDeviceModel::instance()->activeDevice() + && VideoDeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->width() == width) { + //FIXME flawed logic + res = VideoModel::activeDevice()->activeChannel()->activeResolution(); + } + else { + res = new Resolution(width,height); //FIXME leak + } + if (m_lRenderers[id] == nullptr ) { - m_lRenderers[id] = new VideoRenderer(id,shmPath,Resolution(width,height)); + m_lRenderers[id] = new VideoRenderer(id,shmPath,res); m_lRenderers[id]->moveToThread(this); if (!isRunning()) start(); @@ -123,7 +153,7 @@ void VideoModel::startedDecoding(const QString& id, const QString& shmPath, int else { VideoRenderer* renderer = m_lRenderers[id]; renderer->setShmPath(shmPath); - renderer->setResolution(QSize(width,height)); + renderer->setResolution(res); } m_lRenderers[id]->startRendering(); diff --git a/src/videomodel.h b/src/videomodel.h index f89787ba..69997a69 100644 --- a/src/videomodel.h +++ b/src/videomodel.h @@ -46,13 +46,13 @@ public: VideoRenderer* getRenderer(const Call* call) const; VideoRenderer* previewRenderer(); QList<VideoDevice*> devices(); -// VideoDevice* activeDevice() const; + VideoDevice* activeDevice() const; VideoDevice* device(const QString &id); QMutex* startStopMutex() const; //Setters void setBufferSize(uint size); -// void setActiveDevice(const VideoDevice* device); + void setActiveDevice(const VideoDevice* device); void switchDevice(const VideoDevice* device) const; protected: @@ -74,6 +74,7 @@ private: QMutex* m_SSMutex ; QHash<QString,VideoRenderer*> m_lRenderers; QHash<QString,VideoDevice*> m_hDevices ; + VideoDevice* m_pActiveDevice; public Q_SLOTS: void stopPreview (); diff --git a/src/videorenderer.cpp b/src/videorenderer.cpp index 3e052ac2..1dc75a3f 100644 --- a/src/videorenderer.cpp +++ b/src/videorenderer.cpp @@ -55,10 +55,10 @@ struct SHMHeader{ }; ///Constructor -VideoRenderer::VideoRenderer(const QString& id, const QString& shmPath, Resolution res): QObject(nullptr), - m_Width(res.width()), m_Height(res.height()), m_ShmPath(shmPath), fd(-1), +VideoRenderer::VideoRenderer(const QString& id, const QString& shmPath, const Resolution* res): QObject(nullptr), + m_Width(res->width()), m_Height(res->height()), m_ShmPath(shmPath), fd(-1), m_pShmArea((SHMHeader*)MAP_FAILED), m_ShmAreaLen(0), m_BufferGen(0), - m_isRendering(false),m_pTimer(nullptr),m_Res(res),m_pMutex(new QMutex()), + m_isRendering(false),m_pTimer(nullptr),m_pRes(const_cast<Resolution*>(res)),m_pMutex(new QMutex()), m_Id(id),m_FrameIdx(false),m_pSSMutex(new QMutex()) { setObjectName("VideoRenderer:"+id); @@ -330,9 +330,9 @@ const QByteArray& VideoRenderer::currentFrame() } ///Return the current resolution -Resolution VideoRenderer::activeResolution() +const Resolution* VideoRenderer::activeResolution() { - return m_Res; + return m_pRes; } ///Get mutex, in case renderer and views are not in the same thread @@ -354,11 +354,11 @@ int VideoRenderer::fps() const * * ****************************************************************************/ -void VideoRenderer::setResolution(QSize size) +void VideoRenderer::setResolution(Resolution* res) { - m_Res = size; - m_Width = size.width(); - m_Height = size.height(); + m_pRes = res; + m_Width = res->width(); + m_Height = res->height(); } void VideoRenderer::setShmPath(const QString& path) diff --git a/src/videorenderer.h b/src/videorenderer.h index a27494ab..d2abb62e 100644 --- a/src/videorenderer.h +++ b/src/videorenderer.h @@ -41,7 +41,7 @@ class LIB_EXPORT VideoRenderer : public QObject { public: //Constructor - VideoRenderer (const QString& id, const QString& shmPath, const Resolution res); + VideoRenderer (const QString& id, const QString& shmPath, const Resolution* res); ~VideoRenderer(); //Mutators @@ -50,37 +50,37 @@ class LIB_EXPORT VideoRenderer : public QObject { bool startShm (); //Getters - const char* rawData () ; - bool isRendering () ; + const char* rawData () ; + bool isRendering () ; const QByteArray& currentFrame () ; - Resolution activeResolution() ; - QMutex* mutex () ; - int fps () const; + const Resolution* activeResolution() ; + QMutex* mutex () ; + int fps () const; //Setters - void setResolution(QSize size); + void setResolution(Resolution* res); void setShmPath (const QString& path); private: //Attributes - uint m_Width ; - uint m_Height ; - QString m_ShmPath ; - int fd ; - SHMHeader* m_pShmArea ; - signed int m_ShmAreaLen ; - uint m_BufferGen ; - bool m_isRendering; - QTimer* m_pTimer ; - QByteArray m_Frame[2] ; - bool m_FrameIdx ; - Resolution m_Res ; - QMutex* m_pMutex ; - QMutex* m_pSSMutex ; - QString m_Id ; - int m_fpsC ; - int m_Fps ; - QTime m_CurrentTime; + uint m_Width ; + uint m_Height ; + QString m_ShmPath ; + int fd ; + SHMHeader * m_pShmArea ; + signed int m_ShmAreaLen ; + uint m_BufferGen ; + bool m_isRendering; + QTimer* m_pTimer ; + QByteArray m_Frame[2] ; + bool m_FrameIdx ; + Resolution* m_pRes ; + QMutex* m_pMutex ; + QMutex* m_pSSMutex ; + QString m_Id ; + int m_fpsC ; + int m_Fps ; + QTime m_CurrentTime; //Constants static const int TIMEOUT_SEC = 1; // 1 second -- GitLab