diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 69e541a8f0..9a8ca81db9 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4297,7 +4297,7 @@ int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
  */
 int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                          int *got_picture_ptr,
-                         AVPacket *avpkt);
+                         const AVPacket *avpkt);
 
 /**
  * Decode a subtitle message.
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index a4bd442176..5a51900ebf 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -20,6 +20,7 @@
  */
 
 #include "avcodec.h"
+#include "internal.h"
 #include "libavutil/avassert.h"
 #include "bytestream.h"
 
@@ -30,19 +31,23 @@ void av_destruct_packet_nofree(AVPacket *pkt)
     pkt->side_data_elems = 0;
 }
 
-void av_destruct_packet(AVPacket *pkt)
+void ff_packet_free_side_data(AVPacket *pkt)
 {
     int i;
-
-    av_free(pkt->data);
-    pkt->data = NULL; pkt->size = 0;
-
     for (i = 0; i < pkt->side_data_elems; i++)
         av_free(pkt->side_data[i].data);
     av_freep(&pkt->side_data);
     pkt->side_data_elems = 0;
 }
 
+void av_destruct_packet(AVPacket *pkt)
+{
+    av_free(pkt->data);
+    pkt->data = NULL; pkt->size = 0;
+
+    ff_packet_free_side_data(pkt);
+}
+
 void av_init_packet(AVPacket *pkt)
 {
     pkt->pts   = AV_NOPTS_VALUE;
@@ -239,8 +244,6 @@ int av_packet_split_side_data(AVPacket *pkt){
         unsigned int size;
         uint8_t *p;
 
-        av_dup_packet(pkt);
-
         p = pkt->data + pkt->size - 8 - 5;
         for (i=1; ; i++){
             size = AV_RB32(p);
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 068b34bbaa..e6270f81bf 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -96,6 +96,11 @@ unsigned int avpriv_toupper4(unsigned int x);
  */
 void ff_init_buffer_info(AVCodecContext *s, AVFrame *pic);
 
+/**
+ * Remove and free all side data from packet.
+ */
+void ff_packet_free_side_data(AVPacket *pkt);
+
 int avpriv_lock_avformat(void);
 int avpriv_unlock_avformat(void);
 
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 219be6b7fb..e25f1dfb41 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -994,24 +994,26 @@ static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
 
 int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                          int *got_picture_ptr,
-                         AVPacket *avpkt)
+                         const AVPacket *avpkt)
 {
     int ret;
+    // copy to ensure we do not change avpkt
+    AVPacket tmp = *avpkt;
 
     *got_picture_ptr= 0;
     if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
         return -1;
 
     if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){
-        av_packet_split_side_data(avpkt);
-        apply_param_change(avctx, avpkt);
-        avctx->pkt = avpkt;
+        int did_split = av_packet_split_side_data(&tmp);
+        apply_param_change(avctx, &tmp);
+        avctx->pkt = &tmp;
         if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME)
              ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
-                                          avpkt);
+                                          &tmp);
         else {
             ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
-                              avpkt);
+                              &tmp);
             picture->pkt_dts= avpkt->dts;
 
             if(!avctx->has_b_frames){
@@ -1030,6 +1032,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
 
         emms_c(); //needed to avoid an emms_c() call before every return;
 
+        avctx->pkt = NULL;
+        if (did_split)
+            ff_packet_free_side_data(&tmp);
 
         if (*got_picture_ptr){
             avctx->frame_number++;