diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index df9af689f23239e679d4da671e420bb83f1b4976..5c8b4cbf56a3239eecaf18506724d5aa68351889 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -118,6 +118,19 @@ fail2:
     return 0;
 }
 
+static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt)
+{
+    int ret = 0;
+
+    av_packet_unref(avci->last_pkt_props);
+    if (pkt) {
+        ret = av_packet_copy_props(avci->last_pkt_props, pkt);
+        if (!ret)
+            avci->last_pkt_props->size = pkt->size; // HACK: Needed for ff_init_buffer_info().
+    }
+    return ret;
+}
+
 static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
 {
     int ret;
@@ -394,7 +407,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
     if ((avctx->coded_width || avctx->coded_height) && av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx))
         return AVERROR(EINVAL);
 
-    avctx->internal->pkt = avpkt;
+    ret = extract_packet_props(avci, avpkt);
+    if (ret < 0)
+        return ret;
     ret = apply_param_change(avctx, avpkt);
     if (ret < 0)
         return ret;
@@ -412,7 +427,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
         if (ret < 0)
             goto fail;
 
-        avctx->internal->pkt = &tmp;
+        ret = extract_packet_props(avci, &tmp);
+        if (ret < 0)
+            return ret;
         if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
             ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
                                          &tmp);
@@ -438,7 +455,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
 fail:
         emms_c(); //needed to avoid an emms_c() call before every return;
 
-        avctx->internal->pkt = NULL;
 #if FF_API_MERGE_SD
         if (did_split) {
             av_packet_free_side_data(&tmp);
@@ -524,7 +540,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
         if (ret < 0)
             goto fail;
 
-        avctx->internal->pkt = &tmp;
+        ret = extract_packet_props(avci, &tmp);
+        if (ret < 0)
+            return ret;
         if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
             ret = ff_thread_decode_frame(avctx, frame, got_frame_ptr, &tmp);
         else {
@@ -548,7 +566,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                 frame->sample_rate = avctx->sample_rate;
         }
 
-        side= av_packet_get_side_data(avctx->internal->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
+        side= av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
         if(side && side_size>=10) {
             avctx->internal->skip_samples = AV_RL32(side) * avctx->internal->skip_samples_multiplier;
             discard_padding = AV_RL32(side + 4);
@@ -630,7 +648,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
             }
         }
 fail:
-        avctx->internal->pkt = NULL;
 #if FF_API_MERGE_SD
         if (did_split) {
             av_packet_free_side_data(&tmp);
@@ -862,7 +879,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
         if (ret < 0) {
             *got_sub_ptr = 0;
         } else {
-            avctx->internal->pkt = &pkt_recoded;
+             ret = extract_packet_props(avctx->internal, &pkt_recoded);
+             if (ret < 0)
+                return ret;
 
             if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE)
                 sub->pts = av_rescale_q(avpkt->pts,
@@ -912,7 +931,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
 
                 av_packet_unref(&pkt_recoded);
             }
-            avctx->internal->pkt = NULL;
         }
 
 #if FF_API_MERGE_SD
@@ -1292,7 +1310,7 @@ static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame)
 
 int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame)
 {
-    const AVPacket *pkt = avctx->internal->pkt;
+    const AVPacket *pkt = avctx->internal->last_pkt_props;
     int i;
     static const struct {
         enum AVPacketSideDataType packet;
@@ -1338,16 +1356,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
         } else {
             frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD);
         }
-    } else {
-        frame->pts = AV_NOPTS_VALUE;
-#if FF_API_PKT_PTS
-FF_DISABLE_DEPRECATION_WARNINGS
-        frame->pkt_pts = AV_NOPTS_VALUE;
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-        av_frame_set_pkt_pos     (frame, -1);
-        av_frame_set_pkt_duration(frame, 0);
-        av_frame_set_pkt_size    (frame, -1);
     }
     frame->reordered_opaque = avctx->reordered_opaque;
 
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index e5f132a67304027ca132f405810fde74eedccbae..90a887332e2b4ef05c5d45de97c04c383cd6d6eb 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -138,10 +138,10 @@ typedef struct AVCodecInternal {
     void *thread_ctx;
 
     /**
-     * Current packet as passed into the decoder, to avoid having to pass the
-     * packet into every function.
+     * Properties (timestamps+side data) extracted from the last packet passed
+     * for decoding.
      */
-    const AVPacket *pkt;
+    AVPacket *last_pkt_props;
 
     /**
      * temporary buffer used for encoders to store their bitstream
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 46c6292253d441b1a0b4c9d41013c01f6fc9e666..13d682842d6d14f8784a1b4442e54f1de06b1a73 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -800,7 +800,7 @@ int ff_frame_thread_init(AVCodecContext *avctx)
         }
         *copy->internal = *src->internal;
         copy->internal->thread_ctx = p;
-        copy->internal->pkt = &p->avpkt;
+        copy->internal->last_pkt_props = &p->avpkt;
 
         if (!i) {
             src = copy;
diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c
index e53eb2eacc800aabee143097a6f6e0532489abbc..6dcb5f2e662462f886075cdae7824a81d0974d7d 100644
--- a/libavcodec/rawdec.c
+++ b/libavcodec/rawdec.c
@@ -237,8 +237,8 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
     if (res < 0)
         return res;
 
-    av_frame_set_pkt_pos     (frame, avctx->internal->pkt->pos);
-    av_frame_set_pkt_duration(frame, avctx->internal->pkt->duration);
+    av_frame_set_pkt_pos     (frame, avctx->internal->last_pkt_props->pos);
+    av_frame_set_pkt_duration(frame, avctx->internal->last_pkt_props->duration);
 
     if (context->tff >= 0) {
         frame->interlaced_frame = 1;
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 56e58cc426425bbbabca5dfbbd2852c55cf1fafc..6a68971d680113174e91728b39ee72401c6f1742 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -684,6 +684,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
         goto free_and_end;
     }
 
+    avctx->internal->last_pkt_props = av_packet_alloc();
+    if (!avctx->internal->last_pkt_props) {
+        ret = AVERROR(ENOMEM);
+        goto free_and_end;
+    }
+
     avctx->internal->skip_samples_multiplier = 1;
 
     if (codec->priv_data_size > 0) {
@@ -1110,6 +1116,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         av_frame_free(&avctx->internal->to_free);
         av_frame_free(&avctx->internal->buffer_frame);
         av_packet_free(&avctx->internal->buffer_pkt);
+        av_packet_free(&avctx->internal->last_pkt_props);
         av_freep(&avctx->internal->pool);
     }
     av_freep(&avctx->internal);
@@ -1158,6 +1165,7 @@ av_cold int avcodec_close(AVCodecContext *avctx)
         av_frame_free(&avctx->internal->to_free);
         av_frame_free(&avctx->internal->buffer_frame);
         av_packet_free(&avctx->internal->buffer_pkt);
+        av_packet_free(&avctx->internal->last_pkt_props);
         for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
             av_buffer_pool_uninit(&pool->pools[i]);
         av_freep(&avctx->internal->pool);