diff mbox series

[FFmpeg-devel,31/57] avcodec/mpegpicture: Split MPVPicture into WorkPicture and ordinary Pic

Message ID AS8P250MB0744ACCCA409A9F8862D17848F1B2@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM
State New
Headers show
Series [FFmpeg-devel,01/14] avcodec/get_buffer: Remove redundant check | expand

Commit Message

Andreas Rheinhardt April 29, 2024, 9:14 p.m. UTC
There are two types of MPVPictures: Three (cur_pic, last_pic, next_pic)
that are directly part of MpegEncContext and an array of MPVPictures
that are separately allocated and are mostly accessed via pointers
(cur|last|next)_pic_ptr; they are also used to store AVFrames in the
encoder (necessary due to B-frames). As the name implies, each of the
former is directly associated with one of the _ptr pointers:
They actually share the same underlying buffers, but the ones
that are part of the context can have their data pointers offset
and their linesize doubled for field pictures.

Up until now, each of these had their own references; in particular,
there was an underlying av_frame_ref() to sync cur_pic and cur_pic_ptr
etc. This is wasteful.

This commit changes this relationship: cur_pic, last_pic and next_pic
now become MPVWorkPictures; this structure does not have an AVFrame
at all any more, but only the cached values of data and linesize.
It also contains a pointer to the corresponding MPVPicture, establishing
a more natural relationsship between the two.
This already means that creating the context-pictures from the pointers
can no longer fail.

What has not been changed is the fact that the MPVPicture* pointers
are not ownership pointers and that the MPVPictures are part of an
array of MPVPictures that is owned by a single AVCodecContext.
Doing so will be done in a latter commit.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/d3d12va_mpeg2.c               |  10 +-
 libavcodec/d3d12va_vc1.c                 |  10 +-
 libavcodec/dxva2_mpeg2.c                 |  16 +--
 libavcodec/dxva2_vc1.c                   |  20 ++--
 libavcodec/h261dec.c                     |   7 +-
 libavcodec/h263dec.c                     |  33 +++---
 libavcodec/ituh263dec.c                  |   4 +-
 libavcodec/mpeg12dec.c                   |  56 ++++-----
 libavcodec/mpeg12enc.c                   |  14 +--
 libavcodec/mpeg4videodec.c               |   4 +-
 libavcodec/mpeg4videoenc.c               |   4 +-
 libavcodec/mpeg_er.c                     |   6 +-
 libavcodec/mpegpicture.c                 |  58 ++++++---
 libavcodec/mpegpicture.h                 |  31 ++++-
 libavcodec/mpegvideo.c                   |  11 --
 libavcodec/mpegvideo.h                   |   9 +-
 libavcodec/mpegvideo_dec.c               | 143 +++++++++--------------
 libavcodec/mpegvideo_enc.c               |  99 ++++++----------
 libavcodec/mpegvideo_motion.c            |   8 +-
 libavcodec/mpv_reconstruct_mb_template.c |   4 +-
 libavcodec/mss2.c                        |   2 +-
 libavcodec/nvdec_mpeg12.c                |   6 +-
 libavcodec/nvdec_mpeg4.c                 |   6 +-
 libavcodec/nvdec_vc1.c                   |   6 +-
 libavcodec/ratecontrol.c                 |  10 +-
 libavcodec/rv10.c                        |  28 ++---
 libavcodec/rv34.c                        |  38 +++---
 libavcodec/snowenc.c                     |  17 +--
 libavcodec/svq1enc.c                     |   5 +-
 libavcodec/vaapi_mpeg2.c                 |  12 +-
 libavcodec/vaapi_mpeg4.c                 |  14 +--
 libavcodec/vaapi_vc1.c                   |  14 ++-
 libavcodec/vc1.c                         |   2 +-
 libavcodec/vc1_block.c                   |  12 +-
 libavcodec/vc1_mc.c                      |  32 ++---
 libavcodec/vc1_pred.c                    |   2 +-
 libavcodec/vc1dec.c                      |  37 +++---
 libavcodec/vdpau.c                       |   2 +-
 libavcodec/vdpau_mpeg12.c                |   8 +-
 libavcodec/vdpau_mpeg4.c                 |   6 +-
 libavcodec/vdpau_vc1.c                   |  12 +-
 libavcodec/videotoolbox.c                |   2 +-
 libavcodec/wmv2dec.c                     |   2 +-
 43 files changed, 397 insertions(+), 425 deletions(-)

Comments

Michael Niedermayer April 30, 2024, 6:57 p.m. UTC | #1
On Mon, Apr 29, 2024 at 11:14:12PM +0200, Andreas Rheinhardt wrote:
> There are two types of MPVPictures: Three (cur_pic, last_pic, next_pic)
> that are directly part of MpegEncContext and an array of MPVPictures
> that are separately allocated and are mostly accessed via pointers
> (cur|last|next)_pic_ptr; they are also used to store AVFrames in the
> encoder (necessary due to B-frames). As the name implies, each of the
> former is directly associated with one of the _ptr pointers:
> They actually share the same underlying buffers, but the ones
> that are part of the context can have their data pointers offset
> and their linesize doubled for field pictures.
> 
> Up until now, each of these had their own references; in particular,
> there was an underlying av_frame_ref() to sync cur_pic and cur_pic_ptr
> etc. This is wasteful.
> 
> This commit changes this relationship: cur_pic, last_pic and next_pic
> now become MPVWorkPictures; this structure does not have an AVFrame
> at all any more, but only the cached values of data and linesize.
> It also contains a pointer to the corresponding MPVPicture, establishing
> a more natural relationsship between the two.
> This already means that creating the context-pictures from the pointers
> can no longer fail.
> 
> What has not been changed is the fact that the MPVPicture* pointers
> are not ownership pointers and that the MPVPictures are part of an
> array of MPVPictures that is owned by a single AVCodecContext.
> Doing so will be done in a latter commit.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>

segfaults

[vc1 @ 0xa0c81c0] Failed to open codec in avformat_find_stream_info
==840294== Invalid read of size 4
==840294==    at 0xDB91F4: ff_vc1_mc_4mv_chroma4 (vc1_mc.c:893)
==840294==    by 0xDA4FD8: vc1_decode_p_mb_intfr (vc1_block.c:1661)
==840294==    by 0xDAD9CD: vc1_decode_p_blocks (vc1_block.c:2831)
==840294==    by 0xDAE6A4: ff_vc1_decode_blocks (vc1_block.c:2996)
==840294==    by 0xDC5EFB: vc1_decode_frame (vc1dec.c:1304)
==840294==    by 0x99B6D2: decode_simple_internal (decode.c:412)
==840294==    by 0x99BBFB: decode_simple_receive_frame (decode.c:582)
==840294==    by 0x99BD7F: decode_receive_frame_internal (decode.c:611)
==840294==    by 0x99C135: avcodec_send_packet (decode.c:702)
==840294==    by 0x66BE65: try_decode_frame (demux.c:2156)
==840294==    by 0x66EB84: avformat_find_stream_info (demux.c:2840)
==840294==    by 0x24F991: ifile_open (ffmpeg_demux.c:1707)
==840294==    by 0x278387: open_files (ffmpeg_opt.c:1206)
==840294==    by 0x27854A: ffmpeg_parse_options (ffmpeg_opt.c:1246)
==840294==    by 0x28CBF7: main (ffmpeg.c:941)
==840294==  Address 0x9c is not stack'd, malloc'd or (recently) free'd

[...]
Andreas Rheinhardt April 30, 2024, 7:07 p.m. UTC | #2
Michael Niedermayer:
> On Mon, Apr 29, 2024 at 11:14:12PM +0200, Andreas Rheinhardt wrote:
>> There are two types of MPVPictures: Three (cur_pic, last_pic, next_pic)
>> that are directly part of MpegEncContext and an array of MPVPictures
>> that are separately allocated and are mostly accessed via pointers
>> (cur|last|next)_pic_ptr; they are also used to store AVFrames in the
>> encoder (necessary due to B-frames). As the name implies, each of the
>> former is directly associated with one of the _ptr pointers:
>> They actually share the same underlying buffers, but the ones
>> that are part of the context can have their data pointers offset
>> and their linesize doubled for field pictures.
>>
>> Up until now, each of these had their own references; in particular,
>> there was an underlying av_frame_ref() to sync cur_pic and cur_pic_ptr
>> etc. This is wasteful.
>>
>> This commit changes this relationship: cur_pic, last_pic and next_pic
>> now become MPVWorkPictures; this structure does not have an AVFrame
>> at all any more, but only the cached values of data and linesize.
>> It also contains a pointer to the corresponding MPVPicture, establishing
>> a more natural relationsship between the two.
>> This already means that creating the context-pictures from the pointers
>> can no longer fail.
>>
>> What has not been changed is the fact that the MPVPicture* pointers
>> are not ownership pointers and that the MPVPictures are part of an
>> array of MPVPictures that is owned by a single AVCodecContext.
>> Doing so will be done in a latter commit.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> 
> segfaults
> 
> [vc1 @ 0xa0c81c0] Failed to open codec in avformat_find_stream_info
> ==840294== Invalid read of size 4
> ==840294==    at 0xDB91F4: ff_vc1_mc_4mv_chroma4 (vc1_mc.c:893)
> ==840294==    by 0xDA4FD8: vc1_decode_p_mb_intfr (vc1_block.c:1661)
> ==840294==    by 0xDAD9CD: vc1_decode_p_blocks (vc1_block.c:2831)
> ==840294==    by 0xDAE6A4: ff_vc1_decode_blocks (vc1_block.c:2996)
> ==840294==    by 0xDC5EFB: vc1_decode_frame (vc1dec.c:1304)
> ==840294==    by 0x99B6D2: decode_simple_internal (decode.c:412)
> ==840294==    by 0x99BBFB: decode_simple_receive_frame (decode.c:582)
> ==840294==    by 0x99BD7F: decode_receive_frame_internal (decode.c:611)
> ==840294==    by 0x99C135: avcodec_send_packet (decode.c:702)
> ==840294==    by 0x66BE65: try_decode_frame (demux.c:2156)
> ==840294==    by 0x66EB84: avformat_find_stream_info (demux.c:2840)
> ==840294==    by 0x24F991: ifile_open (ffmpeg_demux.c:1707)
> ==840294==    by 0x278387: open_files (ffmpeg_opt.c:1206)
> ==840294==    by 0x27854A: ffmpeg_parse_options (ffmpeg_opt.c:1246)
> ==840294==    by 0x28CBF7: main (ffmpeg.c:941)
> ==840294==  Address 0x9c is not stack'd, malloc'd or (recently) free'd
> 
> [...]

When I ported this code, I presumed that these frames need to exist (all
the time, not only for valid input) because otherwise the code would use
data of a non-existent frame. But I overlooked the check below that you
added in 6c4516d0413ea9b2a9b48fb83d0ba0ef7bc84f92. (Presumably you
tested with this sample?)
Thanks for testing. I will fix this.

- Andreas
diff mbox series

Patch

