diff --git a/src/manager.cpp b/src/manager.cpp
index 12ef2550e373f2661f6de7bed1ecd541f0216d25..1a89ba7ef912f46a71feeefc2e1f249a24d064d7 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -229,8 +229,9 @@ Manager::setAutoAnswer(bool enable)
 Manager::Manager() :
     pluginManager_(new PluginManager)
     , preferences(), voipPreferences(),
-    hookPreference(),  audioPreference(), shortcutPreferences(),
-    hasTriedToRegister_(false)
+    hookPreference(),  audioPreference(), shortcutPreferences()
+    , videoPreferences()
+    , hasTriedToRegister_(false)
     , toneCtrl_(preferences)
     , currentCallMutex_(), dtmfKey_(), dtmfBuf_(0, AudioFormat::MONO())
     , audioLayerMutex_()
@@ -1537,7 +1538,7 @@ Manager::saveConfig()
         hookPreference.serialize(out);
         audioPreference.serialize(out);
 #ifdef RING_VIDEO
-        getVideoDeviceMonitor().serialize(out);
+        videoPreferences.serialize(out);
 #endif
         shortcutPreferences.serialize(out);
 
@@ -2639,7 +2640,7 @@ Manager::loadAccountMap(const YAML::Node &node)
     int errorCount = 0;
     try {
 #ifdef RING_VIDEO
-        getVideoDeviceMonitor().unserialize(node);
+        videoPreferences.unserialize(node);
 #endif
     } catch (const YAML::Exception &e) {
         RING_ERR("%s: No video node in config file", e.what());
@@ -2919,6 +2920,18 @@ Manager::getSinkClient(const std::string& id)
             return sink;
     return nullptr;
 }
+
+bool
+Manager::getDecodingAccelerated() const
+{
+    return videoPreferences.getDecodingAccelerated();
+}
+
+void
+Manager::setDecodingAccelerated(bool isAccelerated)
+{
+    videoPreferences.setDecodingAccelerated(isAccelerated);
+}
 #endif // RING_VIDEO
 
 } // namespace ring
