diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index dd9b059897b69cf25836d4a4d9618e4c4d994cde..816ee9477993ec6ebfeebbf770d99ceb3bab031f 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -64,7 +64,9 @@ constexpr double LOGREG_PARAM_B_HEVC {-5.};
 
 MediaEncoder::MediaEncoder()
     : outputCtx_(avformat_alloc_context())
-{}
+{
+    JAMI_DBG("[%p] New instance created", this);
+}
 
 MediaEncoder::~MediaEncoder()
 {
@@ -86,6 +88,8 @@ MediaEncoder::~MediaEncoder()
         avformat_free_context(outputCtx_);
     }
     av_dict_free(&options_);
+
+    JAMI_DBG("[%p] Instance destroyed", this);
 }
 
 void
@@ -168,10 +172,6 @@ MediaEncoder::openOutput(const std::string& filename, const std::string& format)
         avformat_alloc_output_context2(&outputCtx_, nullptr, nullptr, filename.c_str());
     else
         avformat_alloc_output_context2(&outputCtx_, nullptr, format.c_str(), filename.c_str());
-
-#ifdef RING_ACCEL
-    enableAccel_ = Manager::instance().videoPreferences.getEncodingAccelerated();
-#endif
 }
 
 int
@@ -179,15 +179,35 @@ MediaEncoder::addStream(const SystemCodecInfo& systemCodecInfo)
 {
     if (systemCodecInfo.mediaType == MEDIA_AUDIO) {
         audioCodec_ = systemCodecInfo.name;
-        return initStream(systemCodecInfo, nullptr);
     } else {
         videoCodec_ = systemCodecInfo.name;
-        // TODO only support 1 audio stream and 1 video stream per encoder
-        if (audioOpts_.isValid())
-            return 1; // stream will be added to AVFormatContext after audio stream
-        else
-            return 0; // only a video stream
     }
+
+    auto stream = avformat_new_stream(outputCtx_, outputCodec_);
+
+    if (stream == nullptr) {
+        JAMI_ERR("[%p] Failed to create coding instance for %s", this, systemCodecInfo.name.c_str());
+        return -1;
+    }
+
+    JAMI_DBG("[%p] Created new coding instance for %s @ index %d",
+             this,
+             systemCodecInfo.name.c_str(),
+             stream->index);
+    // Only init audio now, video will be intialized when
+    // encoding the first frame.
+    if (systemCodecInfo.mediaType == MEDIA_AUDIO) {
+        return initStream(systemCodecInfo);
+    }
+
+    // If audio options are valid, it means this session is used
+    // for both audio and video streams, thus the video will be
+    // at index 1, otherwise it will be at index 0.
+    // TODO. Hacky, needs better solution.
+    if (audioOpts_.isValid())
+        return 1;
+    else
+        return 0;
 }
 
 int