diff --git a/libavcodec/d3d12va_mpeg2.c b/libavcodec/d3d12va_mpeg2.c
index c2cf78104c..86a7d97b34 100644
--- a/libavcodec/d3d12va_mpeg2.c
+++ b/libavcodec/d3d12va_mpeg2.c
@@ -44,7 +44,7 @@  static int d3d12va_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint
 {
     const MpegEncContext      *s       = avctx->priv_data;
     D3D12VADecodeContext      *ctx     = D3D12VA_DECODE_CONTEXT(avctx);
-    D3D12DecodePictureContext *ctx_pic = s->cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
 
     if (!ctx)
         return -1;
@@ -69,7 +69,7 @@  static int d3d12va_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint
 static int d3d12va_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
 {
     const MpegEncContext      *s       = avctx->priv_data;
-    D3D12DecodePictureContext *ctx_pic = s->cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
 
     if (ctx_pic->slice_count >= MAX_SLICES) {
         return AVERROR(ERANGE);
@@ -88,7 +88,7 @@  static int d3d12va_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buff
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
     const MpegEncContext      *s            = avctx->priv_data;
-    D3D12DecodePictureContext *ctx_pic      = s->cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic      = s->cur_pic.ptr->hwaccel_picture_private;
 
     const int is_field = s->picture_structure != PICT_FRAME;
     const unsigned mb_count = s->mb_width * (s->mb_height >> is_field);
@@ -137,12 +137,12 @@  static int d3d12va_mpeg2_end_frame(AVCodecContext *avctx)
 {
     int ret;
     MpegEncContext            *s       = avctx->priv_data;
-    D3D12DecodePictureContext *ctx_pic = s->cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
 
     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
         return -1;
 
-    ret = ff_d3d12va_common_end_frame(avctx, s->cur_pic_ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
+    ret = ff_d3d12va_common_end_frame(avctx, s->cur_pic.ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
                                       &ctx_pic->qm, sizeof(ctx_pic->qm), update_input_arguments);
     if (!ret)
         ff_mpeg_draw_horiz_band(s, 0, avctx->height);
diff --git a/libavcodec/d3d12va_vc1.c b/libavcodec/d3d12va_vc1.c
index c4ac67ca04..dccc0fbffa 100644
--- a/libavcodec/d3d12va_vc1.c
+++ b/libavcodec/d3d12va_vc1.c
@@ -45,7 +45,7 @@  static int d3d12va_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_
 {
     const VC1Context          *v       = avctx->priv_data;
     D3D12VADecodeContext      *ctx     = D3D12VA_DECODE_CONTEXT(avctx);
-    D3D12DecodePictureContext *ctx_pic = v->s.cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic = v->s.cur_pic.ptr->hwaccel_picture_private;
 
     if (!ctx)
         return -1;
@@ -67,7 +67,7 @@  static int d3d12va_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_
 static int d3d12va_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
 {
     const VC1Context          *v       = avctx->priv_data;
-    D3D12DecodePictureContext *ctx_pic = v->s.cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic = v->s.cur_pic.ptr->hwaccel_picture_private;
 
     if (ctx_pic->slice_count >= MAX_SLICES) {
         return AVERROR(ERANGE);
@@ -93,7 +93,7 @@  static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
 {
     const VC1Context *v                     = avctx->priv_data;
     const MpegEncContext      *s            = &v->s;
-    D3D12DecodePictureContext *ctx_pic      = s->cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic      = s->cur_pic.ptr->hwaccel_picture_private;
     D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args = &input_args->FrameArguments[input_args->NumFrameArguments++];
 
     const unsigned mb_count = s->mb_width * (s->mb_height >> v->field_mode);
@@ -151,12 +151,12 @@  static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
 static int d3d12va_vc1_end_frame(AVCodecContext *avctx)
 {
     const VC1Context          *v       = avctx->priv_data;
-    D3D12DecodePictureContext *ctx_pic = v->s.cur_pic_ptr->hwaccel_picture_private;
+    D3D12DecodePictureContext *ctx_pic = v->s.cur_pic.ptr->hwaccel_picture_private;
 
     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
         return -1;
 
-    return ff_d3d12va_common_end_frame(avctx, v->s.cur_pic_ptr->f,
+    return ff_d3d12va_common_end_frame(avctx, v->s.cur_pic.ptr->f,
                                        &ctx_pic->pp, sizeof(ctx_pic->pp),
                                        NULL, 0,
                                        update_input_arguments);
diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c
index d29a5bb538..4b58466878 100644
--- a/libavcodec/dxva2_mpeg2.c
+++ b/libavcodec/dxva2_mpeg2.c
@@ -45,17 +45,17 @@  void ff_dxva2_mpeg2_fill_picture_parameters(AVCodecContext *avctx,
                                     DXVA_PictureParameters *pp)
 {
     const struct MpegEncContext *s = avctx->priv_data;
-    const MPVPicture *current_picture = s->cur_pic_ptr;
+    const MPVPicture *current_picture = s->cur_pic.ptr;
     int is_field = s->picture_structure != PICT_FRAME;
 
     memset(pp, 0, sizeof(*pp));
     pp->wDeblockedPictureIndex       = 0;
     if (s->pict_type != AV_PICTURE_TYPE_I)
-        pp->wForwardRefPictureIndex  = ff_dxva2_get_surface_index(avctx, ctx, s->last_pic.f, 0);
+        pp->wForwardRefPictureIndex  = ff_dxva2_get_surface_index(avctx, ctx, s->last_pic.ptr->f, 0);
     else
         pp->wForwardRefPictureIndex  = 0xffff;
     if (s->pict_type == AV_PICTURE_TYPE_B)
-        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_pic.f, 0);
+        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_pic.ptr->f, 0);
     else
         pp->wBackwardRefPictureIndex = 0xffff;
     pp->wDecodedPictureIndex         = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f, 1);
@@ -157,7 +157,7 @@  static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     const struct MpegEncContext *s = avctx->priv_data;
     AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
     struct dxva2_picture_context *ctx_pic =
-        s->cur_pic_ptr->hwaccel_picture_private;
+        s->cur_pic.ptr->hwaccel_picture_private;
     const int is_field = s->picture_structure != PICT_FRAME;
     const unsigned mb_count = s->mb_width * (s->mb_height >> is_field);
     void     *dxva_data_ptr;
@@ -260,7 +260,7 @@  static int dxva2_mpeg2_start_frame(AVCodecContext *avctx,
     const struct MpegEncContext *s = avctx->priv_data;
     AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
     struct dxva2_picture_context *ctx_pic =
-        s->cur_pic_ptr->hwaccel_picture_private;
+        s->cur_pic.ptr->hwaccel_picture_private;
 
     if (!DXVA_CONTEXT_VALID(avctx, ctx))
         return -1;
@@ -280,7 +280,7 @@  static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx,
 {
     const struct MpegEncContext *s = avctx->priv_data;
     struct dxva2_picture_context *ctx_pic =
-        s->cur_pic_ptr->hwaccel_picture_private;
+        s->cur_pic.ptr->hwaccel_picture_private;
     unsigned position;
 
     if (ctx_pic->slice_count >= MAX_SLICES) {
@@ -302,12 +302,12 @@  static int dxva2_mpeg2_end_frame(AVCodecContext *avctx)
 {
     struct MpegEncContext *s = avctx->priv_data;
     struct dxva2_picture_context *ctx_pic =
-        s->cur_pic_ptr->hwaccel_picture_private;
+        s->cur_pic.ptr->hwaccel_picture_private;
     int ret;
 
     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
         return -1;
-    ret = ff_dxva2_common_end_frame(avctx, s->cur_pic_ptr->f,
+    ret = ff_dxva2_common_end_frame(avctx, s->cur_pic.ptr->f,
                                     &ctx_pic->pp, sizeof(ctx_pic->pp),
                                     &ctx_pic->qm, sizeof(ctx_pic->qm),
                                     commit_bitstream_and_slice_buffer);
diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c
index f536da1008..6dc9cd8b5a 100644
--- a/libavcodec/dxva2_vc1.c
+++ b/libavcodec/dxva2_vc1.c
@@ -46,7 +46,7 @@  void ff_dxva2_vc1_fill_picture_parameters(AVCodecContext *avctx,
 {
     const VC1Context *v = avctx->priv_data;
     const MpegEncContext *s = &v->s;
-    const MPVPicture *current_picture = s->cur_pic_ptr;
+    const MPVPicture *current_picture = s->cur_pic.ptr;
     int intcomp = 0;
 
     // determine if intensity compensation is needed
@@ -58,12 +58,12 @@  void ff_dxva2_vc1_fill_picture_parameters(AVCodecContext *avctx,
     }
 
     memset(pp, 0, sizeof(*pp));
-    if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type)
-        pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_pic.f, 0);
+    if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type && s->last_pic.ptr)
+        pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_pic.ptr->f, 0);
     else
         pp->wForwardRefPictureIndex = 0xffff;
-    if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type)
-        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_pic.f, 0);
+    if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type && s->next_pic.ptr)
+        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_pic.ptr->f, 0);
     else
         pp->wBackwardRefPictureIndex = 0xffff;
     pp->wDecodedPictureIndex    =
@@ -191,7 +191,7 @@  static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     const VC1Context *v = avctx->priv_data;
     AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
     const MpegEncContext *s = &v->s;
-    struct dxva2_picture_context *ctx_pic = s->cur_pic_ptr->hwaccel_picture_private;
+    struct dxva2_picture_context *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
 
     static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
     const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ? sizeof(start_code) : 0;
@@ -317,7 +317,7 @@  static int dxva2_vc1_start_frame(AVCodecContext *avctx,
 {
     const VC1Context *v = avctx->priv_data;
     AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
-    struct dxva2_picture_context *ctx_pic = v->s.cur_pic_ptr->hwaccel_picture_private;
+    struct dxva2_picture_context *ctx_pic = v->s.cur_pic.ptr->hwaccel_picture_private;
 
     if (!DXVA_CONTEXT_VALID(avctx, ctx))
         return -1;
@@ -336,7 +336,7 @@  static int dxva2_vc1_decode_slice(AVCodecContext *avctx,
                                   uint32_t size)
 {
     const VC1Context *v = avctx->priv_data;
-    const MPVPicture *current_picture = v->s.cur_pic_ptr;
+    const MPVPicture *current_picture = v->s.cur_pic.ptr;
     struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
     unsigned position;
 
@@ -364,13 +364,13 @@  static int dxva2_vc1_decode_slice(AVCodecContext *avctx,
 static int dxva2_vc1_end_frame(AVCodecContext *avctx)
 {
     VC1Context *v = avctx->priv_data;
-    struct dxva2_picture_context *ctx_pic = v->s.cur_pic_ptr->hwaccel_picture_private;
+    struct dxva2_picture_context *ctx_pic = v->s.cur_pic.ptr->hwaccel_picture_private;
     int ret;
 
     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
         return -1;
 
-    ret = ff_dxva2_common_end_frame(avctx, v->s.cur_pic_ptr->f,
+    ret = ff_dxva2_common_end_frame(avctx, v->s.cur_pic.ptr->f,
                                     &ctx_pic->pp, sizeof(ctx_pic->pp),
                                     NULL, 0,
                                     commit_bitstream_and_slice_buffer);
diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
index 00edd7a7c2..9acfd984ee 100644
--- a/libavcodec/h261dec.c
+++ b/libavcodec/h261dec.c
@@ -649,12 +649,11 @@  static int h261_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     }
     ff_mpv_frame_end(s);
 
-    av_assert0(s->cur_pic.f->pict_type == s->cur_pic_ptr->f->pict_type);
-    av_assert0(s->cur_pic.f->pict_type == s->pict_type);
+    av_assert0(s->pict_type == s->cur_pic.ptr->f->pict_type);
 
-    if ((ret = av_frame_ref(pict, s->cur_pic_ptr->f)) < 0)
+    if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
         return ret;
-    ff_print_debug_info(s, s->cur_pic_ptr, pict);
+    ff_print_debug_info(s, s->cur_pic.ptr, pict);
 
     *got_frame = 1;
 
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 6ae634fceb..4fe4a30000 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -432,22 +432,22 @@  int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     /* no supplementary picture */
     if (buf_size == 0) {
         /* special case for last picture */
-        if (s->low_delay == 0 && s->next_pic_ptr) {
-            if ((ret = av_frame_ref(pict, s->next_pic_ptr->f)) < 0)
+        if (s->low_delay == 0 && s->next_pic.ptr) {
+            if ((ret = av_frame_ref(pict, s->next_pic.ptr->f)) < 0)
                 return ret;
-            s->next_pic_ptr = NULL;
+            s->next_pic.ptr = NULL;
 
             *got_frame = 1;
-        } else if (s->skipped_last_frame && s->cur_pic_ptr) {
+        } else if (s->skipped_last_frame && s->cur_pic.ptr) {
             /* Output the last picture we decoded again if the stream ended with
              * an NVOP */
-            if ((ret = av_frame_ref(pict, s->cur_pic_ptr->f)) < 0)
+            if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
                 return ret;
             /* Copy props from the last input packet. Otherwise, props from the last
              * returned picture would be reused */
             if ((ret = ff_decode_frame_props(avctx, pict)) < 0)
                 return ret;
-            s->cur_pic_ptr = NULL;
+            s->cur_pic.ptr = NULL;
 
             *got_frame = 1;
         }
@@ -561,7 +561,7 @@  retry:
         s->gob_index = H263_GOB_HEIGHT(s->height);
 
     /* skip B-frames if we don't have reference frames */
-    if (!s->last_pic_ptr &&
+    if (!s->last_pic.ptr &&
         (s->pict_type == AV_PICTURE_TYPE_B || s->droppable))
         return get_consumed_bytes(s, buf_size);
     if ((avctx->skip_frame >= AVDISCARD_NONREF &&
@@ -647,21 +647,20 @@  frame_end:
     if (!s->divx_packed && avctx->hwaccel)
         ff_thread_finish_setup(avctx);
 
-    av_assert1(s->cur_pic.f->pict_type == s->cur_pic_ptr->f->pict_type);
-    av_assert1(s->cur_pic.f->pict_type == s->pict_type);
+    av_assert1(s->pict_type == s->cur_pic.ptr->f->pict_type);
     if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
-        if ((ret = av_frame_ref(pict, s->cur_pic_ptr->f)) < 0)
+        if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
             return ret;
-        ff_print_debug_info(s, s->cur_pic_ptr, pict);
-        ff_mpv_export_qp_table(s, pict, s->cur_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG1);
-    } else if (s->last_pic_ptr) {
-        if ((ret = av_frame_ref(pict, s->last_pic_ptr->f)) < 0)
+        ff_print_debug_info(s, s->cur_pic.ptr, pict);
+        ff_mpv_export_qp_table(s, pict, s->cur_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG1);
+    } else if (s->last_pic.ptr) {
+        if ((ret = av_frame_ref(pict, s->last_pic.ptr->f)) < 0)
             return ret;
-        ff_print_debug_info(s, s->last_pic_ptr, pict);
-        ff_mpv_export_qp_table(s, pict, s->last_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG1);
+        ff_print_debug_info(s, s->last_pic.ptr, pict);
+        ff_mpv_export_qp_table(s, pict, s->last_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG1);
     }
 
-    if (s->last_pic_ptr || s->low_delay) {
+    if (s->last_pic.ptr || s->low_delay) {
         if (   pict->format == AV_PIX_FMT_YUV420P
             && (s->codec_tag == AV_RL32("GEOV") || s->codec_tag == AV_RL32("GEOX"))) {
             for (int p = 0; p < 3; p++) {
diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c
index 2e4d74adc8..0809048362 100644
--- a/libavcodec/ituh263dec.c
+++ b/libavcodec/ituh263dec.c
@@ -750,12 +750,12 @@  static inline void set_one_direct_mv(MpegEncContext *s, const MPVPicture *p, int
 static int set_direct_mv(MpegEncContext *s)
 {
     const int mb_index = s->mb_x + s->mb_y * s->mb_stride;
-    const MPVPicture *p = &s->next_pic;
+    const MPVPicture *p = s->next_pic.ptr;
     int colocated_mb_type = p->mb_type[mb_index];
     int i;
 
     if (s->codec_tag == AV_RL32("U263") && p->f->pict_type == AV_PICTURE_TYPE_I) {
-        p = &s->last_pic;
+        p = s->last_pic.ptr;
         colocated_mb_type = p->mb_type[mb_index];
     }
 
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 6877b9ef4a..e3f2dd8af7 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1292,7 +1292,7 @@  static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size)
             return ret;
 
         if (s->picture_structure != PICT_FRAME) {
-            s->cur_pic_ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST *
+            s->cur_pic.ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST *
                                         (s->picture_structure == PICT_TOP_FIELD);
 
             for (int i = 0; i < 3; i++) {
@@ -1309,19 +1309,19 @@  static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size)
         ff_mpeg_er_frame_start(s);
 
         /* first check if we must repeat the frame */
-        s->cur_pic_ptr->f->repeat_pict = 0;
+        s->cur_pic.ptr->f->repeat_pict = 0;
         if (s->repeat_first_field) {
             if (s->progressive_sequence) {
                 if (s->top_field_first)
-                    s->cur_pic_ptr->f->repeat_pict = 4;
+                    s->cur_pic.ptr->f->repeat_pict = 4;
                 else
-                    s->cur_pic_ptr->f->repeat_pict = 2;
+                    s->cur_pic.ptr->f->repeat_pict = 2;
             } else if (s->progressive_frame) {
-                s->cur_pic_ptr->f->repeat_pict = 1;
+                s->cur_pic.ptr->f->repeat_pict = 1;
             }
         }
 
-        ret = ff_frame_new_side_data(s->avctx, s->cur_pic_ptr->f,
+        ret = ff_frame_new_side_data(s->avctx, s->cur_pic.ptr->f,
                                      AV_FRAME_DATA_PANSCAN, sizeof(s1->pan_scan),
                                      &pan_scan);
         if (ret < 0)
@@ -1331,14 +1331,14 @@  static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size)
 
         if (s1->a53_buf_ref) {
             ret = ff_frame_new_side_data_from_buf(
-                s->avctx, s->cur_pic_ptr->f, AV_FRAME_DATA_A53_CC,
+                s->avctx, s->cur_pic.ptr->f, AV_FRAME_DATA_A53_CC,
                 &s1->a53_buf_ref, NULL);
             if (ret < 0)
                 return ret;
         }
 
         if (s1->has_stereo3d) {
-            AVStereo3D *stereo = av_stereo3d_create_side_data(s->cur_pic_ptr->f);
+            AVStereo3D *stereo = av_stereo3d_create_side_data(s->cur_pic.ptr->f);
             if (!stereo)
                 return AVERROR(ENOMEM);
 
@@ -1348,7 +1348,7 @@  static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size)
 
         if (s1->has_afd) {
             AVFrameSideData *sd;
-            ret = ff_frame_new_side_data(s->avctx, s->cur_pic_ptr->f,
+            ret = ff_frame_new_side_data(s->avctx, s->cur_pic.ptr->f,
                                          AV_FRAME_DATA_AFD, 1, &sd);
             if (ret < 0)
                 return ret;
@@ -1360,7 +1360,7 @@  static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size)
         if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME))
             ff_thread_finish_setup(avctx);
     } else { // second field
-        if (!s->cur_pic_ptr) {
+        if (!s->cur_pic.ptr) {
             av_log(s->avctx, AV_LOG_ERROR, "first field missing\n");
             return AVERROR_INVALIDDATA;
         }
@@ -1377,10 +1377,10 @@  static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size)
             return ret;
 
         for (int i = 0; i < 3; i++) {
-            s->cur_pic.data[i] = s->cur_pic_ptr->f->data[i];
+            s->cur_pic.data[i] = s->cur_pic.ptr->f->data[i];
             if (s->picture_structure == PICT_BOTTOM_FIELD)
                 s->cur_pic.data[i] +=
-                    s->cur_pic_ptr->f->linesize[i];
+                    s->cur_pic.ptr->f->linesize[i];
         }
     }
 
@@ -1735,7 +1735,7 @@  static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
     Mpeg1Context *s1  = avctx->priv_data;
     MpegEncContext *s = &s1->mpeg_enc_ctx;
 
-    if (!s->context_initialized || !s->cur_pic_ptr)
+    if (!s->context_initialized || !s->cur_pic.ptr)
         return 0;
 
     if (s->avctx->hwaccel) {
@@ -1756,20 +1756,20 @@  static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
         ff_mpv_frame_end(s);
 
         if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
-            int ret = av_frame_ref(pict, s->cur_pic_ptr->f);
+            int ret = av_frame_ref(pict, s->cur_pic.ptr->f);
             if (ret < 0)
                 return ret;
-            ff_print_debug_info(s, s->cur_pic_ptr, pict);
-            ff_mpv_export_qp_table(s, pict, s->cur_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG2);
+            ff_print_debug_info(s, s->cur_pic.ptr, pict);
+            ff_mpv_export_qp_table(s, pict, s->cur_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG2);
             *got_output = 1;
         } else {
             /* latency of 1 frame for I- and P-frames */
-            if (s->last_pic_ptr && !s->last_pic_ptr->dummy) {
-                int ret = av_frame_ref(pict, s->last_pic_ptr->f);
+            if (s->last_pic.ptr && !s->last_pic.ptr->dummy) {
+                int ret = av_frame_ref(pict, s->last_pic.ptr->f);
                 if (ret < 0)
                     return ret;
-                ff_print_debug_info(s, s->last_pic_ptr, pict);
-                ff_mpv_export_qp_table(s, pict, s->last_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG2);
+                ff_print_debug_info(s, s->last_pic.ptr, pict);
+                ff_mpv_export_qp_table(s, pict, s->last_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG2);
                 *got_output = 1;
             }
         }
@@ -2405,7 +2405,7 @@  static int decode_chunks(AVCodecContext *avctx, AVFrame *picture,
                     return AVERROR_INVALIDDATA;
                 }
 
-                if (!s2->last_pic_ptr) {
+                if (!s2->last_pic.ptr) {
                     /* Skip B-frames if we do not have reference frames and
                      * GOP is not closed. */
                     if (s2->pict_type == AV_PICTURE_TYPE_B) {
@@ -2419,7 +2419,7 @@  static int decode_chunks(AVCodecContext *avctx, AVFrame *picture,
                 }
                 if (s2->pict_type == AV_PICTURE_TYPE_I || (s2->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
                     s->sync = 1;
-                if (!s2->next_pic_ptr) {
+                if (!s2->next_pic.ptr) {
                     /* Skip P-frames if we do not have a reference frame or
                      * we have an invalid header. */
                     if (s2->pict_type == AV_PICTURE_TYPE_P && !s->sync) {
@@ -2460,7 +2460,7 @@  static int decode_chunks(AVCodecContext *avctx, AVFrame *picture,
                     if ((ret = mpeg_field_start(s2, buf, buf_size)) < 0)
                         return ret;
                 }
-                if (!s2->cur_pic_ptr) {
+                if (!s2->cur_pic.ptr) {
                     av_log(avctx, AV_LOG_ERROR,
                            "current_picture not initialized\n");
                     return AVERROR_INVALIDDATA;
@@ -2524,12 +2524,12 @@  static int mpeg_decode_frame(AVCodecContext *avctx, AVFrame *picture,
 
     if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == SEQ_END_CODE)) {
         /* special case for last picture */
-        if (s2->low_delay == 0 && s2->next_pic_ptr) {
-            int ret = av_frame_ref(picture, s2->next_pic_ptr->f);
+        if (s2->low_delay == 0 && s2->next_pic.ptr) {
+            int ret = av_frame_ref(picture, s2->next_pic.ptr->f);
             if (ret < 0)
                 return ret;
 
-            s2->next_pic_ptr = NULL;
+            s2->next_pic.ptr = NULL;
 
             *got_output = 1;
         }
@@ -2552,14 +2552,14 @@  static int mpeg_decode_frame(AVCodecContext *avctx, AVFrame *picture,
         }
         s->extradata_decoded = 1;
         if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) {
-            s2->cur_pic_ptr = NULL;
+            s2->cur_pic.ptr = NULL;
             return ret;
         }
     }
 
     ret = decode_chunks(avctx, picture, got_output, buf, buf_size);
     if (ret<0 || *got_output) {
-        s2->cur_pic_ptr = NULL;
+        s2->cur_pic.ptr = NULL;
 
         if (s->timecode_frame_start != -1 && *got_output) {
             char tcbuf[AV_TIMECODE_STR_SIZE];
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index 326c0079df..ea193e007a 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -290,7 +290,7 @@  static void mpeg1_encode_sequence_header(MpegEncContext *s)
     AVRational aspect_ratio = s->avctx->sample_aspect_ratio;
     int aspect_ratio_info;
 
-    if (!(s->cur_pic.f->flags & AV_FRAME_FLAG_KEY))
+    if (!(s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_KEY))
         return;
 
     if (aspect_ratio.num == 0 || aspect_ratio.den == 0)
@@ -382,7 +382,7 @@  static void mpeg1_encode_sequence_header(MpegEncContext *s)
         put_bits(&s->pb, 2, mpeg12->frame_rate_ext.num-1); // frame_rate_ext_n
         put_bits(&s->pb, 5, mpeg12->frame_rate_ext.den-1); // frame_rate_ext_d
 
-        side_data = av_frame_get_side_data(s->cur_pic_ptr->f, AV_FRAME_DATA_PANSCAN);
+        side_data = av_frame_get_side_data(s->cur_pic.ptr->f, AV_FRAME_DATA_PANSCAN);
         if (side_data) {
             const AVPanScan *pan_scan = (AVPanScan *)side_data->data;
             if (pan_scan->width && pan_scan->height) {
@@ -419,10 +419,10 @@  static void mpeg1_encode_sequence_header(MpegEncContext *s)
     /* time code: we must convert from the real frame rate to a
      * fake MPEG frame rate in case of low frame rate */
     fps       = (framerate.num + framerate.den / 2) / framerate.den;
-    time_code = s->cur_pic_ptr->coded_picture_number +
+    time_code = s->cur_pic.ptr->coded_picture_number +
                 mpeg12->timecode_frame_start;
 
-    mpeg12->gop_picture_number = s->cur_pic_ptr->coded_picture_number;
+    mpeg12->gop_picture_number = s->cur_pic.ptr->coded_picture_number;
 
     av_assert0(mpeg12->drop_frame_timecode == !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
     if (mpeg12->drop_frame_timecode)
@@ -530,7 +530,7 @@  void ff_mpeg1_encode_picture_header(MpegEncContext *s)
         if (s->progressive_sequence)
             put_bits(&s->pb, 1, 0);             /* no repeat */
         else
-            put_bits(&s->pb, 1, !!(s->cur_pic_ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST));
+            put_bits(&s->pb, 1, !!(s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST));
         /* XXX: optimize the generation of this flag with entropy measures */
         s->frame_pred_frame_dct = s->progressive_sequence;
 
@@ -554,7 +554,7 @@  void ff_mpeg1_encode_picture_header(MpegEncContext *s)
         for (i = 0; i < sizeof(svcd_scan_offset_placeholder); i++)
             put_bits(&s->pb, 8, svcd_scan_offset_placeholder[i]);
     }
-    side_data = av_frame_get_side_data(s->cur_pic_ptr->f,
+    side_data = av_frame_get_side_data(s->cur_pic.ptr->f,
                                        AV_FRAME_DATA_STEREO3D);
     if (side_data) {
         const AVStereo3D *stereo = (AVStereo3D *)side_data->data;
@@ -594,7 +594,7 @@  void ff_mpeg1_encode_picture_header(MpegEncContext *s)
     }
 
     if (CONFIG_MPEG2VIDEO_ENCODER && mpeg12->a53_cc) {
-        side_data = av_frame_get_side_data(s->cur_pic_ptr->f,
+        side_data = av_frame_get_side_data(s->cur_pic.ptr->f,
             AV_FRAME_DATA_A53_CC);
         if (side_data) {
             if (side_data->size <= A53_MAX_CC_COUNT * 3 && side_data->size % 3 == 0) {
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 1fda3053f0..b138c94df9 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -1807,7 +1807,7 @@  static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
                 s->last_mv[i][1][1] = 0;
             }
 
-            ff_thread_await_progress(&s->next_pic_ptr->tf, s->mb_y, 0);
+            ff_thread_await_progress(&s->next_pic.ptr->tf, s->mb_y, 0);
         }
 
         /* if we skipped it in the future P-frame than skip it now too */
@@ -2012,7 +2012,7 @@  end:
 
         if (s->pict_type == AV_PICTURE_TYPE_B) {
             const int delta = s->mb_x + 1 == s->mb_width ? 2 : 1;
-            ff_thread_await_progress(&s->next_pic_ptr->tf,
+            ff_thread_await_progress(&s->next_pic.ptr->tf,
                                         (s->mb_x + delta >= s->mb_width)
                                         ? FFMIN(s->mb_y + 1, s->mb_height - 1)
                                         : s->mb_y, 0);
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 6c743b8641..e853282b4b 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -891,7 +891,7 @@  static void mpeg4_encode_gop_header(MpegEncContext *s)
     put_bits(&s->pb, 16, 0);
     put_bits(&s->pb, 16, GOP_STARTCODE);
 
-    time = s->cur_pic_ptr->f->pts;
+    time = s->cur_pic.ptr->f->pts;
     if (s->reordered_input_picture[1])
         time = FFMIN(time, s->reordered_input_picture[1]->f->pts);
     time = time * s->avctx->time_base.num;
@@ -1103,7 +1103,7 @@  int ff_mpeg4_encode_picture_header(MpegEncContext *s)
     }
     put_bits(&s->pb, 3, 0);     /* intra dc VLC threshold */
     if (!s->progressive_sequence) {
-        put_bits(&s->pb, 1, !!(s->cur_pic_ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST));
+        put_bits(&s->pb, 1, !!(s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST));
         put_bits(&s->pb, 1, s->alternate_scan);
     }
     // FIXME sprite stuff
diff --git a/libavcodec/mpeg_er.c b/libavcodec/mpeg_er.c
index 21fe7d6f71..f9421ec91f 100644
--- a/libavcodec/mpeg_er.c
+++ b/libavcodec/mpeg_er.c
@@ -49,9 +49,9 @@  void ff_mpeg_er_frame_start(MpegEncContext *s)
 {
     ERContext *er = &s->er;
 
-    set_erpic(&er->cur_pic,  s->cur_pic_ptr);
-    set_erpic(&er->next_pic, s->next_pic_ptr);
-    set_erpic(&er->last_pic, s->last_pic_ptr);
+    set_erpic(&er->cur_pic,  s->cur_pic.ptr);
+    set_erpic(&er->next_pic, s->next_pic.ptr);
+    set_erpic(&er->last_pic, s->last_pic.ptr);
 
     er->pp_time           = s->pp_time;
     er->pb_time           = s->pb_time;
diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c
index 644097f2cb..84d9209c4c 100644
--- a/libavcodec/mpegpicture.c
+++ b/libavcodec/mpegpicture.c
@@ -45,6 +45,45 @@  static void av_noinline free_picture_tables(MPVPicture *pic)
     pic->mb_height = 0;
 }
 
+void ff_mpv_unref_picture(MPVWorkPicture *pic)
+{
+    if (pic->ptr)
+        ff_mpeg_unref_picture(pic->ptr);
+    memset(pic, 0, sizeof(*pic));
+}
+
+static void set_workpic_from_pic(MPVWorkPicture *wpic, const MPVPicture *pic)
+{
+    for (int i = 0; i < MPV_MAX_PLANES; i++) {
+        wpic->data[i]     = pic->f->data[i];
+        wpic->linesize[i] = pic->f->linesize[i];
+    }
+    wpic->qscale_table = pic->qscale_table;
+    wpic->mb_type      = pic->mb_type;
+    wpic->mbskip_table = pic->mbskip_table;
+
+    for (int i = 0; i < 2; i++) {
+        wpic->motion_val[i] = pic->motion_val[i];
+        wpic->ref_index[i]  = pic->ref_index[i];
+    }
+    wpic->reference  = pic->reference;
+}
+
+void ff_mpv_replace_picture(MPVWorkPicture *dst, const MPVWorkPicture *src)
+{
+    memcpy(dst, src, sizeof(*dst));
+}
+
+void ff_mpv_workpic_from_pic(MPVWorkPicture *wpic, MPVPicture *pic)
+{
+    if (!pic) {
+        memset(wpic, 0, sizeof(*wpic));
+        return;
+    }
+    wpic->ptr = pic;
+    set_workpic_from_pic(wpic, pic);
+}
+
 int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me,
                             ScratchpadContext *sc, int linesize)
 {
@@ -142,17 +181,13 @@  static int alloc_picture_tables(BufferPoolContext *pools, MPVPicture *pic,
     return 0;
 }
 
-int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVPicture *pic,
+int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVWorkPicture *wpic,
                                  MotionEstContext *me, ScratchpadContext *sc,
                                  BufferPoolContext *pools, int mb_height)
 {
+    MPVPicture *pic = wpic->ptr;
     int ret;
 
-    for (int i = 0; i < MPV_MAX_PLANES; i++) {
-        pic->data[i]     = pic->f->data[i];
-        pic->linesize[i] = pic->f->linesize[i];
-    }
-
     ret = ff_mpeg_framesize_alloc(avctx, me, sc,
                                   pic->f->linesize[0]);
     if (ret < 0)
@@ -169,6 +204,7 @@  int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVPicture *pic,
         for (int i = 0; i < 2; i++)
             pic->motion_val[i] = pic->motion_val_base[i] + 4;
     }
+    set_workpic_from_pic(wpic, pic);
 
     return 0;
 fail:
@@ -189,12 +225,10 @@  void ff_mpeg_unref_picture(MPVPicture *pic)
 
     free_picture_tables(pic);
 
-    memset(pic->data,     0, sizeof(pic->data));
-    memset(pic->linesize, 0, sizeof(pic->linesize));
-
     pic->dummy         = 0;
 
     pic->field_picture = 0;
+    pic->interlaced    = 0;
     pic->b_frame_score = 0;
     pic->reference     = 0;
     pic->shared        = 0;
@@ -235,11 +269,6 @@  int ff_mpeg_ref_picture(MPVPicture *dst, MPVPicture *src)
     if (ret < 0)
         goto fail;
 
-    for (int i = 0; i < MPV_MAX_PLANES; i++) {
-        dst->data[i]     = src->data[i];
-        dst->linesize[i] = src->linesize[i];
-    }
-
     update_picture_tables(dst, src);
 
     ff_refstruct_replace(&dst->hwaccel_picture_private,
@@ -252,6 +281,7 @@  int ff_mpeg_ref_picture(MPVPicture *dst, MPVPicture *src)
     dst->shared                  = src->shared;
     dst->display_picture_number  = src->display_picture_number;
     dst->coded_picture_number    = src->coded_picture_number;
+    dst->interlaced              = src->interlaced;
 
     return 0;
 fail:
diff --git a/libavcodec/mpegpicture.h b/libavcodec/mpegpicture.h
index f0837b158a..774c5c8841 100644
--- a/libavcodec/mpegpicture.h
+++ b/libavcodec/mpegpicture.h
@@ -58,9 +58,6 @@  typedef struct MPVPicture {
     struct AVFrame *f;
     ThreadFrame tf;
 
-    uint8_t  *data[MPV_MAX_PLANES];
-    ptrdiff_t linesize[MPV_MAX_PLANES];
-
     int8_t *qscale_table_base;
     int8_t *qscale_table;
 
@@ -83,6 +80,7 @@  typedef struct MPVPicture {
 
     int dummy;                  ///< Picture is a dummy and should not be output
     int field_picture;          ///< whether or not the picture was encoded in separate fields
+    int interlaced;
 
     int b_frame_score;
 
@@ -93,10 +91,30 @@  typedef struct MPVPicture {
     int coded_picture_number;
 } MPVPicture;
 
+typedef struct MPVWorkPicture {
+    uint8_t  *data[MPV_MAX_PLANES];
+    ptrdiff_t linesize[MPV_MAX_PLANES];
+
+    MPVPicture *ptr;
+
+    int8_t *qscale_table;
+
+    int16_t (*motion_val[2])[2];
+
+    uint32_t *mb_type;          ///< types and macros are defined in mpegutils.h
+
+    uint8_t *mbskip_table;
+
+    int8_t *ref_index[2];
+
+    int reference;
+} MPVWorkPicture;
+
 /**
- * Allocate an MPVPicture's accessories, but not the AVFrame's buffer itself.
+ * Allocate an MPVPicture's accessories (but not the AVFrame's buffer itself)
+ * and set the MPVWorkPicture's fields.
  */
-int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVPicture *pic,
+int ff_mpv_alloc_pic_accessories(AVCodecContext *avctx, MPVWorkPicture *pic,
                                  MotionEstContext *me, ScratchpadContext *sc,
                                  BufferPoolContext *pools, int mb_height);
 
@@ -113,6 +131,9 @@  int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me,
                             ScratchpadContext *sc, int linesize);
 
 int ff_mpeg_ref_picture(MPVPicture *dst, MPVPicture *src);
+void ff_mpv_unref_picture(MPVWorkPicture *pic);
+void ff_mpv_workpic_from_pic(MPVWorkPicture *wpic, MPVPicture *pic);
+void ff_mpv_replace_picture(MPVWorkPicture *dst, const MPVWorkPicture *src);
 void ff_mpeg_unref_picture(MPVPicture *picture);
 
 void ff_mpv_picture_free(MPVPicture *pic);
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 34f412a6b7..a4bea7273a 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -760,11 +760,6 @@  av_cold int ff_mpv_common_init(MpegEncContext *s)
             goto fail_nomem;
     }
 
-    if (!(s->next_pic.f = av_frame_alloc()) ||
-        !(s->last_pic.f = av_frame_alloc()) ||
-        !(s->cur_pic.f  = av_frame_alloc()))
-        goto fail_nomem;
-
     if ((ret = ff_mpv_init_context_frame(s)))
         goto fail;
 
@@ -837,15 +832,9 @@  void ff_mpv_common_end(MpegEncContext *s)
             ff_mpv_picture_free(&s->picture[i]);
     }
     av_freep(&s->picture);
-    ff_mpv_picture_free(&s->last_pic);
-    ff_mpv_picture_free(&s->cur_pic);
-    ff_mpv_picture_free(&s->next_pic);
 
     s->context_initialized      = 0;
     s->context_reinit           = 0;
-    s->last_pic_ptr =
-    s->next_pic_ptr =
-    s->cur_pic_ptr  = NULL;
     s->linesize = s->uvlinesize = 0;
 }
 
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index b476b54295..75120f2082 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -156,13 +156,13 @@  typedef struct MpegEncContext {
      * copy of the previous picture structure.
      * note, linesize & data, might not match the previous picture (for field pictures)
      */
-    MPVPicture last_pic;
+    MPVWorkPicture last_pic;
 
     /**
      * copy of the next picture structure.
      * note, linesize & data, might not match the next picture (for field pictures)
      */
-    MPVPicture next_pic;
+    MPVWorkPicture next_pic;
 
     /**
      * Reference to the source picture for encoding.
@@ -174,11 +174,8 @@  typedef struct MpegEncContext {
      * copy of the current picture structure.
      * note, linesize & data, might not match the current picture (for field pictures)
      */
-    MPVPicture cur_pic;
+    MPVWorkPicture cur_pic;
 
-    MPVPicture *last_pic_ptr;      ///< pointer to the previous picture.
-    MPVPicture *next_pic_ptr;      ///< pointer to the next picture (for bidir pred)
-    MPVPicture *cur_pic_ptr;       ///< pointer to the current picture
     int skipped_last_frame;
     int last_dc[3];                ///< last DC values for MPEG-1
     int16_t *dc_val_base;
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 97efd4fe81..71a6c0ad67 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -114,12 +114,10 @@  int ff_mpeg_update_thread_context(AVCodecContext *dst,
 
 #define UPDATE_PICTURE(pic)\
 do {\
-    ff_mpeg_unref_picture(&s->pic);\
-    if (s1->pic.f && s1->pic.f->buf[0]) {\
-        ret = ff_mpeg_ref_picture(&s->pic, &s1->pic);\
-        if (ret < 0)\
-            return ret;\
-    }\
+    if (s->picture && s1->picture && s1->pic.ptr && s1->pic.ptr->f->buf[0]) {\
+        ff_mpv_workpic_from_pic(&s->pic, &s->picture[s1->pic.ptr - s1->picture]);\
+    } else\
+        ff_mpv_unref_picture(&s->pic);\
 } while (0)
 
     UPDATE_PICTURE(cur_pic);
@@ -129,15 +127,6 @@  do {\
     s->linesize   = s1->linesize;
     s->uvlinesize = s1->uvlinesize;
 
-#define REBASE_PICTURE(pic, new_ctx, old_ctx)                                 \
-    ((pic && pic >= old_ctx->picture &&                                       \
-      pic < old_ctx->picture + MAX_PICTURE_COUNT) ?                           \
-        &new_ctx->picture[pic - old_ctx->picture] : NULL)
-
-    s->last_pic_ptr = REBASE_PICTURE(s1->last_pic_ptr, s, s1);
-    s->cur_pic_ptr  = REBASE_PICTURE(s1->cur_pic_ptr,  s, s1);
-    s->next_pic_ptr = REBASE_PICTURE(s1->next_pic_ptr, s, s1);
-
     // Error/bug resilience
     s->workaround_bugs      = s1->workaround_bugs;
     s->padding_bug_score    = s1->padding_bug_score;
@@ -193,9 +182,9 @@  int ff_mpv_common_frame_size_change(MpegEncContext *s)
 
     ff_mpv_free_context_frame(s);
 
-    s->last_pic_ptr =
-    s->next_pic_ptr =
-    s->cur_pic_ptr  = NULL;
+    s->last_pic.ptr =
+    s->next_pic.ptr =
+    s->cur_pic.ptr  = NULL;
 
     if ((s->width || s->height) &&
         (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0)
@@ -228,7 +217,7 @@  int ff_mpv_common_frame_size_change(MpegEncContext *s)
     return err;
 }
 
-static int alloc_picture(MpegEncContext *s, MPVPicture **picp, int reference)
+static int alloc_picture(MpegEncContext *s, MPVWorkPicture *dst, int reference)
 {
     AVCodecContext *avctx = s->avctx;
     int idx = ff_find_unused_picture(s->avctx, s->picture, 0);
@@ -239,6 +228,7 @@  static int alloc_picture(MpegEncContext *s, MPVPicture **picp, int reference)
         return idx;
 
     pic = &s->picture[idx];
+    dst->ptr = pic;
 
     pic->tf.f = pic->f;
     pic->reference = reference;
@@ -271,36 +261,27 @@  static int alloc_picture(MpegEncContext *s, MPVPicture **picp, int reference)
     av_assert1(s->mb_height == s->buffer_pools.alloc_mb_height ||
                FFALIGN(s->mb_height, 2) == s->buffer_pools.alloc_mb_height);
     av_assert1(s->mb_stride == s->buffer_pools.alloc_mb_stride);
-    ret = ff_mpv_alloc_pic_accessories(s->avctx, pic, &s->me, &s->sc,
+    ret = ff_mpv_alloc_pic_accessories(s->avctx, dst, &s->me, &s->sc,
                                        &s->buffer_pools, s->mb_height);
     if (ret < 0)
         goto fail;
-    *picp = pic;
 
     return 0;
 fail:
-    ff_mpeg_unref_picture(pic);
+    ff_mpv_unref_picture(dst);
     return ret;
 }
 
-static int av_cold alloc_dummy_frame(MpegEncContext *s, MPVPicture **picp, MPVPicture *wpic)
+static int av_cold alloc_dummy_frame(MpegEncContext *s, MPVWorkPicture *dst)
 {
     MPVPicture *pic;
-    int ret = alloc_picture(s, &pic, 1);
+    int ret = alloc_picture(s, dst, 1);
     if (ret < 0)
         return ret;
 
+    pic = dst->ptr;
     pic->dummy = 1;
 
-    ff_mpeg_unref_picture(wpic);
-    ret = ff_mpeg_ref_picture(wpic, pic);
-    if (ret < 0) {
-        ff_mpeg_unref_picture(pic);
-        return ret;
-    }
-
-    *picp = pic;
-
     ff_thread_report_progress(&pic->tf, INT_MAX, 0);
     ff_thread_report_progress(&pic->tf, INT_MAX, 1);
 
@@ -330,9 +311,9 @@  int ff_mpv_alloc_dummy_frames(MpegEncContext *s)
     AVCodecContext *avctx = s->avctx;
     int ret;
 
-    if ((!s->last_pic_ptr || !s->last_pic_ptr->f->buf[0]) &&
+    if ((!s->last_pic.ptr || !s->last_pic.ptr->f->buf[0]) &&
         (s->pict_type != AV_PICTURE_TYPE_I)) {
-        if (s->pict_type == AV_PICTURE_TYPE_B && s->next_pic_ptr && s->next_pic_ptr->f->buf[0])
+        if (s->pict_type == AV_PICTURE_TYPE_B && s->next_pic.ptr && s->next_pic.ptr->f->buf[0])
             av_log(avctx, AV_LOG_DEBUG,
                    "allocating dummy last picture for B frame\n");
         else if (s->codec_id != AV_CODEC_ID_H261 /* H.261 has no keyframes */ &&
@@ -341,25 +322,25 @@  int ff_mpv_alloc_dummy_frames(MpegEncContext *s)
                    "warning: first frame is no keyframe\n");
 
         /* Allocate a dummy frame */
-        ret = alloc_dummy_frame(s, &s->last_pic_ptr, &s->last_pic);
+        ret = alloc_dummy_frame(s, &s->last_pic);
         if (ret < 0)
             return ret;
 
         if (!avctx->hwaccel) {
             int luma_val = s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263 ? 16 : 0x80;
-            color_frame(s->last_pic_ptr->f, luma_val);
+            color_frame(s->last_pic.ptr->f, luma_val);
         }
     }
-    if ((!s->next_pic_ptr || !s->next_pic_ptr->f->buf[0]) &&
+    if ((!s->next_pic.ptr || !s->next_pic.ptr->f->buf[0]) &&
         s->pict_type == AV_PICTURE_TYPE_B) {
         /* Allocate a dummy frame */
-        ret = alloc_dummy_frame(s, &s->next_pic_ptr, &s->next_pic);
+        ret = alloc_dummy_frame(s, &s->next_pic);
         if (ret < 0)
             return ret;
     }
 
-    av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_pic_ptr &&
-                                                 s->last_pic_ptr->f->buf[0]));
+    av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_pic.ptr &&
+                                                 s->last_pic.ptr->f->buf[0]));
 
     return 0;
 }
@@ -380,68 +361,49 @@  int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     /* mark & release old frames */
-    if (s->pict_type != AV_PICTURE_TYPE_B && s->last_pic_ptr &&
-        s->last_pic_ptr != s->next_pic_ptr &&
-        s->last_pic_ptr->f->buf[0]) {
-        ff_mpeg_unref_picture(s->last_pic_ptr);
+    if (s->pict_type != AV_PICTURE_TYPE_B && s->last_pic.ptr &&
+        s->last_pic.ptr != s->next_pic.ptr &&
+        s->last_pic.ptr->f->buf[0]) {
+        ff_mpeg_unref_picture(s->last_pic.ptr);
     }
 
     /* release non reference/forgotten frames */
     for (int i = 0; i < MAX_PICTURE_COUNT; i++) {
         if (!s->picture[i].reference ||
-            (&s->picture[i] != s->last_pic_ptr &&
-             &s->picture[i] != s->next_pic_ptr)) {
+            (&s->picture[i] != s->last_pic.ptr &&
+             &s->picture[i] != s->next_pic.ptr)) {
             ff_mpeg_unref_picture(&s->picture[i]);
         }
     }
 
-    ff_mpeg_unref_picture(&s->cur_pic);
-    ff_mpeg_unref_picture(&s->last_pic);
-    ff_mpeg_unref_picture(&s->next_pic);
-
-    ret = alloc_picture(s, &s->cur_pic_ptr,
+    ret = alloc_picture(s, &s->cur_pic,
                         s->pict_type != AV_PICTURE_TYPE_B && !s->droppable);
     if (ret < 0)
         return ret;
 
-    s->cur_pic_ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !!s->top_field_first;
-    s->cur_pic_ptr->f->flags |= AV_FRAME_FLAG_INTERLACED *
+    s->cur_pic.ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !!s->top_field_first;
+    s->cur_pic.ptr->f->flags |= AV_FRAME_FLAG_INTERLACED *
                                 (!s->progressive_frame && !s->progressive_sequence);
-    s->cur_pic_ptr->field_picture = s->picture_structure != PICT_FRAME;
+    s->cur_pic.ptr->field_picture = s->picture_structure != PICT_FRAME;
 
-    s->cur_pic_ptr->f->pict_type = s->pict_type;
+    s->cur_pic.ptr->f->pict_type = s->pict_type;
     if (s->pict_type == AV_PICTURE_TYPE_I)
-        s->cur_pic_ptr->f->flags |= AV_FRAME_FLAG_KEY;
+        s->cur_pic.ptr->f->flags |= AV_FRAME_FLAG_KEY;
     else
-        s->cur_pic_ptr->f->flags &= ~AV_FRAME_FLAG_KEY;
-
-    if ((ret = ff_mpeg_ref_picture(&s->cur_pic, s->cur_pic_ptr)) < 0)
-        return ret;
+        s->cur_pic.ptr->f->flags &= ~AV_FRAME_FLAG_KEY;
 
     if (s->pict_type != AV_PICTURE_TYPE_B) {
-        s->last_pic_ptr = s->next_pic_ptr;
+        ff_mpv_workpic_from_pic(&s->last_pic, s->next_pic.ptr);
         if (!s->droppable)
-            s->next_pic_ptr = s->cur_pic_ptr;
+            ff_mpv_workpic_from_pic(&s->next_pic, s->cur_pic.ptr);
     }
     ff_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n",
-            s->last_pic_ptr, s->next_pic_ptr, s->cur_pic_ptr,
-            s->last_pic_ptr ? s->last_pic_ptr->f->data[0] : NULL,
-            s->next_pic_ptr ? s->next_pic_ptr->f->data[0] : NULL,
-            s->cur_pic_ptr  ? s->cur_pic_ptr->f->data[0]  : NULL,
+            (void*)s->last_pic.ptr, (void*)s->next_pic.ptr, (void*)s->cur_pic.ptr,
+            s->last_pic.ptr ? s->last_pic.ptr->f->data[0] : NULL,
+            s->next_pic.ptr ? s->next_pic.ptr->f->data[0] : NULL,
+            s->cur_pic.ptr  ? s->cur_pic.ptr->f->data[0]  : NULL,
             s->pict_type, s->droppable);
 
-    if (s->last_pic_ptr) {
-        if (s->last_pic_ptr->f->buf[0] &&
-            (ret = ff_mpeg_ref_picture(&s->last_pic,
-                                       s->last_pic_ptr)) < 0)
-            return ret;
-    }
-    if (s->next_pic_ptr) {
-        if (s->next_pic_ptr->f->buf[0] &&
-            (ret = ff_mpeg_ref_picture(&s->next_pic, s->next_pic_ptr)) < 0)
-            return ret;
-    }
-
     ret = ff_mpv_alloc_dummy_frames(s);
     if (ret < 0)
         return ret;
@@ -461,7 +423,7 @@  int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     if (s->avctx->debug & FF_DEBUG_NOMC)
-        color_frame(s->cur_pic_ptr->f, 0x80);
+        color_frame(s->cur_pic.ptr->f, 0x80);
 
     return 0;
 }
@@ -472,7 +434,7 @@  void ff_mpv_frame_end(MpegEncContext *s)
     emms_c();
 
     if (s->cur_pic.reference)
-        ff_thread_report_progress(&s->cur_pic_ptr->tf, INT_MAX, 0);
+        ff_thread_report_progress(&s->cur_pic.ptr->tf, INT_MAX, 0);
 }
 
 void ff_print_debug_info(const MpegEncContext *s, const MPVPicture *p, AVFrame *pict)
@@ -515,8 +477,8 @@  int ff_mpv_export_qp_table(const MpegEncContext *s, AVFrame *f,
 
 void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h)
 {
-    ff_draw_horiz_band(s->avctx, s->cur_pic_ptr->f,
-                       s->last_pic_ptr ? s->last_pic_ptr->f : NULL,
+    ff_draw_horiz_band(s->avctx, s->cur_pic.ptr->f,
+                       s->last_pic.ptr ? s->last_pic.ptr->f : NULL,
                        y, h, s->picture_structure,
                        s->first_field, s->low_delay);
 }
@@ -530,11 +492,10 @@  void ff_mpeg_flush(AVCodecContext *avctx)
 
     for (int i = 0; i < MAX_PICTURE_COUNT; i++)
         ff_mpeg_unref_picture(&s->picture[i]);
-    s->cur_pic_ptr = s->last_pic_ptr = s->next_pic_ptr = NULL;
 
-    ff_mpeg_unref_picture(&s->cur_pic);
-    ff_mpeg_unref_picture(&s->last_pic);
-    ff_mpeg_unref_picture(&s->next_pic);
+    ff_mpv_unref_picture(&s->cur_pic);
+    ff_mpv_unref_picture(&s->last_pic);
+    ff_mpv_unref_picture(&s->next_pic);
 
     s->mb_x = s->mb_y = 0;
 
@@ -545,7 +506,7 @@  void ff_mpeg_flush(AVCodecContext *avctx)
 void ff_mpv_report_decode_progress(MpegEncContext *s)
 {
     if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred)
-        ff_thread_report_progress(&s->cur_pic_ptr->tf, s->mb_y, 0);
+        ff_thread_report_progress(&s->cur_pic.ptr->tf, s->mb_y, 0);
 }
 
 
@@ -864,7 +825,7 @@  static inline void MPV_motion_lowres(MpegEncContext *s,
         } else {
             if (s->picture_structure != s->field_select[dir][0] + 1 &&
                 s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
-                ref_picture = s->cur_pic_ptr->f->data;
+                ref_picture = s->cur_pic.ptr->f->data;
             }
             mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
                                0, 0, s->field_select[dir][0],
@@ -881,7 +842,7 @@  static inline void MPV_motion_lowres(MpegEncContext *s,
                 s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
                 ref2picture = ref_picture;
             } else {
-                ref2picture = s->cur_pic_ptr->f->data;
+                ref2picture = s->cur_pic.ptr->f->data;
             }
 
             mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
@@ -922,7 +883,7 @@  static inline void MPV_motion_lowres(MpegEncContext *s,
                 // opposite parity is always in the same
                 // frame if this is second field
                 if (!s->first_field) {
-                    ref_picture = s->cur_pic_ptr->f->data;
+                    ref_picture = s->cur_pic.ptr->f->data;
                 }
             }
         }
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index ad4502f3db..066dca9ac5 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1356,7 +1356,7 @@  static int estimate_best_b_count(MpegEncContext *s)
 
     for (i = 0; i < s->max_b_frames + 2; i++) {
         const MPVPicture *pre_input_ptr = i ? s->input_picture[i - 1] :
-                                           s->next_pic_ptr;
+                                           s->next_pic.ptr;
 
         if (pre_input_ptr) {
             const uint8_t *data[4];
@@ -1484,8 +1484,8 @@  static int select_input_picture(MpegEncContext *s)
     if (!s->reordered_input_picture[0] && s->input_picture[0]) {
         if (s->frame_skip_threshold || s->frame_skip_factor) {
             if (s->picture_in_gop_number < s->gop_size &&
-                s->next_pic_ptr &&
-                skip_check(s, s->input_picture[0], s->next_pic_ptr)) {
+                s->next_pic.ptr &&
+                skip_check(s, s->input_picture[0], s->next_pic.ptr)) {
                 // FIXME check that the gop check above is +-1 correct
                 ff_mpeg_unref_picture(s->input_picture[0]);
 
@@ -1496,7 +1496,7 @@  static int select_input_picture(MpegEncContext *s)
         }
 
         if (/*s->picture_in_gop_number >= s->gop_size ||*/
-            !s->next_pic_ptr || s->intra_only) {
+            !s->next_pic.ptr || s->intra_only) {
             s->reordered_input_picture[0] = s->input_picture[0];
             s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_I;
             s->reordered_input_picture[0]->coded_picture_number =
@@ -1624,17 +1624,17 @@  no_output_pic:
                     s->new_pic->data[i] += INPLACE_OFFSET;
             }
         }
-        s->cur_pic_ptr = s->reordered_input_picture[0];
+        s->cur_pic.ptr = s->reordered_input_picture[0];
         av_assert1(s->mb_width  == s->buffer_pools.alloc_mb_width);
         av_assert1(s->mb_height == s->buffer_pools.alloc_mb_height);
         av_assert1(s->mb_stride == s->buffer_pools.alloc_mb_stride);
-        ret = ff_mpv_alloc_pic_accessories(s->avctx, s->cur_pic_ptr, &s->me,
+        ret = ff_mpv_alloc_pic_accessories(s->avctx, &s->cur_pic, &s->me,
                                            &s->sc, &s->buffer_pools, s->mb_height);
         if (ret < 0) {
-            ff_mpeg_unref_picture(s->cur_pic_ptr);
+            ff_mpv_unref_picture(&s->cur_pic);
             return ret;
         }
-        s->picture_number = s->cur_pic_ptr->display_picture_number;
+        s->picture_number = s->cur_pic.ptr->display_picture_number;
 
     }
     return 0;
@@ -1674,7 +1674,7 @@  static void frame_end(MpegEncContext *s)
     emms_c();
 
     s->last_pict_type                 = s->pict_type;
-    s->last_lambda_for [s->pict_type] = s->cur_pic_ptr->f->quality;
+    s->last_lambda_for [s->pict_type] = s->cur_pic.ptr->f->quality;
     if (s->pict_type!= AV_PICTURE_TYPE_B)
         s->last_non_b_pict_type = s->pict_type;
 }
@@ -1700,47 +1700,26 @@  static void update_noise_reduction(MpegEncContext *s)
     }
 }
 
-static int frame_start(MpegEncContext *s)
+static void frame_start(MpegEncContext *s)
 {
-    int ret;
-
     /* mark & release old frames */
-    if (s->pict_type != AV_PICTURE_TYPE_B && s->last_pic_ptr &&
-        s->last_pic_ptr != s->next_pic_ptr &&
-        s->last_pic_ptr->f->buf[0]) {
-        ff_mpeg_unref_picture(s->last_pic_ptr);
+    if (s->pict_type != AV_PICTURE_TYPE_B && s->last_pic.ptr &&
+        s->last_pic.ptr != s->next_pic.ptr &&
+        s->last_pic.ptr->f->buf[0]) {
+        ff_mpv_unref_picture(&s->last_pic);
     }
 
-    s->cur_pic_ptr->f->pict_type = s->pict_type;
-
-    ff_mpeg_unref_picture(&s->cur_pic);
-    if ((ret = ff_mpeg_ref_picture(&s->cur_pic, s->cur_pic_ptr)) < 0)
-        return ret;
+    s->cur_pic.ptr->f->pict_type = s->pict_type;
 
     if (s->pict_type != AV_PICTURE_TYPE_B) {
-        s->last_pic_ptr = s->next_pic_ptr;
-        s->next_pic_ptr = s->cur_pic_ptr;
-    }
-
-    if (s->last_pic_ptr) {
-        ff_mpeg_unref_picture(&s->last_pic);
-        if (s->last_pic_ptr->f->buf[0] &&
-            (ret = ff_mpeg_ref_picture(&s->last_pic, s->last_pic_ptr)) < 0)
-            return ret;
-    }
-    if (s->next_pic_ptr) {
-        ff_mpeg_unref_picture(&s->next_pic);
-        if (s->next_pic_ptr->f->buf[0] &&
-            (ret = ff_mpeg_ref_picture(&s->next_pic, s->next_pic_ptr)) < 0)
-            return ret;
+        ff_mpv_replace_picture(&s->last_pic, &s->next_pic);
+        ff_mpv_replace_picture(&s->next_pic, &s->cur_pic);
     }
 
     if (s->dct_error_sum) {
         av_assert2(s->noise_reduction && s->encoding);
         update_noise_reduction(s);
     }
-
-    return 0;
 }
 
 int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
@@ -1793,9 +1772,7 @@  int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
 
         s->pict_type = s->new_pic->pict_type;
         //emms_c();
-        ret = frame_start(s);
-        if (ret < 0)
-            return ret;
+        frame_start(s);
 vbv_retry:
         ret = encode_picture(s);
         if (growing_buffer) {
@@ -1858,7 +1835,7 @@  vbv_retry:
 
         for (int i = 0; i < MPV_MAX_PLANES; i++)
             avctx->error[i] += s->encoding_error[i];
-        ff_side_data_set_encoder_stats(pkt, s->cur_pic.f->quality,
+        ff_side_data_set_encoder_stats(pkt, s->cur_pic.ptr->f->quality,
                                        s->encoding_error,
                                        (avctx->flags&AV_CODEC_FLAG_PSNR) ? MPV_MAX_PLANES : 0,
                                        s->pict_type);
@@ -1952,10 +1929,10 @@  vbv_retry:
         }
         s->total_bits     += s->frame_bits;
 
-        pkt->pts = s->cur_pic.f->pts;
-        pkt->duration = s->cur_pic.f->duration;
+        pkt->pts = s->cur_pic.ptr->f->pts;
+        pkt->duration = s->cur_pic.ptr->f->duration;
         if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) {
-            if (!s->cur_pic.coded_picture_number)
+            if (!s->cur_pic.ptr->coded_picture_number)
                 pkt->dts = pkt->pts - s->dts_delta;
             else
                 pkt->dts = s->reordered_pts;
@@ -1965,12 +1942,12 @@  vbv_retry:
 
         // the no-delay case is handled in generic code
         if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY) {
-            ret = ff_encode_reordered_opaque(avctx, pkt, s->cur_pic.f);
+            ret = ff_encode_reordered_opaque(avctx, pkt, s->cur_pic.ptr->f);
             if (ret < 0)
                 return ret;
         }
 
-        if (s->cur_pic.f->flags & AV_FRAME_FLAG_KEY)
+        if (s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_KEY)
             pkt->flags |= AV_PKT_FLAG_KEY;
         if (s->mb_info)
             av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size);
@@ -3516,14 +3493,12 @@  static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src)
 
 static int estimate_qp(MpegEncContext *s, int dry_run){
     if (s->next_lambda){
-        s->cur_pic_ptr->f->quality =
-        s->cur_pic.f->quality = s->next_lambda;
+        s->cur_pic.ptr->f->quality = s->next_lambda;
         if(!dry_run) s->next_lambda= 0;
     } else if (!s->fixed_qscale) {
         int quality = ff_rate_estimate_qscale(s, dry_run);
-        s->cur_pic_ptr->f->quality =
-        s->cur_pic.f->quality = quality;
-        if (s->cur_pic.f->quality < 0)
+        s->cur_pic.ptr->f->quality = quality;
+        if (s->cur_pic.ptr->f->quality < 0)
             return -1;
     }
 
@@ -3546,15 +3521,15 @@  static int estimate_qp(MpegEncContext *s, int dry_run){
         s->lambda= s->lambda_table[0];
         //FIXME broken
     }else
-        s->lambda = s->cur_pic.f->quality;
+        s->lambda = s->cur_pic.ptr->f->quality;
     update_qscale(s);
     return 0;
 }
 
 /* must be called before writing the header */
 static void set_frame_distances(MpegEncContext * s){
-    av_assert1(s->cur_pic_ptr->f->pts != AV_NOPTS_VALUE);
-    s->time = s->cur_pic_ptr->f->pts * s->avctx->time_base.num;
+    av_assert1(s->cur_pic.ptr->f->pts != AV_NOPTS_VALUE);
+    s->time = s->cur_pic.ptr->f->pts * s->avctx->time_base.num;
 
     if(s->pict_type==AV_PICTURE_TYPE_B){
         s->pb_time= s->pp_time - (s->last_non_b_time - s->time);
@@ -3585,7 +3560,7 @@  static int encode_picture(MpegEncContext *s)
 
     s->me.scene_change_score=0;
 
-//    s->lambda= s->cur_pic_ptr->quality; //FIXME qscale / ... stuff for ME rate distortion
+//    s->lambda= s->cur_pic.ptr->quality; //FIXME qscale / ... stuff for ME rate distortion
 
     if(s->pict_type==AV_PICTURE_TYPE_I){
         if(s->msmpeg4_version >= 3) s->no_rounding=1;
@@ -3773,18 +3748,14 @@  static int encode_picture(MpegEncContext *s)
         }
     }
 
-    //FIXME var duplication
     if (s->pict_type == AV_PICTURE_TYPE_I) {
-        s->cur_pic_ptr->f->flags |= AV_FRAME_FLAG_KEY; //FIXME pic_ptr
-        s->cur_pic.f->flags |= AV_FRAME_FLAG_KEY;
+        s->cur_pic.ptr->f->flags |= AV_FRAME_FLAG_KEY;
     } else {
-        s->cur_pic_ptr->f->flags &= ~AV_FRAME_FLAG_KEY; //FIXME pic_ptr
-        s->cur_pic.f->flags &= ~AV_FRAME_FLAG_KEY;
+        s->cur_pic.ptr->f->flags &= ~AV_FRAME_FLAG_KEY;
     }
-    s->cur_pic_ptr->f->pict_type =
-    s->cur_pic.f->pict_type = s->pict_type;
+    s->cur_pic.ptr->f->pict_type = s->pict_type;
 
-    if (s->cur_pic.f->flags & AV_FRAME_FLAG_KEY)
+    if (s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_KEY)
         s->picture_in_gop_number=0;
 
     s->mb_x = s->mb_y = 0;
diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c
index a757357316..88c0566558 100644
--- a/libavcodec/mpegvideo_motion.c
+++ b/libavcodec/mpegvideo_motion.c
@@ -514,7 +514,7 @@  static inline void apply_obmc(MpegEncContext *s,
                               op_pixels_func (*pix_op)[4])
 {
     LOCAL_ALIGNED_8(int16_t, mv_cache, [4], [4][2]);
-    const MPVPicture *cur_frame = &s->cur_pic;
+    const MPVWorkPicture *cur_frame = &s->cur_pic;
     int mb_x = s->mb_x;
     int mb_y = s->mb_y;
     const int xy         = mb_x + mb_y * s->mb_stride;
@@ -749,7 +749,7 @@  static av_always_inline void mpv_motion_internal(MpegEncContext *s,
             av_assert2(s->out_format == FMT_MPEG1);
             if (s->picture_structure != s->field_select[dir][0] + 1 &&
                 s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
-                ref_picture = s->cur_pic_ptr->f->data;
+                ref_picture = s->cur_pic.ptr->f->data;
             }
 
             mpeg_motion(s, dest_y, dest_cb, dest_cr,
@@ -767,7 +767,7 @@  static av_always_inline void mpv_motion_internal(MpegEncContext *s,
                     s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
                     ref2picture = ref_picture;
                 } else {
-                    ref2picture = s->cur_pic_ptr->f->data;
+                    ref2picture = s->cur_pic.ptr->f->data;
                 }
 
                 mpeg_motion(s, dest_y, dest_cb, dest_cr,
@@ -807,7 +807,7 @@  static av_always_inline void mpv_motion_internal(MpegEncContext *s,
                     /* opposite parity is always in the same frame if this is
                      * second field */
                     if (!s->first_field)
-                        ref_picture = s->cur_pic_ptr->f->data;
+                        ref_picture = s->cur_pic.ptr->f->data;
                 }
             }
             break;
diff --git a/libavcodec/mpv_reconstruct_mb_template.c b/libavcodec/mpv_reconstruct_mb_template.c
index 70dab76f73..0b7a6a6d31 100644
--- a/libavcodec/mpv_reconstruct_mb_template.c
+++ b/libavcodec/mpv_reconstruct_mb_template.c
@@ -124,11 +124,11 @@  void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
             if (HAVE_THREADS && is_mpeg12 != DEFINITELY_MPEG12 &&
                 s->avctx->active_thread_type & FF_THREAD_FRAME) {
                 if (s->mv_dir & MV_DIR_FORWARD) {
-                    ff_thread_await_progress(&s->last_pic_ptr->tf,
+                    ff_thread_await_progress(&s->last_pic.ptr->tf,
                                              lowest_referenced_row(s, 0), 0);
                 }
                 if (s->mv_dir & MV_DIR_BACKWARD) {
-                    ff_thread_await_progress(&s->next_pic_ptr->tf,
+                    ff_thread_await_progress(&s->next_pic.ptr->tf,
                                              lowest_referenced_row(s, 1), 0);
                 }
             }
diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c
index 05319436b6..1888053eb2 100644
--- a/libavcodec/mss2.c
+++ b/libavcodec/mss2.c
@@ -382,7 +382,7 @@  static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size,
     MSS12Context *c   = &ctx->c;
     VC1Context *v     = avctx->priv_data;
     MpegEncContext *s = &v->s;
-    MPVPicture *f;
+    MPVWorkPicture *f;
     int ret;
 
     ff_mpeg_flush(avctx);
diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c
index 76ef81ea4d..99b2b14f1f 100644
--- a/libavcodec/nvdec_mpeg12.c
+++ b/libavcodec/nvdec_mpeg12.c
@@ -39,7 +39,7 @@  static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer
     CUVIDMPEG2PICPARAMS *ppc = &pp->CodecSpecific.mpeg2;
     FrameDecodeData *fdd;
     NVDECFrame *cf;
-    AVFrame *cur_frame = s->cur_pic.f;
+    AVFrame *cur_frame = s->cur_pic.ptr->f;
 
     int ret, i;
 
@@ -64,8 +64,8 @@  static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer
                              s->pict_type == AV_PICTURE_TYPE_P,
 
         .CodecSpecific.mpeg2 = {
-            .ForwardRefIdx     = ff_nvdec_get_ref_idx(s->last_pic.f),
-            .BackwardRefIdx    = ff_nvdec_get_ref_idx(s->next_pic.f),
+            .ForwardRefIdx     = ff_nvdec_get_ref_idx(s->last_pic.ptr ? s->last_pic.ptr->f : NULL),
+            .BackwardRefIdx    = ff_nvdec_get_ref_idx(s->next_pic.ptr ? s->next_pic.ptr->f : NULL),
 
             .picture_coding_type        = s->pict_type,
             .full_pel_forward_vector    = s->full_pel[0],
diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c
index 468002d1c5..80da11b5b1 100644
--- a/libavcodec/nvdec_mpeg4.c
+++ b/libavcodec/nvdec_mpeg4.c
@@ -38,7 +38,7 @@  static int nvdec_mpeg4_start_frame(AVCodecContext *avctx, const uint8_t *buffer,
     CUVIDMPEG4PICPARAMS *ppc = &pp->CodecSpecific.mpeg4;
     FrameDecodeData *fdd;
     NVDECFrame *cf;
-    AVFrame *cur_frame = s->cur_pic.f;
+    AVFrame *cur_frame = s->cur_pic.ptr->f;
 
     int ret, i;
 
@@ -60,8 +60,8 @@  static int nvdec_mpeg4_start_frame(AVCodecContext *avctx, const uint8_t *buffer,
                              s->pict_type == AV_PICTURE_TYPE_S,
 
         .CodecSpecific.mpeg4 = {
-            .ForwardRefIdx                = ff_nvdec_get_ref_idx(s->last_pic.f),
-            .BackwardRefIdx               = ff_nvdec_get_ref_idx(s->next_pic.f),
+            .ForwardRefIdx                = ff_nvdec_get_ref_idx(s->last_pic.ptr ? s->last_pic.ptr->f : NULL),
+            .BackwardRefIdx               = ff_nvdec_get_ref_idx(s->next_pic.ptr ? s->next_pic.ptr->f : NULL),
 
             .video_object_layer_width     = s->width,
             .video_object_layer_height    = s->height,
diff --git a/libavcodec/nvdec_vc1.c b/libavcodec/nvdec_vc1.c
index 40cd18a8e7..0668863cb4 100644
--- a/libavcodec/nvdec_vc1.c
+++ b/libavcodec/nvdec_vc1.c
@@ -38,7 +38,7 @@  static int nvdec_vc1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u
     CUVIDPICPARAMS     *pp = &ctx->pic_params;
     FrameDecodeData *fdd;
     NVDECFrame *cf;
-    AVFrame *cur_frame = s->cur_pic.f;
+    AVFrame *cur_frame = s->cur_pic.ptr->f;
 
     int ret;
 
@@ -63,8 +63,8 @@  static int nvdec_vc1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u
                              s->pict_type == AV_PICTURE_TYPE_P,
 
         .CodecSpecific.vc1 = {
-            .ForwardRefIdx     = ff_nvdec_get_ref_idx(s->last_pic.f),
-            .BackwardRefIdx    = ff_nvdec_get_ref_idx(s->next_pic.f),
+            .ForwardRefIdx     = ff_nvdec_get_ref_idx(s->last_pic.ptr ? s->last_pic.ptr->f : NULL),
+            .BackwardRefIdx    = ff_nvdec_get_ref_idx(s->next_pic.ptr ? s->next_pic.ptr->f : NULL),
             .FrameWidth        = cur_frame->width,
             .FrameHeight       = cur_frame->height,
 
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index 3397fffcab..193e9452bd 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -40,10 +40,10 @@  void ff_write_pass1_stats(MpegEncContext *s)
     snprintf(s->avctx->stats_out, 256,
              "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d "
              "fcode:%d bcode:%d mc-var:%"PRId64" var:%"PRId64" icount:%d skipcount:%d hbits:%d;\n",
-             s->cur_pic_ptr->display_picture_number,
-             s->cur_pic_ptr->coded_picture_number,
+             s->cur_pic.ptr->display_picture_number,
+             s->cur_pic.ptr->coded_picture_number,
              s->pict_type,
-             s->cur_pic.f->quality,
+             s->cur_pic.ptr->f->quality,
              s->i_tex_bits,
              s->p_tex_bits,
              s->mv_bits,
@@ -933,9 +933,9 @@  float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run)
          * here instead of reordering but the reordering is simpler for now
          * until H.264 B-pyramid must be handled. */
         if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)
-            dts_pic = s->cur_pic_ptr;
+            dts_pic = s->cur_pic.ptr;
         else
-            dts_pic = s->last_pic_ptr;
+            dts_pic = s->last_pic.ptr;
 
         if (!dts_pic || dts_pic->f->pts == AV_NOPTS_VALUE)
             wanted_bits = (uint64_t)(s->bit_rate * (double)picture_number / fps);
diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c
index aea42dd314..201e7ed6d0 100644
--- a/libavcodec/rv10.c
+++ b/libavcodec/rv10.c
@@ -170,7 +170,7 @@  static int rv20_decode_picture_header(RVDecContext *rv, int whole_size)
         av_log(s->avctx, AV_LOG_ERROR, "low delay B\n");
         return -1;
     }
-    if (!s->last_pic_ptr && s->pict_type == AV_PICTURE_TYPE_B) {
+    if (!s->last_pic.ptr && s->pict_type == AV_PICTURE_TYPE_B) {
         av_log(s->avctx, AV_LOG_ERROR, "early B-frame\n");
         return AVERROR_INVALIDDATA;
     }
@@ -458,9 +458,9 @@  static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf,
     if (whole_size < s->mb_width * s->mb_height / 8)
         return AVERROR_INVALIDDATA;
 
-    if ((s->mb_x == 0 && s->mb_y == 0) || !s->cur_pic_ptr) {
+    if ((s->mb_x == 0 && s->mb_y == 0) || !s->cur_pic.ptr) {
         // FIXME write parser so we always have complete frames?
-        if (s->cur_pic_ptr) {
+        if (s->cur_pic.ptr) {
             ff_er_frame_end(&s->er, NULL);
             ff_mpv_frame_end(s);
             s->mb_x = s->mb_y = s->resync_mb_x = s->resync_mb_y = 0;
@@ -469,7 +469,7 @@  static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf,
             return ret;
         ff_mpeg_er_frame_start(s);
     } else {
-        if (s->cur_pic_ptr->f->pict_type != s->pict_type) {
+        if (s->cur_pic.ptr->f->pict_type != s->pict_type) {
             av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n");
             return AVERROR_INVALIDDATA;
         }
@@ -632,28 +632,28 @@  static int rv10_decode_frame(AVCodecContext *avctx, AVFrame *pict,
             i++;
     }
 
-    if (s->cur_pic_ptr && s->mb_y >= s->mb_height) {
+    if (s->cur_pic.ptr && s->mb_y >= s->mb_height) {
         ff_er_frame_end(&s->er, NULL);
         ff_mpv_frame_end(s);
 
         if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
-            if ((ret = av_frame_ref(pict, s->cur_pic_ptr->f)) < 0)
+            if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
                 return ret;
-            ff_print_debug_info(s, s->cur_pic_ptr, pict);
-            ff_mpv_export_qp_table(s, pict, s->cur_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG1);
-        } else if (s->last_pic_ptr) {
-            if ((ret = av_frame_ref(pict, s->last_pic_ptr->f)) < 0)
+            ff_print_debug_info(s, s->cur_pic.ptr, pict);
+            ff_mpv_export_qp_table(s, pict, s->cur_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG1);
+        } else if (s->last_pic.ptr) {
+            if ((ret = av_frame_ref(pict, s->last_pic.ptr->f)) < 0)
                 return ret;
-            ff_print_debug_info(s, s->last_pic_ptr, pict);
-            ff_mpv_export_qp_table(s, pict,s->last_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG1);
+            ff_print_debug_info(s, s->last_pic.ptr, pict);
+            ff_mpv_export_qp_table(s, pict,s->last_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG1);
         }
 
-        if (s->last_pic_ptr || s->low_delay) {
+        if (s->last_pic.ptr || s->low_delay) {
             *got_frame = 1;
         }
 
         // so we can detect if frame_end was not called (find some nicer solution...)
-        s->cur_pic_ptr = NULL;
+        s->cur_pic.ptr = NULL;
     }
 
     return avpkt->size;
diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index 284de14e8c..d935c261b5 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -565,7 +565,7 @@  static void rv34_pred_mv_b(RV34DecContext *r, int block_type, int dir)
     int has_A = 0, has_B = 0, has_C = 0;
     int mx, my;
     int i, j;
-    MPVPicture *cur_pic = &s->cur_pic;
+    MPVWorkPicture *cur_pic = &s->cur_pic;
     const int mask = dir ? MB_TYPE_L1 : MB_TYPE_L0;
     int type = cur_pic->mb_type[mb_pos];
 
@@ -719,7 +719,7 @@  static inline void rv34_mc(RV34DecContext *r, const int block_type,
     if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
         /* wait for the referenced mb row to be finished */
         int mb_row = s->mb_y + ((yoff + my + 5 + 8 * height) >> 4);
-        const ThreadFrame *f = dir ? &s->next_pic_ptr->tf : &s->last_pic_ptr->tf;
+        const ThreadFrame *f = dir ? &s->next_pic.ptr->tf : &s->last_pic.ptr->tf;
         ff_thread_await_progress(f, mb_row, 0);
     }
 
@@ -899,7 +899,7 @@  static int rv34_decode_mv(RV34DecContext *r, int block_type)
         //surprisingly, it uses motion scheme from next reference frame
         /* wait for the current mb row to be finished */
         if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
-            ff_thread_await_progress(&s->next_pic_ptr->tf, FFMAX(0, s->mb_y-1), 0);
+            ff_thread_await_progress(&s->next_pic.ptr->tf, FFMAX(0, s->mb_y-1), 0);
 
         next_bt = s->next_pic.mb_type[s->mb_x + s->mb_y * s->mb_stride];
         if(IS_INTRA(next_bt) || IS_SKIP(next_bt)){
@@ -1483,7 +1483,7 @@  static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int
                 r->loop_filter(r, s->mb_y - 2);
 
             if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
-                ff_thread_report_progress(&s->cur_pic_ptr->tf,
+                ff_thread_report_progress(&s->cur_pic.ptr->tf,
                                           s->mb_y - 2, 0);
 
         }
@@ -1581,19 +1581,19 @@  static int finish_frame(AVCodecContext *avctx, AVFrame *pict)
     s->mb_num_left = 0;
 
     if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
-        ff_thread_report_progress(&s->cur_pic_ptr->tf, INT_MAX, 0);
+        ff_thread_report_progress(&s->cur_pic.ptr->tf, INT_MAX, 0);
 
     if (s->pict_type == AV_PICTURE_TYPE_B) {
-        if ((ret = av_frame_ref(pict, s->cur_pic_ptr->f)) < 0)
+        if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
             return ret;
-        ff_print_debug_info(s, s->cur_pic_ptr, pict);
-        ff_mpv_export_qp_table(s, pict, s->cur_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG1);
+        ff_print_debug_info(s, s->cur_pic.ptr, pict);
+        ff_mpv_export_qp_table(s, pict, s->cur_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG1);
         got_picture = 1;
-    } else if (s->last_pic_ptr) {
-        if ((ret = av_frame_ref(pict, s->last_pic_ptr->f)) < 0)
+    } else if (s->last_pic.ptr) {
+        if ((ret = av_frame_ref(pict, s->last_pic.ptr->f)) < 0)
             return ret;
-        ff_print_debug_info(s, s->last_pic_ptr, pict);
-        ff_mpv_export_qp_table(s, pict, s->last_pic_ptr, FF_MPV_QSCALE_TYPE_MPEG1);
+        ff_print_debug_info(s, s->last_pic.ptr, pict);
+        ff_mpv_export_qp_table(s, pict, s->last_pic.ptr, FF_MPV_QSCALE_TYPE_MPEG1);
         got_picture = 1;
     }
 
@@ -1628,10 +1628,10 @@  int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     /* no supplementary picture */
     if (buf_size == 0) {
         /* special case for last picture */
-        if (s->next_pic_ptr) {
-            if ((ret = av_frame_ref(pict, s->next_pic_ptr->f)) < 0)
+        if (s->next_pic.ptr) {
+            if ((ret = av_frame_ref(pict, s->next_pic.ptr->f)) < 0)
                 return ret;
-            s->next_pic_ptr = NULL;
+            s->next_pic.ptr = NULL;
 
             *got_picture_ptr = 1;
         }
@@ -1654,7 +1654,7 @@  int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n");
         return AVERROR_INVALIDDATA;
     }
-    if ((!s->last_pic_ptr || !s->last_pic_ptr->f->data[0]) &&
+    if ((!s->last_pic.ptr || !s->last_pic.ptr->f->data[0]) &&
         si.type == AV_PICTURE_TYPE_B) {
         av_log(avctx, AV_LOG_ERROR, "Invalid decoder state: B-frame without "
                "reference data.\n");
@@ -1667,7 +1667,7 @@  int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
 
     /* first slice */
     if (si.start == 0) {
-        if (s->mb_num_left > 0 && s->cur_pic_ptr) {
+        if (s->mb_num_left > 0 && s->cur_pic.ptr) {
             av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n",
                    s->mb_num_left);
             if (!s->context_reinit)
@@ -1792,7 +1792,7 @@  int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
             break;
     }
 
-    if (s->cur_pic_ptr) {
+    if (s->cur_pic.ptr) {
         if (last) {
             if(r->loop_filter)
                 r->loop_filter(r, s->mb_height - 1);
@@ -1809,7 +1809,7 @@  int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
             ff_er_frame_end(&s->er, NULL);
             ff_mpv_frame_end(s);
             s->mb_num_left = 0;
-            ff_thread_report_progress(&s->cur_pic_ptr->tf, INT_MAX, 0);
+            ff_thread_report_progress(&s->cur_pic.ptr->tf, INT_MAX, 0);
             return AVERROR_INVALIDDATA;
         }
     }
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 49e7a10321..e7a870d783 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -62,6 +62,7 @@  typedef struct SnowEncContext {
 
     MECmpContext mecc;
     MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX)
+    MPVPicture cur_pic, last_pic;
 #define ME_CACHE_SIZE 1024
     unsigned me_cache[ME_CACHE_SIZE];
     unsigned me_cache_generation;
@@ -1834,9 +1835,9 @@  static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     if (ret < 0)
         return ret;
 
-    mpv->cur_pic_ptr    = &mpv->cur_pic;
-    mpv->cur_pic.f      = s->current_picture;
-    mpv->cur_pic.f->pts = pict->pts;
+    mpv->cur_pic.ptr         = &enc->cur_pic;
+    mpv->cur_pic.ptr->f      = s->current_picture;
+    mpv->cur_pic.ptr->f->pts = pict->pts;
     if(pic->pict_type == AV_PICTURE_TYPE_P){
         int block_width = (width +15)>>4;
         int block_height= (height+15)>>4;
@@ -1846,9 +1847,9 @@  static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         av_assert0(s->last_picture[0]->data[0]);
 
         mpv->avctx = s->avctx;
-        mpv->last_pic.f   = s->last_picture[0];
+        mpv->last_pic.ptr    = &enc->last_pic;
+        mpv->last_pic.ptr->f = s->last_picture[0];
         mpv-> new_pic     = s->input_picture;
-        mpv->last_pic_ptr = &mpv->last_pic;
         mpv->linesize   = stride;
         mpv->uvlinesize = s->current_picture->linesize[1];
         mpv->width      = width;
@@ -2043,9 +2044,9 @@  redo_frame:
     mpv->frame_bits = 8 * (s->c.bytestream - s->c.bytestream_start);
     mpv->p_tex_bits = mpv->frame_bits - mpv->misc_bits - mpv->mv_bits;
     mpv->total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
-    mpv->cur_pic.display_picture_number =
-    mpv->cur_pic.coded_picture_number   = avctx->frame_num;
-    mpv->cur_pic.f->quality             = pic->quality;
+    enc->cur_pic.display_picture_number =
+    enc->cur_pic.coded_picture_number   = avctx->frame_num;
+    enc->cur_pic.f->quality             = pic->quality;
     if (enc->pass1_rc)
         if (ff_rate_estimate_qscale(mpv, 0) < 0)
             return -1;
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index c75ab1800a..9631fa243d 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -60,6 +60,7 @@  typedef struct SVQ1EncContext {
      * else, the idea is to make the motion estimation eventually independent
      * of MpegEncContext, so this will be removed then. */
     MpegEncContext m;
+    MPVPicture cur_pic, last_pic;
     AVCodecContext *avctx;
     MECmpContext mecc;
     HpelDSPContext hdsp;
@@ -326,8 +327,8 @@  static int svq1_encode_plane(SVQ1EncContext *s, int plane,
 
     if (s->pict_type == AV_PICTURE_TYPE_P) {
         s->m.avctx                         = s->avctx;
-        s->m.cur_pic_ptr                   = &s->m.cur_pic;
-        s->m.last_pic_ptr              = &s->m.last_pic;
+        s->m.cur_pic.ptr                   = &s->cur_pic;
+        s->m.last_pic.ptr                  = &s->last_pic;
         s->m.last_pic.data[0]        = ref_plane;
         s->m.linesize                      =
         s->m.last_pic.linesize[0]    =
diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c
index 389540fd0c..328a2f7db3 100644
--- a/libavcodec/vaapi_mpeg2.c
+++ b/libavcodec/vaapi_mpeg2.c
@@ -42,12 +42,12 @@  static inline int mpeg2_get_is_frame_start(const MpegEncContext *s)
 static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
 {
     const MpegEncContext *s = avctx->priv_data;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     VAPictureParameterBufferMPEG2 pic_param;
     VAIQMatrixBufferMPEG2 iq_matrix;
     int i, err;
 
-    pic->output_surface = ff_vaapi_get_surface_id(s->cur_pic_ptr->f);
+    pic->output_surface = ff_vaapi_get_surface_id(s->cur_pic.ptr->f);
 
     pic_param = (VAPictureParameterBufferMPEG2) {
         .horizontal_size                 = s->width,
@@ -73,10 +73,10 @@  static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_
 
     switch (s->pict_type) {
     case AV_PICTURE_TYPE_B:
-        pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_pic.f);
+        pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_pic.ptr->f);
         // fall-through
     case AV_PICTURE_TYPE_P:
-        pic_param.forward_reference_picture = ff_vaapi_get_surface_id(s->last_pic.f);
+        pic_param.forward_reference_picture = ff_vaapi_get_surface_id(s->last_pic.ptr->f);
         break;
     }
 
@@ -115,7 +115,7 @@  fail:
 static int vaapi_mpeg2_end_frame(AVCodecContext *avctx)
 {
     MpegEncContext     *s   = avctx->priv_data;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     int ret;
 
     ret = ff_vaapi_decode_issue(avctx, pic);
@@ -131,7 +131,7 @@  fail:
 static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
 {
     const MpegEncContext *s = avctx->priv_data;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     VASliceParameterBufferMPEG2 slice_param;
     GetBitContext gb;
     uint32_t quantiser_scale_code, intra_slice_flag, macroblock_offset;
diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c
index e227bee113..76602c544a 100644
--- a/libavcodec/vaapi_mpeg4.c
+++ b/libavcodec/vaapi_mpeg4.c
@@ -49,11 +49,11 @@  static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_
 {
     Mpeg4DecContext *ctx = avctx->priv_data;
     MpegEncContext *s = &ctx->m;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     VAPictureParameterBufferMPEG4 pic_param;
     int i, err;
 
-    pic->output_surface = ff_vaapi_get_surface_id(s->cur_pic_ptr->f);
+    pic->output_surface = ff_vaapi_get_surface_id(s->cur_pic.ptr->f);
 
     pic_param = (VAPictureParameterBufferMPEG4) {
         .vop_width                        = s->width,
@@ -78,7 +78,7 @@  static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_
         .vop_fields.bits = {
             .vop_coding_type              = s->pict_type - AV_PICTURE_TYPE_I,
             .backward_reference_vop_coding_type =
-                s->pict_type == AV_PICTURE_TYPE_B ? s->next_pic.f->pict_type - AV_PICTURE_TYPE_I : 0,
+                s->pict_type == AV_PICTURE_TYPE_B ? s->next_pic.ptr->f->pict_type - AV_PICTURE_TYPE_I : 0,
             .vop_rounding_type            = s->no_rounding,
             .intra_dc_vlc_thr             = mpeg4_get_intra_dc_vlc_thr(ctx),
             .top_field_first              = s->top_field_first,
@@ -100,9 +100,9 @@  static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_
     }
 
     if (s->pict_type == AV_PICTURE_TYPE_B)
-        pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_pic.f);
+        pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_pic.ptr->f);
     if (s->pict_type != AV_PICTURE_TYPE_I)
-        pic_param.forward_reference_picture  = ff_vaapi_get_surface_id(s->last_pic.f);
+        pic_param.forward_reference_picture  = ff_vaapi_get_surface_id(s->last_pic.ptr->f);
 
     err = ff_vaapi_decode_make_param_buffer(avctx, pic,
                                             VAPictureParameterBufferType,
@@ -139,7 +139,7 @@  fail:
 static int vaapi_mpeg4_end_frame(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     int ret;
 
     ret = ff_vaapi_decode_issue(avctx, pic);
@@ -155,7 +155,7 @@  fail:
 static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
 {
     MpegEncContext *s = avctx->priv_data;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     VASliceParameterBufferMPEG4 slice_param;
     int err;
 
diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c
index ef914cf4b2..8aedad7828 100644
--- a/libavcodec/vaapi_vc1.c
+++ b/libavcodec/vaapi_vc1.c
@@ -253,11 +253,11 @@  static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t
 {
     const VC1Context *v = avctx->priv_data;
     const MpegEncContext *s = &v->s;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     VAPictureParameterBufferVC1 pic_param;
     int err;
 
-    pic->output_surface = ff_vaapi_get_surface_id(s->cur_pic_ptr->f);
+    pic->output_surface = ff_vaapi_get_surface_id(s->cur_pic.ptr->f);
 
     pic_param = (VAPictureParameterBufferVC1) {
         .forward_reference_picture         = VA_INVALID_ID,
@@ -374,10 +374,12 @@  static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t
 
     switch (s->pict_type) {
     case AV_PICTURE_TYPE_B:
-        pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_pic.f);
+        if (s->next_pic.ptr)
+            pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_pic.ptr->f);
         // fall-through
     case AV_PICTURE_TYPE_P:
-        pic_param.forward_reference_picture = ff_vaapi_get_surface_id(s->last_pic.f);
+        if (s->last_pic.ptr)
+            pic_param.forward_reference_picture = ff_vaapi_get_surface_id(s->last_pic.ptr->f);
         break;
     }
 
@@ -450,7 +452,7 @@  static int vaapi_vc1_end_frame(AVCodecContext *avctx)
 {
     VC1Context *v = avctx->priv_data;
     MpegEncContext *s = &v->s;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     int ret;
 
     ret = ff_vaapi_decode_issue(avctx, pic);
@@ -465,7 +467,7 @@  static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer,
 {
     const VC1Context *v = avctx->priv_data;
     const MpegEncContext *s = &v->s;
-    VAAPIDecodePicture *pic = s->cur_pic_ptr->hwaccel_picture_private;
+    VAAPIDecodePicture *pic = s->cur_pic.ptr->hwaccel_picture_private;
     VASliceParameterBufferVC1 slice_param;
     int mb_height;
     int err;
diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index 643232653c..987e77fcc7 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -856,7 +856,7 @@  int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_BI : AV_PICTURE_TYPE_B;
         else
             v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
-        v->s.cur_pic_ptr->f->pict_type = v->s.pict_type;
+        v->s.cur_pic.ptr->f->pict_type = v->s.pict_type;
         if (!v->pic_header_flag)
             goto parse_common_info;
     }
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index 9cb9fd27bf..b880f978d1 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -59,9 +59,9 @@  static inline void init_block_index(VC1Context *v)
     MpegEncContext *s = &v->s;
     ff_init_block_index(s);
     if (v->field_mode && !(v->second_field ^ v->tff)) {
-        s->dest[0] += s->cur_pic_ptr->f->linesize[0];
-        s->dest[1] += s->cur_pic_ptr->f->linesize[1];
-        s->dest[2] += s->cur_pic_ptr->f->linesize[2];
+        s->dest[0] += s->cur_pic.ptr->f->linesize[0];
+        s->dest[1] += s->cur_pic.ptr->f->linesize[1];
+        s->dest[2] += s->cur_pic.ptr->f->linesize[2];
     }
 }
 
@@ -2106,7 +2106,7 @@  static int vc1_decode_b_mb_intfi(VC1Context *v)
             if (bmvtype == BMV_TYPE_DIRECT) {
                 dmv_x[0] = dmv_y[0] = pred_flag[0] = 0;
                 dmv_x[1] = dmv_y[1] = pred_flag[0] = 0;
-                if (!s->next_pic_ptr->field_picture) {
+                if (!s->next_pic.ptr->field_picture) {
                     av_log(s->avctx, AV_LOG_ERROR, "Mixed field/frame direct mode not supported\n");
                     return AVERROR_INVALIDDATA;
                 }
@@ -2272,7 +2272,7 @@  static int vc1_decode_b_mb_intfr(VC1Context *v)
             direct = v->direct_mb_plane[mb_pos];
 
         if (direct) {
-            if (s->next_pic_ptr->field_picture)
+            if (s->next_pic.ptr->field_picture)
                 av_log(s->avctx, AV_LOG_WARNING, "Mixed frame/field direct mode not supported\n");
             s->mv[0][0][0] = s->cur_pic.motion_val[0][s->block_index[0]][0] = scale_mv(s->next_pic.motion_val[1][s->block_index[0]][0], v->bfraction, 0, s->quarter_sample);
             s->mv[0][0][1] = s->cur_pic.motion_val[0][s->block_index[0]][1] = scale_mv(s->next_pic.motion_val[1][s->block_index[0]][1], v->bfraction, 0, s->quarter_sample);
@@ -2969,7 +2969,7 @@  void ff_vc1_decode_blocks(VC1Context *v)
 
     v->s.esc3_level_length = 0;
     if (v->x8_type) {
-        ff_intrax8_decode_picture(&v->x8, &v->s.cur_pic,
+        ff_intrax8_decode_picture(&v->x8, v->s.cur_pic.ptr,
                                   &v->s.gb, &v->s.mb_x, &v->s.mb_y,
                                   2 * v->pq + v->halfpq, v->pq * !v->pquantizer,
                                   v->s.loop_filter, v->s.low_delay);
diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c
index ad41004e66..de9774ac2b 100644
--- a/libavcodec/vc1_mc.c
+++ b/libavcodec/vc1_mc.c
@@ -187,8 +187,8 @@  void ff_vc1_mc_1mv(VC1Context *v, int dir)
         !v->s.last_pic.data[0])
         return;
 
-    linesize   = s->cur_pic_ptr->f->linesize[0];
-    uvlinesize = s->cur_pic_ptr->f->linesize[1];
+    linesize   = s->cur_pic.ptr->f->linesize[0];
+    uvlinesize = s->cur_pic.ptr->f->linesize[1];
 
     mx = s->mv[dir][0][0];
     my = s->mv[dir][0][1];
@@ -233,7 +233,7 @@  void ff_vc1_mc_1mv(VC1Context *v, int dir)
             luty  = v->last_luty;
             lutuv = v->last_lutuv;
             use_ic = v->last_use_ic;
-            interlace = !!(s->last_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+            interlace = s->last_pic.ptr->interlaced;
         }
     } else {
         srcY = s->next_pic.data[0];
@@ -242,7 +242,7 @@  void ff_vc1_mc_1mv(VC1Context *v, int dir)
         luty  = v->next_luty;
         lutuv = v->next_lutuv;
         use_ic = v->next_use_ic;
-        interlace = !!(s->next_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+        interlace = s->next_pic.ptr->interlaced;
     }
 
     if (!srcY || !srcU) {
@@ -467,7 +467,7 @@  void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
         !v->s.last_pic.data[0])
         return;
 
-    linesize = s->cur_pic_ptr->f->linesize[0];
+    linesize = s->cur_pic.ptr->f->linesize[0];
 
     mx = s->mv[dir][n][0];
     my = s->mv[dir][n][1];
@@ -482,13 +482,13 @@  void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
             srcY = s->last_pic.data[0];
             luty = v->last_luty;
             use_ic = v->last_use_ic;
-            interlace = !!(s->last_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+            interlace = s->last_pic.ptr->interlaced;
         }
     } else {
         srcY = s->next_pic.data[0];
         luty = v->next_luty;
         use_ic = v->next_use_ic;
-        interlace = !!(s->next_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+        interlace = s->next_pic.ptr->interlaced;
     }
 
     if (!srcY) {
@@ -669,7 +669,7 @@  void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
     s->cur_pic.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx;
     s->cur_pic.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty;
 
-    uvlinesize = s->cur_pic_ptr->f->linesize[1];
+    uvlinesize = s->cur_pic.ptr->f->linesize[1];
 
     uvmx = (tx + ((tx & 3) == 3)) >> 1;
     uvmy = (ty + ((ty & 3) == 3)) >> 1;
@@ -708,14 +708,14 @@  void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
             srcV = s->last_pic.data[2];
             lutuv = v->last_lutuv;
             use_ic = v->last_use_ic;
-            interlace = !!(s->last_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+            interlace = s->last_pic.ptr->interlaced;
         }
     } else {
         srcU = s->next_pic.data[1];
         srcV = s->next_pic.data[2];
         lutuv = v->next_lutuv;
         use_ic = v->next_use_ic;
-        interlace = !!(s->next_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+        interlace = s->next_pic.ptr->interlaced;
     }
 
     if (!srcU) {
@@ -856,7 +856,7 @@  void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
     if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
         return;
 
-    uvlinesize = s->cur_pic_ptr->f->linesize[1];
+    uvlinesize = s->cur_pic.ptr->f->linesize[1];
 
     for (i = 0; i < 4; i++) {
         int d = i < 2 ? dir: dir2;
@@ -884,13 +884,13 @@  void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
             srcV = s->next_pic.data[2];
             lutuv  = v->next_lutuv;
             use_ic = v->next_use_ic;
-            interlace = !!(s->next_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+            interlace = s->next_pic.ptr->interlaced;
         } else {
             srcU = s->last_pic.data[1];
             srcV = s->last_pic.data[2];
             lutuv  = v->last_lutuv;
             use_ic = v->last_use_ic;
-            interlace = !!(s->last_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+            interlace = s->last_pic.ptr->interlaced;
         }
         if (!srcU)
             return;
@@ -1015,8 +1015,8 @@  void ff_vc1_interp_mc(VC1Context *v)
     if (!v->field_mode && !v->s.next_pic.data[0])
         return;
 
-    linesize   = s->cur_pic_ptr->f->linesize[0];
-    uvlinesize = s->cur_pic_ptr->f->linesize[1];
+    linesize   = s->cur_pic.ptr->f->linesize[0];
+    uvlinesize = s->cur_pic.ptr->f->linesize[1];
 
     mx   = s->mv[1][0][0];
     my   = s->mv[1][0][1];
@@ -1034,7 +1034,7 @@  void ff_vc1_interp_mc(VC1Context *v)
     srcU = s->next_pic.data[1];
     srcV = s->next_pic.data[2];
 
-    interlace = !!(s->next_pic.f->flags & AV_FRAME_FLAG_INTERLACED);
+    interlace = s->next_pic.ptr->interlaced;
 
     src_x   = s->mb_x * 16 + (mx   >> 2);
     src_y   = s->mb_y * 16 + (my   >> 2);
diff --git a/libavcodec/vc1_pred.c b/libavcodec/vc1_pred.c
index 9141290d26..6e260fa053 100644
--- a/libavcodec/vc1_pred.c
+++ b/libavcodec/vc1_pred.c
@@ -719,7 +719,7 @@  void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2],
         s->cur_pic.motion_val[1][xy][1] = 0;
         return;
     }
-        if (direct && s->next_pic_ptr->field_picture)
+        if (direct && s->next_pic.ptr->field_picture)
             av_log(s->avctx, AV_LOG_WARNING, "Mixed frame/field direct mode not supported\n");
 
         s->mv[0][0][0] = scale_mv(s->next_pic.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample);
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 71fda305da..9bbd5cecf6 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -322,7 +322,7 @@  static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb)
         return AVERROR_UNKNOWN;
     }
 
-    if (v->two_sprites && (!s->last_pic_ptr || !s->last_pic.data[0])) {
+    if (v->two_sprites && (!s->last_pic.ptr || !s->last_pic.data[0])) {
         av_log(avctx, AV_LOG_WARNING, "Need two sprites, only got one\n");
         v->two_sprites = 0;
     }
@@ -340,7 +340,7 @@  static void vc1_sprite_flush(AVCodecContext *avctx)
 {
     VC1Context *v     = avctx->priv_data;
     MpegEncContext *s = &v->s;
-    MPVPicture *f = &s->cur_pic;
+    MPVWorkPicture *f = &s->cur_pic;
     int plane, i;
 
     /* Windows Media Image codecs have a convergence interval of two keyframes.
@@ -837,10 +837,10 @@  static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     /* no supplementary picture */
     if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) {
         /* special case for last picture */
-        if (s->low_delay == 0 && s->next_pic_ptr) {
-            if ((ret = av_frame_ref(pict, s->next_pic_ptr->f)) < 0)
+        if (s->low_delay == 0 && s->next_pic.ptr) {
+            if ((ret = av_frame_ref(pict, s->next_pic.ptr->f)) < 0)
                 return ret;
-            s->next_pic_ptr = NULL;
+            s->next_pic.ptr = NULL;
 
             *got_frame = 1;
         }
@@ -1047,7 +1047,7 @@  static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     }
 
     /* skip B-frames if we don't have reference frames */
-    if (!s->last_pic_ptr && s->pict_type == AV_PICTURE_TYPE_B) {
+    if (!s->last_pic.ptr && s->pict_type == AV_PICTURE_TYPE_B) {
         av_log(v->s.avctx, AV_LOG_DEBUG, "Skipping B frame without reference frames\n");
         goto end;
     }
@@ -1061,19 +1061,20 @@  static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict,
         goto err;
     }
 
-    v->s.cur_pic_ptr->field_picture = v->field_mode;
-    v->s.cur_pic_ptr->f->flags |= AV_FRAME_FLAG_INTERLACED * (v->fcm != PROGRESSIVE);
-    v->s.cur_pic_ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !!v->tff;
+    v->s.cur_pic.ptr->field_picture = v->field_mode;
+    v->s.cur_pic.ptr->f->flags |= AV_FRAME_FLAG_INTERLACED * (v->fcm != PROGRESSIVE);
+    v->s.cur_pic.ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !!v->tff;
+    v->s.cur_pic.ptr->interlaced = v->fcm != PROGRESSIVE;
 
     // process pulldown flags
-    s->cur_pic_ptr->f->repeat_pict = 0;
+    s->cur_pic.ptr->f->repeat_pict = 0;
     // Pulldown flags are only valid when 'broadcast' has been set.
     if (v->rff) {
         // repeat field
-        s->cur_pic_ptr->f->repeat_pict = 1;
+        s->cur_pic.ptr->f->repeat_pict = 1;
     } else if (v->rptfrm) {
         // repeat frames
-        s->cur_pic_ptr->f->repeat_pict = v->rptfrm * 2;
+        s->cur_pic.ptr->f->repeat_pict = v->rptfrm * 2;
     }
 
     if (avctx->hwaccel) {
@@ -1135,7 +1136,7 @@  static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict,
                 ret = AVERROR_INVALIDDATA;
                 goto err;
             }
-            v->s.cur_pic_ptr->f->pict_type = v->s.pict_type;
+            v->s.cur_pic.ptr->f->pict_type = v->s.pict_type;
 
             ret = hwaccel->start_frame(avctx, buf_start_second_field,
                                        (buf + buf_size) - buf_start_second_field);
@@ -1353,16 +1354,16 @@  image:
         *got_frame = 1;
     } else {
         if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
-            if ((ret = av_frame_ref(pict, s->cur_pic_ptr->f)) < 0)
+            if ((ret = av_frame_ref(pict, s->cur_pic.ptr->f)) < 0)
                 goto err;
             if (!v->field_mode)
-                ff_print_debug_info(s, s->cur_pic_ptr, pict);
+                ff_print_debug_info(s, s->cur_pic.ptr, pict);
             *got_frame = 1;
-        } else if (s->last_pic_ptr) {
-            if ((ret = av_frame_ref(pict, s->last_pic_ptr->f)) < 0)
+        } else if (s->last_pic.ptr) {
+            if ((ret = av_frame_ref(pict, s->last_pic.ptr->f)) < 0)
                 goto err;
             if (!v->field_mode)
-                ff_print_debug_info(s, s->last_pic_ptr, pict);
+                ff_print_debug_info(s, s->last_pic.ptr, pict);
             *got_frame = 1;
         }
     }
diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c
index f46bfa2bdf..0dd5641603 100644
--- a/libavcodec/vdpau.c
+++ b/libavcodec/vdpau.c
@@ -370,7 +370,7 @@  int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
 int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
-    MPVPicture *pic = s->cur_pic_ptr;
+    MPVPicture *pic = s->cur_pic.ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     int val;
 
diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c
index abd8cb19af..1ce0bfaa07 100644
--- a/libavcodec/vdpau_mpeg12.c
+++ b/libavcodec/vdpau_mpeg12.c
@@ -35,7 +35,7 @@  static int vdpau_mpeg_start_frame(AVCodecContext *avctx,
                                   const uint8_t *buffer, uint32_t size)
 {
     MpegEncContext * const s = avctx->priv_data;
-    MPVPicture *pic          = s->cur_pic_ptr;
+    MPVPicture *pic          = s->cur_pic.ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     VdpPictureInfoMPEG1Or2 *info = &pic_ctx->info.mpeg;
     VdpVideoSurface ref;
@@ -47,12 +47,12 @@  static int vdpau_mpeg_start_frame(AVCodecContext *avctx,
 
     switch (s->pict_type) {
     case AV_PICTURE_TYPE_B:
-        ref = ff_vdpau_get_surface_id(s->next_pic.f);
+        ref = ff_vdpau_get_surface_id(s->next_pic.ptr->f);
         assert(ref != VDP_INVALID_HANDLE);
         info->backward_reference = ref;
         /* fall through to forward prediction */
     case AV_PICTURE_TYPE_P:
-        ref = ff_vdpau_get_surface_id(s->last_pic.f);
+        ref = ff_vdpau_get_surface_id(s->last_pic.ptr->f);
         info->forward_reference  = ref;
     }
 
@@ -87,7 +87,7 @@  static int vdpau_mpeg_decode_slice(AVCodecContext *avctx,
                                    const uint8_t *buffer, uint32_t size)
 {
     MpegEncContext * const s = avctx->priv_data;
-    MPVPicture *pic          = s->cur_pic_ptr;
+    MPVPicture *pic          = s->cur_pic.ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     int val;
 
diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c
index e2766835f6..40af8655cc 100644
--- a/libavcodec/vdpau_mpeg4.c
+++ b/libavcodec/vdpau_mpeg4.c
@@ -34,7 +34,7 @@  static int vdpau_mpeg4_start_frame(AVCodecContext *avctx,
 {
     Mpeg4DecContext *ctx = avctx->priv_data;
     MpegEncContext * const s = &ctx->m;
-    MPVPicture *pic          = s->cur_pic_ptr;
+    MPVPicture *pic          = s->cur_pic.ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     VdpPictureInfoMPEG4Part2 *info = &pic_ctx->info.mpeg4;
     VdpVideoSurface ref;
@@ -47,13 +47,13 @@  static int vdpau_mpeg4_start_frame(AVCodecContext *avctx,
 
     switch (s->pict_type) {
     case AV_PICTURE_TYPE_B:
-        ref = ff_vdpau_get_surface_id(s->next_pic.f);
+        ref = ff_vdpau_get_surface_id(s->next_pic.ptr->f);
         assert(ref != VDP_INVALID_HANDLE);
         info->backward_reference = ref;
         info->vop_coding_type    = 2;
         /* fall-through */
     case AV_PICTURE_TYPE_P:
-        ref = ff_vdpau_get_surface_id(s->last_pic.f);
+        ref = ff_vdpau_get_surface_id(s->last_pic.ptr->f);
         assert(ref != VDP_INVALID_HANDLE);
         info->forward_reference  = ref;
     }
diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c
index 9ed1665cad..d02a454bb8 100644
--- a/libavcodec/vdpau_vc1.c
+++ b/libavcodec/vdpau_vc1.c
@@ -36,7 +36,7 @@  static int vdpau_vc1_start_frame(AVCodecContext *avctx,
 {
     VC1Context * const v  = avctx->priv_data;
     MpegEncContext * const s = &v->s;
-    MPVPicture *pic          = s->cur_pic_ptr;
+    MPVPicture *pic          = s->cur_pic.ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     VdpPictureInfoVC1 *info = &pic_ctx->info.vc1;
     VdpVideoSurface ref;
@@ -47,15 +47,15 @@  static int vdpau_vc1_start_frame(AVCodecContext *avctx,
 
     switch (s->pict_type) {
     case AV_PICTURE_TYPE_B:
-        if (s->next_pic_ptr) {
-            ref = ff_vdpau_get_surface_id(s->next_pic.f);
+        if (s->next_pic.ptr) {
+            ref = ff_vdpau_get_surface_id(s->next_pic.ptr->f);
             assert(ref != VDP_INVALID_HANDLE);
             info->backward_reference = ref;
         }
         /* fall-through */
     case AV_PICTURE_TYPE_P:
-        if (s->last_pic_ptr) {
-            ref = ff_vdpau_get_surface_id(s->last_pic.f);
+        if (s->last_pic.ptr) {
+            ref = ff_vdpau_get_surface_id(s->last_pic.ptr->f);
             assert(ref != VDP_INVALID_HANDLE);
             info->forward_reference  = ref;
         }
@@ -104,7 +104,7 @@  static int vdpau_vc1_decode_slice(AVCodecContext *avctx,
 {
     VC1Context * const v  = avctx->priv_data;
     MpegEncContext * const s = &v->s;
-    MPVPicture *pic          = s->cur_pic_ptr;
+    MPVPicture *pic          = s->cur_pic.ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     int val;
 
diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
index 7807047aa6..a8ea8ff7ff 100644
--- a/libavcodec/videotoolbox.c
+++ b/libavcodec/videotoolbox.c
@@ -1108,7 +1108,7 @@  static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx,
 static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
-    AVFrame *frame = s->cur_pic_ptr->f;
+    AVFrame *frame = s->cur_pic.ptr->f;
 
     return ff_videotoolbox_common_end_frame(avctx, frame);
 }
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 432d6f7223..bb3829dcd6 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -330,7 +330,7 @@  int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s)
     s->esc3_run_length   = 0;
 
     if (w->j_type) {
-        ff_intrax8_decode_picture(&w->x8, &s->cur_pic,
+        ff_intrax8_decode_picture(&w->x8, s->cur_pic.ptr,
                                   &s->gb, &s->mb_x, &s->mb_y,
                                   2 * s->qscale, (s->qscale - 1) | 1,
                                   s->loop_filter, s->low_delay);