[FFmpeg-devel] avcodec/wcmv: use ff_reget_buffer()

Submitted by James Almer on Aug. 29, 2019, 10:26 p.m.

Details

Message ID 20190829222657.10931-1-jamrial@gmail.com
State New
Headers show

Commit Message

James Almer Aug. 29, 2019, 10:26 p.m.
Signed-off-by: James Almer <jamrial@gmail.com>
---
Untested. There doesn't seem to be a fate test, and i have no samples
at hand.

 libavcodec/wcmv.c | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

Comments

Paul B Mahol Aug. 30, 2019, 6:26 a.m.
It still exits early when no blocks are encoded.

On 8/30/19, James Almer <jamrial@gmail.com> wrote:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> Untested. There doesn't seem to be a fate test, and i have no samples
> at hand.
>
>  libavcodec/wcmv.c | 23 +++++++++--------------
>  1 file changed, 9 insertions(+), 14 deletions(-)
>
> diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
> index 0d60b9fe1f..68142b45fd 100644
> --- a/libavcodec/wcmv.c
> +++ b/libavcodec/wcmv.c
> @@ -60,7 +60,7 @@ static int decode_frame(AVCodecContext *avctx,
>      if (!blocks)
>          return avpkt->size;
>
> -    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
> +    if ((ret = ff_reget_buffer(avctx, s->prev_frame)) < 0)
>          return ret;
>
>      if (blocks > 5) {
> @@ -157,13 +157,9 @@ static int decode_frame(AVCodecContext *avctx,
>      if (bytestream2_get_bytes_left(&gb) < 8LL * blocks)
>          return AVERROR_INVALIDDATA;
>
> -    if (s->prev_frame->data[0]) {
> -        ret = av_frame_copy(frame, s->prev_frame);
> -        if (ret < 0)
> -            return ret;
> -    } else {
> -        ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 };
> -        av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0,
> +    if (!avctx->frame_number) {
> +        ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 };
> +        av_image_fill_black(s->prev_frame->data, linesize, avctx->pix_fmt,
> 0,
>                              avctx->width, avctx->height);
>      }
>
> @@ -184,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx,
>          if (w > avctx->width || h > avctx->height)
>              return AVERROR_INVALIDDATA;
>
> -        dst = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0]
> + x * bpp;
> +        dst = s->prev_frame->data[0] + (avctx->height - y - 1) *
> s->prev_frame->linesize[0] + x * bpp;
>          for (int i = 0; i < h; i++) {
>              s->zstream.next_out  = dst;
>              s->zstream.avail_out = w * bpp;
> @@ -196,15 +192,14 @@ static int decode_frame(AVCodecContext *avctx,
>                  return AVERROR_INVALIDDATA;
>              }
>
> -            dst -= frame->linesize[0];
> +            dst -= s->prev_frame->linesize[0];
>          }
>      }
>
> -    frame->key_frame = intra;
> -    frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
> +    s->prev_frame->key_frame = intra;
> +    s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I :
> AV_PICTURE_TYPE_P;
>
> -    av_frame_unref(s->prev_frame);
> -    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
> +    if ((ret = av_frame_ref(frame, s->prev_frame)) < 0)
>          return ret;
>
>      *got_frame = 1;
> --
> 2.22.0
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Paul B Mahol Aug. 30, 2019, 6:45 a.m.
Here is sample: https://0x0.st/z49v.avi