diff --git a/src/manager.h b/src/manager.h
index 2734334847725ac75abbac76e5ac8c367f81903d..f472115883b3230dadff9254116316cb0352611b 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -117,6 +117,11 @@ class Manager {
          */
         ShortcutPreferences shortcutPreferences;
 
+        /**
+         * Video preferences
+         */
+        VideoPreferences videoPreferences;
+
         // Manager should not be accessed until initialized.
         // FIXME this is an evil hack!
         static std::atomic_bool initialized;
@@ -1013,6 +1018,10 @@ class Manager {
         std::shared_ptr<video::SinkClient> getSinkClient(const std::string& id);
 
         VideoManager& getVideoManager() const { return *videoManager_; }
+
+        bool getDecodingAccelerated() const;
+
+        void setDecodingAccelerated(bool isAccelerated);
 #endif // RING_VIDEO
 
         std::atomic<unsigned> dhtLogLevel {0}; // default = disable
diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index 959e41aca745230dda30782da152a5dc6e94dab5..378fcdfec4562baab22ea482f261fb66fde27d12 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -26,6 +26,7 @@
 #include "audio/audiobuffer.h"
 #include "audio/ringbuffer.h"
 #include "audio/resampler.h"
+#include "manager.h"
 
 #if defined(RING_VIDEO) && defined(RING_ACCEL)
 #include "video/accel.h"
@@ -96,7 +97,9 @@ int MediaDecoder::openInput(const DeviceParams& params)
     RING_DBG("Trying to open device %s with format %s, pixel format %s, size %dx%d, rate %lf", params.input.c_str(),
                                                         params.format.c_str(), params.pixel_format.c_str(), params.width, params.height, params.framerate.real());
 
-    enableAccel_ = (params.enableAccel != "0");
+    // if there was a fallback to software decoding, do not enable accel
+    // it has been disabled already by the video_receive_thread
+    enableAccel_ &= Manager::instance().getDecodingAccelerated();
 
     int ret = avformat_open_input(
         &inputCtx_,
diff --git a/src/media/media_decoder.h b/src/media/media_decoder.h
index 6340f3a916856d34691b1765be7e30ac7f4c7295..83551ea3c7197b438c1738a41859c2caafa81a32 100644
--- a/src/media/media_decoder.h
+++ b/src/media/media_decoder.h
@@ -94,6 +94,7 @@ class MediaDecoder {
         int getPixelFormat() const;
 
         void setOptions(const std::map<std::string, std::string>& options);
+        void enableAccel(const bool enableAccel) { enableAccel_ = enableAccel; }
 
     private:
         NON_COPYABLE(MediaDecoder);
diff --git a/src/media/media_device.h b/src/media/media_device.h
index abf4826e030014b833a4f5201f6c4548bb48c6ae..9fb685943417165da45b7707e6a71f5dde197915 100644
--- a/src/media/media_device.h
+++ b/src/media/media_device.h
@@ -45,7 +45,6 @@ struct DeviceParams {
     std::string sdp_flags {};
     unsigned offset_x {};
     unsigned offset_y {};
-    std::string enableAccel {};
 };
 
 }
diff --git a/src/media/video/video_base.cpp b/src/media/video/video_base.cpp
index 366447a1850516bc8b3641f8f08a1e72e18ae326..63d1e01457031147b982860aebbb80c7d5335de0 100644
--- a/src/media/video/video_base.cpp
+++ b/src/media/video/video_base.cpp
@@ -81,7 +81,6 @@ VideoSettings::VideoSettings(const std::map<std::string, std::string>& settings)
     channel = extractString(settings, "channel");
     video_size = extractString(settings, "size");
     framerate = extractString(settings, "rate");
-    enableAccel = extractString(settings, "enableAccel");
 }
 
 std::map<std::string, std::string>
@@ -91,8 +90,7 @@ VideoSettings::to_map() const
         {"name", name},
         {"size", video_size},
         {"channel", channel},
-        {"rate", framerate},
-        {"enableAccel", enableAccel}
+        {"rate", framerate}
     };
 }
 
@@ -107,7 +105,6 @@ convert<ring::video::VideoSettings>::encode(const ring::video::VideoSettings& rh
     node["video_size"] = rhs.video_size;
     node["channel"] = rhs.channel;
     node["framerate"] = rhs.framerate;
-    node["enableAccel"] = rhs.enableAccel;
     return node;
 }
 
@@ -121,11 +118,6 @@ convert<ring::video::VideoSettings>::decode(const Node& node, ring::video::Video
     rhs.video_size = node["video_size"].as<std::string>();
     rhs.channel = node["channel"].as<std::string>();
     rhs.framerate = node["framerate"].as<std::string>();
-    // optional setting that may or may not be there
-    try {
-        rhs.enableAccel = node["enableAccel"].as<std::string>();
-    } catch (...) {}
-
     return true;
 }
 
diff --git a/src/media/video/video_base.h b/src/media/video/video_base.h
index 54e3d531f766f553d24dc9983adc8397044ec54a..46d28704092e7370d2180889fbd5d039878d94bd 100644
--- a/src/media/video/video_base.h
+++ b/src/media/video/video_base.h
@@ -159,7 +159,6 @@ struct VideoSettings
     std::string channel {};
     std::string video_size {};
     std::string framerate {};
-    std::string enableAccel {};
 };
 
 }} // namespace ring::video
diff --git a/src/media/video/video_device.h b/src/media/video/video_device.h
index b4e9f69119b7e500dc247d0dfa3cabe9dfdccb12..504501f810b5d0e0db89c2852c193164379389a1 100644
--- a/src/media/video/video_device.h
+++ b/src/media/video/video_device.h
@@ -128,8 +128,6 @@ public:
                       settings.framerate.c_str());
         }
 
-        settings.enableAccel = "1";
-
         return settings;
     }
 
@@ -143,7 +141,6 @@ public:
         settings.channel = params.channel_name;
         settings.video_size = sizeToString(params.width, params.height);
         settings.framerate = ring::to_string(params.framerate.real());
