diff --git a/src/media/libav_deps.h b/src/media/libav_deps.h
index c3dd6d69b52985e8c50e9a0c13627cdbef036206..8983445855fcdfb40186da9dc16c40d5e9b7eea7 100644
--- a/src/media/libav_deps.h
+++ b/src/media/libav_deps.h
@@ -100,5 +100,9 @@ static inline const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat p
                                                   (x)->width, (x)->height)
 #endif
 
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102)
+#define av_free_packet av_packet_unref
+#endif
+
 
 #endif // __LIBAV_DEPS_H__
diff --git a/src/media/media_buffer.cpp b/src/media/media_buffer.cpp
index 8f182f973880eb60113144a59725e08b9464eee3..8d116f49c5cf48b285d91d5a839a68301e0d2461 100644
--- a/src/media/media_buffer.cpp
+++ b/src/media/media_buffer.cpp
@@ -125,8 +125,13 @@ VideoFrame::setFromMemory(uint8_t* ptr, int format, int width, int height) noexc
     setGeometry(format, width, height);
     if (not ptr)
         return;
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102)
+    av_image_fill_arrays(frame_->data, frame_->linesize, (uint8_t*)ptr,
+                         (AVPixelFormat)frame_->format, width, height, 1);
+#else
     avpicture_fill((AVPicture*)frame_.get(), (uint8_t*)ptr,
                    (AVPixelFormat)frame_->format, width, height);
+#endif
 }
 
 void
@@ -155,9 +160,16 @@ VideoFrame&
 VideoFrame::operator =(const VideoFrame& src)
 {
     reserve(src.format(), src.width(), src.height());
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102)
+    auto source = src.pointer();
+    av_image_copy(frame_->data, frame_->linesize, (const uint8_t **)source->data,
+                  source->linesize, (AVPixelFormat)frame_->format,
+                  frame_->width, frame_->height);
+#else
     av_picture_copy((AVPicture *)frame_.get(), (AVPicture *)src.pointer(),
                     (AVPixelFormat)frame_->format,
                     frame_->width, frame_->height);
+#endif
     return *this;
 }
 
@@ -166,8 +178,13 @@ VideoFrame::operator =(const VideoFrame& src)
 std::size_t
 videoFrameSize(int format, int width, int height)
 {
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102)
+    return av_image_get_buffer_size((AVPixelFormat)libav_utils::libav_pixel_format(format),
+                                    width, height, 1);
+#else
     return avpicture_get_size((AVPixelFormat)libav_utils::libav_pixel_format(format),
                               width, height);
+#endif
 }
 
 void
diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index 6f137cd3b75e024c55430761747b5ab1b86cc51e..055bb4a17f3ac09b124520327c0ed26f9ffa7e7a 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -170,7 +170,11 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format)
 
     // find the first audio stream from the input
     for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i)
+#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32)
+        if (inputCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+#else
         if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+#endif
             streamIndex_ = i;
 
     if (streamIndex_ == -1) {
@@ -180,6 +184,16 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format)
 
     // Get a pointer to the codec context for the video stream
     avStream_ = inputCtx_->streams[streamIndex_];
+#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32)
+    inputDecoder_ = avcodec_find_decoder(avStream_->codecpar->codec_id);
+    if (!inputDecoder_) {
+        RING_ERR("Unsupported codec");
+        return -1;
+    }
+
+    decoderCtx_ = avcodec_alloc_context3(inputDecoder_);
+    avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar);
+#else
     decoderCtx_ = avStream_->codec;
     if (decoderCtx_ == 0) {
         RING_ERR("Decoder context is NULL");
@@ -192,6 +206,7 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format)
         RING_ERR("Unsupported codec");
         return -1;
     }
+#endif
 
     decoderCtx_->thread_count = std::thread::hardware_concurrency();
     decoderCtx_->channels = format.nb_channels;
@@ -253,7 +268,11 @@ int MediaDecoder::setupFromVideoData()
 
     // find the first video stream from the input
     for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i)