@@ -203,7 +223,23 @@ MediaEncoder::initStream(const std::string& codecName, AVBufferRef* framesCtx)
 int
 MediaEncoder::initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx)
 {
+    JAMI_DBG("[%p] Initializing stream: codec type %d, name %s, lib %s",
+             this,
+             systemCodecInfo.codecType,
+             systemCodecInfo.name.c_str(),
+             systemCodecInfo.libName.c_str());
+
     std::lock_guard<std::mutex> lk(encMutex_);
+
+    if (!outputCtx_)
+        throw MediaEncoderException("Cannot allocate stream");
+
+    // Must already have codec instance(s)
+    if (outputCtx_->nb_streams == 0) {
+        JAMI_ERR("[%p] Can not init, output context has no coding sessions!", this);
+        throw MediaEncoderException("Can not init, output context has no coding sessions!");
+    }
+
     AVCodecContext* encoderCtx = nullptr;
     AVMediaType mediaType;
 
@@ -212,19 +248,26 @@ MediaEncoder::initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* fr
     else if (systemCodecInfo.mediaType == MEDIA_AUDIO)
         mediaType = AVMEDIA_TYPE_AUDIO;
 
-    AVStream* stream;
-    if (!outputCtx_)
-        throw MediaEncoderException("Cannot allocate stream");
-    // add video stream to outputformat context
-    if (outputCtx_->nb_streams <= 0)
-        stream = avformat_new_stream(outputCtx_, outputCodec_);
-    else {
-        stream = outputCtx_->streams[0];
-        stream->codecpar->width = videoOpts_.width;
-        stream->codecpar->height = videoOpts_.height;
+    AVStream* stream {nullptr};
+
+    // Only supports one audio and one video streams at most per instance.
+    for (unsigned i = 0; i < outputCtx_->nb_streams; i++) {
+        stream = outputCtx_->streams[i];
+        if (stream->codecpar->codec_type == mediaType) {
+            if (mediaType == AVMEDIA_TYPE_VIDEO) {
+                stream->codecpar->width = videoOpts_.width;
+                stream->codecpar->height = videoOpts_.height;
+            }
+            break;
+        }
     }
-    if (!stream)
+
+    if (stream == nullptr) {
+        JAMI_ERR("[%p] Can not init, output context has no coding sessions for %s",
+                 this,
+                 systemCodecInfo.name.c_str());
         throw MediaEncoderException("Cannot allocate stream");
+    }
 
     currentStreamIdx_ = stream->index;
 #ifdef RING_ACCEL
@@ -490,7 +533,7 @@ bool
 MediaEncoder::send(AVPacket& pkt, int streamIdx)
 {
     if (!initialized_) {
-        streamIdx = initStream(videoCodec_, nullptr);
+        streamIdx = initStream(videoCodec_);
         startIO();
     }
     if (streamIdx < 0)
diff --git a/src/media/media_encoder.h b/src/media/media_encoder.h
index 787f2eb9ede4ea4f759679eedbfdfc03d105db32..2a6d0141e9a2cc88729479aa8ca06681de3233be 100644
--- a/src/media/media_encoder.h
+++ b/src/media/media_encoder.h
@@ -122,8 +122,8 @@ private:
     AVCodecContext* prepareEncoderContext(AVCodec* outputCodec, bool is_video);
     void forcePresetX2645(AVCodecContext* encoderCtx);
     void extractProfileLevelID(const std::string& parameters, AVCodecContext* ctx);
-    int initStream(const std::string& codecName, AVBufferRef* framesCtx);
-    int initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx);
+    int initStream(const std::string& codecName, AVBufferRef* framesCtx = {});
+    int initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx = {});
     void openIOContext();
     void startIO();
     AVCodecContext* getCurrentVideoAVCtx();
@@ -167,7 +167,7 @@ private:
     int scaledFrameBufferSize_ = 0;
 
 #ifdef RING_ACCEL
-    bool enableAccel_ = true;
+    bool enableAccel_ {false};
     std::unique_ptr<video::HardwareAccel> accel_;
 #endif
 
diff --git a/src/media/media_recorder.cpp b/src/media/media_recorder.cpp
index 415865af43342c055075b0bb546c420761d044f6..35132505eacbd4fc3cbd01549392144dbed7768d 100644
--- a/src/media/media_recorder.cpp
+++ b/src/media/media_recorder.cpp
@@ -85,8 +85,7 @@ struct MediaRecorder::StreamObserver : public Observer<std::shared_ptr<MediaFram
                     JAMI_ERR("Accel failure: %s", e.what());
                     return;
                 }
-            }
-            else
+            } else
 #endif
                 framePtr = std::static_pointer_cast<VideoFrame>(m);
             int angle = framePtr->getOrientation();
@@ -264,10 +263,9 @@ MediaRecorder::onFrame(const std::string& name, const std::shared_ptr<MediaFrame
             (AVPixelFormat)(std::static_pointer_cast<VideoFrame>(frame))->format());
         if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
             try {
-                clone = video::HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>(
-                                                                    frame),
-                                                                static_cast<AVPixelFormat>(
-                                                                    ms.format));
+                clone = video::HardwareAccel::transferToMainMemory(
+                    *std::static_pointer_cast<VideoFrame>(frame),
+                    static_cast<AVPixelFormat>(ms.format));
             } catch (const std::runtime_error& e) {
                 JAMI_ERR("Accel failure: %s", e.what());
                 return;
@@ -351,16 +349,6 @@ MediaRecorder::initRecord()
         encoder_->setOptions(audioStream);
     }
 
-    if (hasVideo_) {
-        auto videoCodec = std::static_pointer_cast<jami::SystemVideoCodecInfo>(
-            getSystemCodecContainer()->searchCodecByName("VP8", jami::MEDIA_VIDEO));
-        videoIdx_ = encoder_->addStream(*videoCodec.get());
-        if (videoIdx_ < 0) {
-            JAMI_ERR() << "Failed to add video stream to encoder";
-            return -1;
-        }
-    }
-
     if (hasAudio_) {
         auto audioCodec = std::static_pointer_cast<jami::SystemAudioCodecInfo>(
             getSystemCodecContainer()->searchCodecByName("opus", jami::MEDIA_AUDIO));
@@ -371,6 +359,16 @@ MediaRecorder::initRecord()
         }
     }
 