-        settings.enableAccel = params.enableAccel;
         return settings;
     }
 
@@ -162,7 +159,6 @@ public:
         params.width = size.first;
         params.height = size.second;
         params.framerate = rateFromString(settings.channel, size, settings.framerate);
-        params.enableAccel = settings.enableAccel;
         setDeviceParams(params);
     }
 
diff --git a/src/media/video/video_device_monitor.cpp b/src/media/video/video_device_monitor.cpp
index ba1cff48e74f0f211a24cdc07395e754d7170eb5..204f33a53b7a788e47ff51b8590631ecc8085c7c 100644
--- a/src/media/video/video_device_monitor.cpp
+++ b/src/media/video/video_device_monitor.cpp
@@ -303,9 +303,7 @@ VideoDeviceMonitor::overwritePreferences(VideoSettings settings)
 void
 VideoDeviceMonitor::serialize(YAML::Emitter &out)
 {
-    out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
     out << YAML::Key << "devices" << YAML::Value << preferences_;
-    out << YAML::EndMap;
 }
 
 void
diff --git a/src/media/video/video_receive_thread.cpp b/src/media/video/video_receive_thread.cpp
index e3ab0bd55928141264642df5c77317e496453b6d..0b0d0a70e52504bbc5079890757532bca9ecbe0f 100644
--- a/src/media/video/video_receive_thread.cpp
+++ b/src/media/video/video_receive_thread.cpp
@@ -38,14 +38,15 @@ using std::string;
 
 VideoReceiveThread::VideoReceiveThread(const std::string& id,
                                        const std::string &sdp,
-                                       const DeviceParams& args) :
+                                       const bool isReset) :
     VideoGenerator::VideoGenerator()
-    , args_(args)
+    , args_()
     , dstWidth_(0)
     , dstHeight_(0)
     , id_(id)
     , stream_(sdp)
     , restartDecoder_(false)
+    , isReset_(isReset)
     , sdpContext_(stream_.str().size(), false, &readFunction, 0, 0, this)
     , sink_ {Manager::instance().createSinkClient(id)}
     , requestKeyFrameCallback_(0)