+#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32)
+        if (inputCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
+#else
         if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+#endif
             streamIndex_ = i;
 
     if (streamIndex_ == -1) {
@@ -263,12 +282,30 @@ int MediaDecoder::setupFromVideoData()
 
     // Get a pointer to the codec context for the video stream
     avStream_ = inputCtx_->streams[streamIndex_];
+#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32)
+    inputDecoder_ = avcodec_find_decoder(avStream_->codecpar->codec_id);
+    if (!inputDecoder_) {
+        RING_ERR("Unsupported codec");
+        return -1;
+    }
+
+    decoderCtx_ = avcodec_alloc_context3(inputDecoder_);
+    avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar);
+#else
     decoderCtx_ = avStream_->codec;
     if (decoderCtx_ == 0) {
         RING_ERR("Decoder context is NULL");
         return -1;
     }
 
+    // find the decoder for the video stream
+    inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id);
+    if (!inputDecoder_) {
+        RING_ERR("Unsupported codec");
+        return -1;
+    }
+#endif
+
     decoderCtx_->thread_count = std::thread::hardware_concurrency();
 
 #ifdef RING_ACCEL
@@ -278,13 +315,6 @@ int MediaDecoder::setupFromVideoData()
     }
 #endif // RING_ACCEL
 
-    // find the decoder for the video stream
-    inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id);
-    if (!inputDecoder_) {
-        RING_ERR("Unsupported codec");
-        return -1;
-    }
-
     if (emulateRate_) {
         RING_DBG("Using framerate emulation");
         startTime_ = av_gettime();
@@ -331,12 +361,24 @@ MediaDecoder::decode(VideoFrame& result)
 
     auto frame = result.pointer();
     int frameFinished = 0;
-    int len = avcodec_decode_video2(decoderCtx_, frame,
-                                    &frameFinished, &inpacket);
-    av_packet_unref(&inpacket);
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
+    ret = avcodec_send_packet(decoderCtx_, &inpacket);
+    if (ret < 0)
+        return ret == AVERROR_EOF ? Status::Success : Status::DecodeError;
 
-    if (len <= 0)
+    ret = avcodec_receive_frame(decoderCtx_, frame);
+    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+        return Status::DecodeError;
+    if (ret >= 0)
+        frameFinished = 1;
+#else
+    ret = avcodec_decode_video2(decoderCtx_, frame,
+                                    &frameFinished, &inpacket);
+    if (ret <= 0)
         return Status::DecodeError;
+#endif
+
+    av_packet_unref(&inpacket);
 
     if (frameFinished) {
         frame->format = (AVPixelFormat) correctPixFmt(frame->format);
@@ -348,8 +390,13 @@ MediaDecoder::decode(VideoFrame& result)
                 return Status::RestartRequired;
         }
 #endif // RING_ACCEL
+#if LIBAVUTIL_VERSION_CHECK(55, 20, 0, 34, 100)
+        if (emulateRate_ and frame->pts != AV_NOPTS_VALUE) {
+            auto frame_time = getTimeBase()*(frame->pts - avStream_->start_time);
+#else
         if (emulateRate_ and frame->pkt_pts != AV_NOPTS_VALUE) {
             auto frame_time = getTimeBase()*(frame->pkt_pts - avStream_->start_time);
+#endif
             auto target = startTime_ + static_cast<std::int64_t>(frame_time.real() * 1e6);
             auto now = av_gettime();
             if (target > now) {
@@ -390,17 +437,34 @@ MediaDecoder::decode(const AudioFrame& decodedFrame)
     }
 
     int frameFinished = 0;
-    int len = avcodec_decode_audio4(decoderCtx_, frame,
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
+        ret = avcodec_send_packet(decoderCtx_, &inpacket);
+        if (ret < 0)
+            return ret == AVERROR_EOF ? Status::Success : Status::DecodeError;
+
+    ret = avcodec_receive_frame(decoderCtx_, frame);
+    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+        return Status::DecodeError;
+    if (ret >= 0)
+        frameFinished = 1;
+#else
+    ret = avcodec_decode_audio4(decoderCtx_, frame,
                                     &frameFinished, &inpacket);
     av_packet_unref(&inpacket);
 
-    if (len <= 0) {
+    if (ret <= 0)
         return Status::DecodeError;
-    }
+#endif
 
     if (frameFinished) {
+        av_packet_unref(&inpacket);
+#if LIBAVUTIL_VERSION_CHECK(55, 20, 0, 34, 100)
+        if (emulateRate_ and frame->pts != AV_NOPTS_VALUE) {
+            auto frame_time = getTimeBase()*(frame->pts - avStream_->start_time);
+#else
         if (emulateRate_ and frame->pkt_pts != AV_NOPTS_VALUE) {
             auto frame_time = getTimeBase()*(frame->pkt_pts - avStream_->start_time);
+#endif
             auto target = startTime_ + static_cast<std::int64_t>(frame_time.real() * 1e6);
             auto now = av_gettime();
             if (target > now) {
@@ -421,15 +485,28 @@ MediaDecoder::flush(VideoFrame& result)
     av_init_packet(&inpacket);
 
     int frameFinished = 0;
-    auto len = avcodec_decode_video2(decoderCtx_, result.pointer(),
+    int ret = 0;
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
+    ret = avcodec_send_packet(decoderCtx_, &inpacket);
+    if (ret < 0)
+        return ret == AVERROR_EOF ? Status::Success : Status::DecodeError;
+
+    ret = avcodec_receive_frame(decoderCtx_, result.pointer());
+    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+        return Status::DecodeError;
+    if (ret >= 0)
+        frameFinished = 1;
+#else
+    ret = avcodec_decode_video2(decoderCtx_, result.pointer(),
                                     &frameFinished, &inpacket);
-
     av_packet_unref(&inpacket);
 
-    if (len <= 0)
+    if (ret <= 0)
         return Status::DecodeError;
+#endif
 
     if (frameFinished) {
+        av_packet_unref(&inpacket);
 #ifdef RING_ACCEL
         // flush is called when closing the stream
         // so don't restart the media decoder
diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index b229bc814d741f6a233ade2b78dab09534406f28..e79e5090933678c0a4f657afe9e24fd7bdee1b8b 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -228,7 +228,13 @@ MediaEncoder::openOutput(const char *filename,
     if (!stream_)
         throw MediaEncoderException("Could not allocate stream");
 
+#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32)
+    auto par = std::unique_ptr<AVCodecParameters>(new AVCodecParameters());
+    avcodec_parameters_from_context(par.get(), encoderCtx_);
+    stream_->codecpar = par.release();
+#else
     stream_->codec = encoderCtx_;
+#endif
 #ifdef RING_VIDEO
     if (args.codec->systemCodecInfo.mediaType == MEDIA_VIDEO) {
         // allocate buffers for both scaled (pre-encoder) and encoded frames
@@ -315,10 +321,41 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
     memset(&pkt, 0, sizeof(pkt));
     av_init_packet(&pkt);
 
-#if LIBAVCODEC_VERSION_MAJOR >= 54
+    int ret = 0;
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
+    ret = avcodec_send_frame(encoderCtx_, frame);
+    if (ret < 0)
+        return -1;
+
+    while (1) {
+        ret = avcodec_receive_packet(encoderCtx_, &pkt);
+        if (ret == AVERROR(EAGAIN))
+            break;
+        if (ret < 0)
+            return -1;
+
+        if (pkt.size) {
+            if (pkt.pts != AV_NOPTS_VALUE)
+                pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
+                                       stream_->time_base);
+            if (pkt.dts != AV_NOPTS_VALUE)
+                pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
+                                       stream_->time_base);
+
+            pkt.stream_index = stream_->index;
+
+            // write the compressed frame
+            ret = av_write_frame(outputCtx_, &pkt);
+            if (ret < 0)
+                print_averror("av_write_frame", ret);
+            else
+                break;
+        }
+    }
+#elif LIBAVCODEC_VERSION_MAJOR >= 54
 
     int got_packet;
-    int ret = avcodec_encode_video2(encoderCtx_, &pkt, frame, &got_packet);
+    ret = avcodec_encode_video2(encoderCtx_, &pkt, frame, &got_packet);
     if (ret < 0) {
         print_averror("avcodec_encode_video2", ret);
         av_free_packet(&pkt);
@@ -342,8 +379,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
     }
 
 #else
-
-    int ret = avcodec_encode_video(encoderCtx_, encoderBuffer_.data(),
+    ret = avcodec_encode_video(encoderCtx_, encoderBuffer_.data(),
                                    encoderBufferSize_, frame);
     if (ret < 0) {
         print_averror("avcodec_encode_video", ret);
@@ -448,9 +484,41 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
         av_init_packet(&pkt);
         pkt.data = NULL; // packet data will be allocated by the encoder
         pkt.size = 0;
+        int ret = 0;
 
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
+        ret = avcodec_send_frame(encoderCtx_, frame);
+        if (ret < 0)
+            return -1;
+
+        while (1) {
+            ret = avcodec_receive_packet(encoderCtx_, &pkt);
+            if (ret == AVERROR(EAGAIN))
+                break;
+            if (ret < 0)
+                return -1;
+
+            if (pkt.size) {
+                if (pkt.pts != AV_NOPTS_VALUE)
+                    pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
+                                           stream_->time_base);
+                if (pkt.dts != AV_NOPTS_VALUE)
+                    pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
+                                           stream_->time_base);
+
+                pkt.stream_index = stream_->index;
+
+                // write the compressed frame
+                ret = av_write_frame(outputCtx_, &pkt);
+                if (ret < 0)
+                    print_averror("av_write_frame", ret);
+                else
+                    break;
+            }
+        }
+#else
         int got_packet;
-        int ret = avcodec_encode_audio2(encoderCtx_, &pkt, frame, &got_packet);
+        ret = avcodec_encode_audio2(encoderCtx_, &pkt, frame, &got_packet);
         if (ret < 0) {
             print_averror("avcodec_encode_audio2", ret);
             av_free_packet(&pkt);
@@ -473,6 +541,7 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
             if (ret < 0)
                 print_averror("av_write_frame", ret);
         }
+#endif
 
         av_free_packet(&pkt);
         av_frame_free(&frame);
@@ -487,8 +556,38 @@ int MediaEncoder::flush()
     memset(&pkt, 0, sizeof(pkt));
     av_init_packet(&pkt);
 
-    int ret;
-#if (LIBAVCODEC_VERSION_MAJOR >= 54)
+    int ret = 0;
+#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
+    ret = avcodec_send_frame(encoderCtx_, nullptr);
+    if (ret < 0)
+        return -1;
+
+    while (1) {
+        ret = avcodec_receive_packet(encoderCtx_, &pkt);
+        if (ret == AVERROR(EAGAIN))
+            break;
+        if (ret < 0)
+            return -1;
+
+        if (pkt.size) {
+            if (pkt.pts != AV_NOPTS_VALUE)
+                pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
+                                       stream_->time_base);
+            if (pkt.dts != AV_NOPTS_VALUE)
+                pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
+                                       stream_->time_base);
+
+            pkt.stream_index = stream_->index;
+
+            // write the compressed frame
+            ret = av_write_frame(outputCtx_, &pkt);
+            if (ret < 0)
+                print_averror("av_write_frame", ret);
+            else
+                break;
+        }
+    }
+#elif (LIBAVCODEC_VERSION_MAJOR >= 54)
 
     int got_packet;
 
@@ -531,7 +630,11 @@ std::string
 MediaEncoder::print_sdp()
 {
     /* theora sdp can be huge */
+#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32)
+    const auto sdp_size = outputCtx_->streams[0]->codecpar->extradata_size + 2048;
+#else
     const auto sdp_size = outputCtx_->streams[0]->codec->extradata_size + 2048;
+#endif
     std::string result;
     std::string sdp(sdp_size, '\0');
     av_sdp_create(&outputCtx_, 1, &(*sdp.begin()), sdp_size);
diff --git a/src/media/video/video_scaler.cpp b/src/media/video/video_scaler.cpp
index c575893b7ed4edf3d39fa6d6df212f42aff990c1..4123e700f091ab06884be17c89268469a65d3465 100644
--- a/src/media/video/video_scaler.cpp
+++ b/src/media/video/video_scaler.cpp
@@ -124,10 +124,10 @@ VideoScaler::scale_and_pad(const VideoFrame& input, VideoFrame& output,
             x_shift = -((-x_shift) >> out_desc->log2_chroma_w);
             y_shift = -((-y_shift) >> out_desc->log2_chroma_h);
         }
-#if LIBAVUTIL_VERSION_MAJOR < 56
-        auto x_step = out_desc->comp[i].step_minus1 + 1; // using deprecated api
-#else
+#if LIBAVUTIL_VERSION_CHECK(55, 20, 0, 17, 103)
         auto x_step = out_desc->comp[i].step;
+#else
+        auto x_step = out_desc->comp[i].step_minus1 + 1;
 #endif
         tmp_data_[i] = output_frame->data[i] + y_shift * output_frame->linesize[i] + x_shift * x_step;
     }