+    if (hasVideo_) {
+        auto videoCodec = std::static_pointer_cast<jami::SystemVideoCodecInfo>(
+            getSystemCodecContainer()->searchCodecByName("VP8", jami::MEDIA_VIDEO));
+        videoIdx_ = encoder_->addStream(*videoCodec.get());
+        if (videoIdx_ < 0) {
+            JAMI_ERR() << "Failed to add video stream to encoder";
+            return -1;
+        }
+    }
+
     encoder_->setIOContext(nullptr);
 
     JAMI_DBG() << "Recording initialized";
diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp
index 54bcd74a712fc0265a8ac8c01a5457ea63fe7f7c..e9c198a585b8cedb34bfe38aa0cac03167034ea2 100644
--- a/src/media/video/video_rtp_session.cpp
+++ b/src/media/video/video_rtp_session.cpp
@@ -149,7 +149,11 @@ VideoRtpSession::startSender()
 
         send_.linkableHW = conference_ == nullptr;
         send_.bitrate = videoBitrateInfo_.videoBitrateCurrent;
-        bool isScreenScharing = localVideoParams_.format == "x11grab";
+        // NOTE:
+        // Current implementation does not handle resolution change
+        // (needed by window sharing feature) with HW codecs, so HW
+        // codecs will be disabled for now.
+        bool allowHwAccel = (localVideoParams_.format != "x11grab");
 
         if (socketPair_)
             initSeqVal_ = socketPair_->lastSeqValOut();
@@ -167,13 +171,8 @@ VideoRtpSession::startSender()
                                     send_.bitrate,
                                     static_cast<rational<int>>(localVideoParams_.framerate))
                       : videoMixer_->getStream("Video Sender");
-            sender_.reset(new VideoSender(getRemoteRtpUri(),
-                                          ms,
-                                          send_,
-                                          *socketPair_,
-                                          initSeqVal_ + 1,
-                                          mtu_,
-                                          isScreenScharing));
+            sender_.reset(new VideoSender(
+                getRemoteRtpUri(), ms, send_, *socketPair_, initSeqVal_ + 1, mtu_, allowHwAccel));
             if (changeOrientationCallback_)
                 sender_->setChangeOrientationCallback(changeOrientationCallback_);
             if (socketPair_)
diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp
index 4a35f3ead0a278ceab4e30a2b75cdaffd7586b24..f4a45a0efb5483f8bef11d320c9f0964d7435acd 100644
--- a/src/media/video/video_sender.cpp
+++ b/src/media/video/video_sender.cpp
@@ -48,7 +48,7 @@ VideoSender::VideoSender(const std::string& dest,
                          SocketPair& socketPair,
                          const uint16_t seqVal,
                          uint16_t mtu,
-                         bool isScreenScharing = false)
+                         bool enableHwAccel)
     : muxContext_(socketPair.createIOContext(mtu))
     , videoEncoder_(new MediaEncoder)
 {
@@ -56,24 +56,19 @@ VideoSender::VideoSender(const std::string& dest,
     videoEncoder_->openOutput(dest, "rtp");
     videoEncoder_->setOptions(opts);
     videoEncoder_->setOptions(args);
+#ifdef RING_ACCEL
+    videoEncoder_->enableAccel(enableHwAccel
+                               and Manager::instance().videoPreferences.getEncodingAccelerated());
+#endif
     videoEncoder_->addStream(args.codec->systemCodecInfo);
     videoEncoder_->setInitSeqVal(seqVal);
     videoEncoder_->setIOContext(muxContext_->getContext());
-#ifdef RING_ACCEL
-    if (isScreenScharing)
-        videoEncoder_->enableAccel(false);
-#endif
     // Send local video codec in SmartInfo
     Smartools::getInstance().setLocalVideoCodec(videoEncoder_->getVideoCodec());
     // Send the resolution in smartInfo
     Smartools::getInstance().setResolution("local", opts.width, opts.height);
 }
 
-VideoSender::~VideoSender()
-{
-    videoEncoder_->flush();
-}
-
 void
 VideoSender::encodeAndSendVideo(const std::shared_ptr<VideoFrame>& input_frame)
 {
diff --git a/src/media/video/video_sender.h b/src/media/video/video_sender.h
index 0d2ca3068caf4893f38ea6851bea536359cf69a7..aaa8a4414602ff36e4cd97586f87b295a0ffa1c0 100644
--- a/src/media/video/video_sender.h
+++ b/src/media/video/video_sender.h
@@ -49,9 +49,9 @@ public:
                 SocketPair& socketPair,
                 const uint16_t seqVal,
                 uint16_t mtu,
-                bool isScreenScharing);
+                bool allowHwAccel = true);
 
-    ~VideoSender();
+    ~VideoSender() {};
 
     void forceKeyFrame();