@@ -71,6 +72,9 @@ bool VideoReceiveThread::setup()
 {
     videoDecoder_.reset(new MediaDecoder());
 
+    // disable accel if there was a fallback to software decoding
+    videoDecoder_->enableAccel(!isReset_);
+
     dstWidth_ = args_.width;
     dstHeight_ = args_.height;
 
diff --git a/src/media/video/video_receive_thread.h b/src/media/video/video_receive_thread.h
index 57d1032de879e4b0be4317a010b66d3e624a8890..773acd15163a60b96665ad8f4556bacd00cae30e 100644
--- a/src/media/video/video_receive_thread.h
+++ b/src/media/video/video_receive_thread.h
@@ -47,7 +47,7 @@ class SinkClient;
 
 class VideoReceiveThread : public VideoGenerator {
 public:
-    VideoReceiveThread(const std::string &id, const std::string &sdp, const DeviceParams& args);
+    VideoReceiveThread(const std::string &id, const std::string &sdp, const bool isReset);
     ~VideoReceiveThread();
     void startLoop();
 
@@ -79,6 +79,7 @@ private:
     std::unique_ptr<MediaIOHandle> demuxContext_;
     std::shared_ptr<SinkClient> sink_;
     std::atomic_bool restartDecoder_;
+    bool isReset_;
     void (*requestKeyFrameCallback_)(const std::string &);
     void openDecoder();
     bool decodeFrame();
diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp
index 077dff5363b47b167e80a4c888adf6674137ae68..72b7f97e1c2eb461859df3eadf519be3eed7c20a 100644
--- a/src/media/video/video_rtp_session.cpp
+++ b/src/media/video/video_rtp_session.cpp
@@ -129,13 +129,13 @@ VideoRtpSession::restartSender()
 void VideoRtpSession::startReceiver()
 {
     if (receive_.enabled and not receive_.holding) {
-        DeviceParams receiverArgs = {};
+        bool isReset = false;
         if (receiveThread_) {
             RING_WARN("Restarting video receiver");
-            receiverArgs.enableAccel = "0"; // most likely cause of this restart
+            isReset = true;
         }
         receiveThread_.reset(
-            new VideoReceiveThread(callID_, receive_.receiving_sdp, receiverArgs)
+            new VideoReceiveThread(callID_, receive_.receiving_sdp, isReset)
         );
         /* ebail: keyframe requests can lead to timeout if they are not answered.
          * we decided so to disable them for the moment
@@ -160,7 +160,7 @@ VideoRtpSession::restartReceiver()
     if (not socketPair_)
         return;
 
-    startReceiver(); // disable accel
+    startReceiver();
 }
 
 void VideoRtpSession::start(std::unique_ptr<IceSocket> rtp_sock,
diff --git a/src/preferences.cpp b/src/preferences.cpp
index 2a612c0a569693a67f528098618a034a7db99ee7..6b9c37ac968a0df10085e643c8006174148881df 100644
--- a/src/preferences.cpp
+++ b/src/preferences.cpp
@@ -45,6 +45,8 @@
 #endif
 #endif /* HAVE_OPENSL */
 
+#include "client/videomanager.h"
+
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 #include <yaml-cpp/yaml.h>
@@ -122,6 +124,10 @@ static const char * const POPUP_SHORT_KEY = "popupWindow";
 static const char * const TOGGLE_HOLD_SHORT_KEY = "toggleHold";
 static const char * const TOGGLE_PICKUP_HANGUP_SHORT_KEY = "togglePickupHangup";
 
+// video preferences
+constexpr const char * const VideoPreferences::CONFIG_LABEL;
+static const char * const DECODING_ACCELERATED_KEY = "decodingAccelerated";
+
 static const char * const DFT_PULSE_LENGTH_STR = "250"; /** Default DTMF lenght */
 static const char * const ALSA_DFT_CARD    = "0";          /** Default sound card index */
 
@@ -533,4 +539,27 @@ void ShortcutPreferences::unserialize(const YAML::Node &in)
     parseValue(node, TOGGLE_PICKUP_HANGUP_SHORT_KEY, togglePickupHangup_);
 }
 
+VideoPreferences::VideoPreferences()
+    : decodingAccelerated_(false)
+{
+}
+
+void VideoPreferences::serialize(YAML::Emitter &out)
+{
+    out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap;
+    out << YAML::Key << DECODING_ACCELERATED_KEY << YAML::Value << decodingAccelerated_;
+    getVideoDeviceMonitor().serialize(out);
+    out << YAML::EndMap;
+}
+
+void VideoPreferences::unserialize(const YAML::Node &in)
+{
+    const auto &node = in[CONFIG_LABEL];
+    // value may or may not be present
+    try {
+        parseValue(node, DECODING_ACCELERATED_KEY, decodingAccelerated_);
+    } catch (...) { decodingAccelerated_ = false; } // experimental, so disabled by default
+    getVideoDeviceMonitor().unserialize(node);
+}
+
 } // namespace ring
diff --git a/src/preferences.h b/src/preferences.h
index 1a8edbb86b9f595f8c1fdf63dcff4703cf9e5a27..27716a4fd1b1697b6297251d13632c99c1f5082b 100644
--- a/src/preferences.h
+++ b/src/preferences.h
@@ -439,6 +439,26 @@ class ShortcutPreferences : public Serializable {
         constexpr static const char * const CONFIG_LABEL = "shortcuts";
 };
 
+class VideoPreferences : public Serializable {
+    public:
+        VideoPreferences();
+
+        void serialize(YAML::Emitter &out);
+        void unserialize(const YAML::Node &in);
+
+        bool getDecodingAccelerated() const {
+            return decodingAccelerated_;
+        }
+
+        void setDecodingAccelerated(bool decodingAccelerated) {
+            decodingAccelerated_ = decodingAccelerated;
+        }
+
+    private:
+        bool decodingAccelerated_;
+        constexpr static const char* const CONFIG_LABEL = "video";
+};
+
 } // namespace ring
 
 #endif