On 8/30/19, Paul B Mahol <onemda@gmail.com> wrote:
> It still exits early when no blocks are encoded.
>
> On 8/30/19, James Almer <jamrial@gmail.com> wrote:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>> Untested. There doesn't seem to be a fate test, and i have no samples
>> at hand.
>>
>>  libavcodec/wcmv.c | 23 +++++++++--------------
>>  1 file changed, 9 insertions(+), 14 deletions(-)
>>
>> diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
>> index 0d60b9fe1f..68142b45fd 100644
>> --- a/libavcodec/wcmv.c
>> +++ b/libavcodec/wcmv.c
>> @@ -60,7 +60,7 @@ static int decode_frame(AVCodecContext *avctx,
>>      if (!blocks)
>>          return avpkt->size;
>>
>> -    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
>> +    if ((ret = ff_reget_buffer(avctx, s->prev_frame)) < 0)
>>          return ret;
>>
>>      if (blocks > 5) {
>> @@ -157,13 +157,9 @@ static int decode_frame(AVCodecContext *avctx,
>>      if (bytestream2_get_bytes_left(&gb) < 8LL * blocks)
>>          return AVERROR_INVALIDDATA;
>>
>> -    if (s->prev_frame->data[0]) {
>> -        ret = av_frame_copy(frame, s->prev_frame);
>> -        if (ret < 0)
>> -            return ret;
>> -    } else {
>> -        ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 };
>> -        av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0,
>> +    if (!avctx->frame_number) {
>> +        ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 };
>> +        av_image_fill_black(s->prev_frame->data, linesize,
>> avctx->pix_fmt,
>> 0,
>>                              avctx->width, avctx->height);
>>      }
>>
>> @@ -184,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx,
>>          if (w > avctx->width || h > avctx->height)
>>              return AVERROR_INVALIDDATA;
>>
>> -        dst = frame->data[0] + (avctx->height - y - 1) *
>> frame->linesize[0]
>> + x * bpp;
>> +        dst = s->prev_frame->data[0] + (avctx->height - y - 1) *
>> s->prev_frame->linesize[0] + x * bpp;
>>          for (int i = 0; i < h; i++) {
>>              s->zstream.next_out  = dst;
>>              s->zstream.avail_out = w * bpp;
>> @@ -196,15 +192,14 @@ static int decode_frame(AVCodecContext *avctx,
>>                  return AVERROR_INVALIDDATA;
>>              }
>>
>> -            dst -= frame->linesize[0];
>> +            dst -= s->prev_frame->linesize[0];
>>          }
>>      }
>>
>> -    frame->key_frame = intra;
>> -    frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
>> +    s->prev_frame->key_frame = intra;
>> +    s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I :
>> AV_PICTURE_TYPE_P;
>>
>> -    av_frame_unref(s->prev_frame);
>> -    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
>> +    if ((ret = av_frame_ref(frame, s->prev_frame)) < 0)
>>          return ret;
>>
>>      *got_frame = 1;
>> --
>> 2.22.0
>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
James Almer Aug. 30, 2019, 1:52 p.m.
On 8/30/2019 3:26 AM, Paul B Mahol wrote:
> It still exits early when no blocks are encoded.

That's unrelated to this patch. I can look into reverting 976dae8b32 and
preventing data copying when the frame doesn't change in a separate
patchset.

> 
> On 8/30/19, James Almer <jamrial@gmail.com> wrote:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>> Untested. There doesn't seem to be a fate test, and i have no samples
>> at hand.
>>
>>  libavcodec/wcmv.c | 23 +++++++++--------------
>>  1 file changed, 9 insertions(+), 14 deletions(-)
>>
>> diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
>> index 0d60b9fe1f..68142b45fd 100644
>> --- a/libavcodec/wcmv.c
>> +++ b/libavcodec/wcmv.c
>> @@ -60,7 +60,7 @@ static int decode_frame(AVCodecContext *avctx,
>>      if (!blocks)
>>          return avpkt->size;
>>
>> -    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
>> +    if ((ret = ff_reget_buffer(avctx, s->prev_frame)) < 0)
>>          return ret;
>>
>>      if (blocks > 5) {
>> @@ -157,13 +157,9 @@ static int decode_frame(AVCodecContext *avctx,
>>      if (bytestream2_get_bytes_left(&gb) < 8LL * blocks)
>>          return AVERROR_INVALIDDATA;
>>
>> -    if (s->prev_frame->data[0]) {
>> -        ret = av_frame_copy(frame, s->prev_frame);
>> -        if (ret < 0)
>> -            return ret;
>> -    } else {
>> -        ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 };
>> -        av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0,
>> +    if (!avctx->frame_number) {
>> +        ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 };
>> +        av_image_fill_black(s->prev_frame->data, linesize, avctx->pix_fmt,
>> 0,
>>                              avctx->width, avctx->height);
>>      }
>>
>> @@ -184,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx,
>>          if (w > avctx->width || h > avctx->height)
>>              return AVERROR_INVALIDDATA;
>>
>> -        dst = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0]
>> + x * bpp;
>> +        dst = s->prev_frame->data[0] + (avctx->height - y - 1) *
>> s->prev_frame->linesize[0] + x * bpp;
>>          for (int i = 0; i < h; i++) {
>>              s->zstream.next_out  = dst;
>>              s->zstream.avail_out = w * bpp;
>> @@ -196,15 +192,14 @@ static int decode_frame(AVCodecContext *avctx,
>>                  return AVERROR_INVALIDDATA;
>>              }
>>
>> -            dst -= frame->linesize[0];
>> +            dst -= s->prev_frame->linesize[0];
>>          }
>>      }
>>
>> -    frame->key_frame = intra;
>> -    frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
>> +    s->prev_frame->key_frame = intra;
>> +    s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I :
>> AV_PICTURE_TYPE_P;
>>
>> -    av_frame_unref(s->prev_frame);
>> -    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
>> +    if ((ret = av_frame_ref(frame, s->prev_frame)) < 0)
>>          return ret;
>>
>>      *got_frame = 1;
>> --
>> 2.22.0
>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
James Almer Aug. 30, 2019, 1:56 p.m.
On 8/30/2019 3:45 AM, Paul B Mahol wrote:
> Here is sample: https://0x0.st/z49v.avi

Thanks. Can you make a fate test for it?

> 
> On 8/30/19, Paul B Mahol <onemda@gmail.com> wrote:
>> It still exits early when no blocks are encoded.
>>
>> On 8/30/19, James Almer <jamrial@gmail.com> wrote:
>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>> ---
>>> Untested. There doesn't seem to be a fate test, and i have no samples
>>> at hand.
>>>
>>>  libavcodec/wcmv.c | 23 +++++++++--------------
>>>  1 file changed, 9 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
>>> index 0d60b9fe1f..68142b45fd 100644
>>> --- a/libavcodec/wcmv.c
>>> +++ b/libavcodec/wcmv.c
>>> @@ -60,7 +60,7 @@ static int decode_frame(AVCodecContext *avctx,
>>>      if (!blocks)
>>>          return avpkt->size;
>>>
>>> -    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
>>> +    if ((ret = ff_reget_buffer(avctx, s->prev_frame)) < 0)
>>>          return ret;
>>>
>>>      if (blocks > 5) {
>>> @@ -157,13 +157,9 @@ static int decode_frame(AVCodecContext *avctx,
>>>      if (bytestream2_get_bytes_left(&gb) < 8LL * blocks)
>>>          return AVERROR_INVALIDDATA;
>>>
>>> -    if (s->prev_frame->data[0]) {
>>> -        ret = av_frame_copy(frame, s->prev_frame);
>>> -        if (ret < 0)
>>> -            return ret;
>>> -    } else {
>>> -        ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 };
>>> -        av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0,
>>> +    if (!avctx->frame_number) {
>>> +        ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 };
>>> +        av_image_fill_black(s->prev_frame->data, linesize,
>>> avctx->pix_fmt,
>>> 0,
>>>                              avctx->width, avctx->height);
>>>      }
>>>
>>> @@ -184,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx,
>>>          if (w > avctx->width || h > avctx->height)
>>>              return AVERROR_INVALIDDATA;
>>>
>>> -        dst = frame->data[0] + (avctx->height - y - 1) *
>>> frame->linesize[0]
>>> + x * bpp;
>>> +        dst = s->prev_frame->data[0] + (avctx->height - y - 1) *
>>> s->prev_frame->linesize[0] + x * bpp;
>>>          for (int i = 0; i < h; i++) {
>>>              s->zstream.next_out  = dst;
>>>              s->zstream.avail_out = w * bpp;
>>> @@ -196,15 +192,14 @@ static int decode_frame(AVCodecContext *avctx,
>>>                  return AVERROR_INVALIDDATA;
>>>              }
>>>
>>> -            dst -= frame->linesize[0];
>>> +            dst -= s->prev_frame->linesize[0];
>>>          }
>>>      }
>>>
>>> -    frame->key_frame = intra;
>>> -    frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
>>> +    s->prev_frame->key_frame = intra;
>>> +    s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I :
>>> AV_PICTURE_TYPE_P;
>>>
>>> -    av_frame_unref(s->prev_frame);
>>> -    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
>>> +    if ((ret = av_frame_ref(frame, s->prev_frame)) < 0)
>>>          return ret;
>>>
>>>      *got_frame = 1;
>>> --
>>> 2.22.0
>>>
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>>> To unsubscribe, visit link above, or email
>>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
Paul B Mahol Aug. 30, 2019, 6:11 p.m.
On 8/30/19, James Almer <jamrial@gmail.com> wrote:
> On 8/30/2019 3:45 AM, Paul B Mahol wrote:
>> Here is sample: https://0x0.st/z49v.avi
>
> Thanks. Can you make a fate test for it?

Here is much smaller file.

https://0x0.st/z4f5.avi


>
>>
>> On 8/30/19, Paul B Mahol <onemda@gmail.com> wrote:
>>> It still exits early when no blocks are encoded.
>>>
>>> On 8/30/19, James Almer <jamrial@gmail.com> wrote:
>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>> ---
>>>> Untested. There doesn't seem to be a fate test, and i have no samples
>>>> at hand.
>>>>
>>>>  libavcodec/wcmv.c | 23 +++++++++--------------
>>>>  1 file changed, 9 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
>>>> index 0d60b9fe1f..68142b45fd 100644
>>>> --- a/libavcodec/wcmv.c
>>>> +++ b/libavcodec/wcmv.c
>>>> @@ -60,7 +60,7 @@ static int decode_frame(AVCodecContext *avctx,
>>>>      if (!blocks)
>>>>          return avpkt->size;
>>>>
>>>> -    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) <
>>>> 0)
>>>> +    if ((ret = ff_reget_buffer(avctx, s->prev_frame)) < 0)
>>>>          return ret;
>>>>
>>>>      if (blocks > 5) {
>>>> @@ -157,13 +157,9 @@ static int decode_frame(AVCodecContext *avctx,
>>>>      if (bytestream2_get_bytes_left(&gb) < 8LL * blocks)
>>>>          return AVERROR_INVALIDDATA;
>>>>
>>>> -    if (s->prev_frame->data[0]) {
>>>> -        ret = av_frame_copy(frame, s->prev_frame);
>>>> -        if (ret < 0)
>>>> -            return ret;
>>>> -    } else {
>>>> -        ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 };
>>>> -        av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0,
>>>> +    if (!avctx->frame_number) {
>>>> +        ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0
>>>> };
>>>> +        av_image_fill_black(s->prev_frame->data, linesize,
>>>> avctx->pix_fmt,
>>>> 0,
>>>>                              avctx->width, avctx->height);
>>>>      }
>>>>
>>>> @@ -184,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx,
>>>>          if (w > avctx->width || h > avctx->height)
>>>>              return AVERROR_INVALIDDATA;
>>>>
>>>> -        dst = frame->data[0] + (avctx->height - y - 1) *
>>>> frame->linesize[0]
>>>> + x * bpp;
>>>> +        dst = s->prev_frame->data[0] + (avctx->height - y - 1) *
>>>> s->prev_frame->linesize[0] + x * bpp;
>>>>          for (int i = 0; i < h; i++) {
>>>>              s->zstream.next_out  = dst;
>>>>              s->zstream.avail_out = w * bpp;
>>>> @@ -196,15 +192,14 @@ static int decode_frame(AVCodecContext *avctx,
>>>>                  return AVERROR_INVALIDDATA;
>>>>              }
>>>>
>>>> -            dst -= frame->linesize[0];
>>>> +            dst -= s->prev_frame->linesize[0];
>>>>          }
>>>>      }
>>>>
>>>> -    frame->key_frame = intra;
>>>> -    frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
>>>> +    s->prev_frame->key_frame = intra;
>>>> +    s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I :
>>>> AV_PICTURE_TYPE_P;
>>>>
>>>> -    av_frame_unref(s->prev_frame);
>>>> -    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
>>>> +    if ((ret = av_frame_ref(frame, s->prev_frame)) < 0)
>>>>          return ret;
>>>>
>>>>      *got_frame = 1;
>>>> --
>>>> 2.22.0
>>>>
>>>> _______________________________________________
>>>> ffmpeg-devel mailing list
>>>> ffmpeg-devel@ffmpeg.org
>>>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>>
>>>> To unsubscribe, visit link above, or email
>>>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
James Almer Sept. 4, 2019, 1:28 p.m.
On 8/30/2019 3:26 AM, Paul B Mahol wrote:
> It still exits early when no blocks are encoded.

Reverted that and pushed.

Patch hide | download patch | download mbox

diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
index 0d60b9fe1f..68142b45fd 100644
--- a/libavcodec/wcmv.c
+++ b/libavcodec/wcmv.c
@@ -60,7 +60,7 @@  static int decode_frame(AVCodecContext *avctx,
     if (!blocks)
         return avpkt->size;
 
-    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
+    if ((ret = ff_reget_buffer(avctx, s->prev_frame)) < 0)
         return ret;
 
     if (blocks > 5) {
@@ -157,13 +157,9 @@  static int decode_frame(AVCodecContext *avctx,
     if (bytestream2_get_bytes_left(&gb) < 8LL * blocks)
         return AVERROR_INVALIDDATA;
 
-    if (s->prev_frame->data[0]) {
-        ret = av_frame_copy(frame, s->prev_frame);
-        if (ret < 0)
-            return ret;
-    } else {
-        ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 };
-        av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0,
+    if (!avctx->frame_number) {
+        ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 };
+        av_image_fill_black(s->prev_frame->data, linesize, avctx->pix_fmt, 0,
                             avctx->width, avctx->height);
     }
 
@@ -184,7 +180,7 @@  static int decode_frame(AVCodecContext *avctx,
         if (w > avctx->width || h > avctx->height)
             return AVERROR_INVALIDDATA;
 
-        dst = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * bpp;
+        dst = s->prev_frame->data[0] + (avctx->height - y - 1) * s->prev_frame->linesize[0] + x * bpp;
         for (int i = 0; i < h; i++) {
             s->zstream.next_out  = dst;
             s->zstream.avail_out = w * bpp;
@@ -196,15 +192,14 @@  static int decode_frame(AVCodecContext *avctx,
                 return AVERROR_INVALIDDATA;
             }
 
-            dst -= frame->linesize[0];
+            dst -= s->prev_frame->linesize[0];
         }
     }
 
-    frame->key_frame = intra;
-    frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+    s->prev_frame->key_frame = intra;
+    s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
 
-    av_frame_unref(s->prev_frame);
-    if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
+    if ((ret = av_frame_ref(frame, s->prev_frame)) < 0)
         return ret;
 
     *got_frame = 1;