static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
                                     int *got_frame, AVPacket *avpkt)
{
    ScreenpressoContext *ctx = avctx->priv_data;
    AVFrame *frame = data;
    int keyframe;
    int ret;

    /* Size check */
    if (avpkt->size < 3) {
        av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size);
        return AVERROR_INVALIDDATA;
    }

    /* Basic sanity check, but not really harmful */
    if ((avpkt->data[0] != 0x73 && avpkt->data[0] != 0x72) ||
        avpkt->data[1] != 8) { // bpp probably
        av_log(avctx, AV_LOG_WARNING, "Unknown header 0x%02X%02X\n",
               avpkt->data[0], avpkt->data[1]);
    }
    keyframe = (avpkt->data[0] == 0x73);

    /* Resize deflate buffer and frame on resolution change */
    if (ctx->inflated_size != avctx->width * avctx->height * 3) {
        av_frame_unref(ctx->current);
        ret = ff_get_buffer(avctx, ctx->current, AV_GET_BUFFER_FLAG_REF);
        if (ret < 0)
            return ret;

        /* If malloc fails, reset len to avoid preserving an invalid value */
        ctx->inflated_size = avctx->width * avctx->height * 3;
        ret = av_reallocp(&ctx->inflated_buf, ctx->inflated_size);
        if (ret < 0) {
            ctx->inflated_size = 0;
            return ret;
        }
    }

    /* Inflate the frame after the 2 byte header */
    ret = uncompress(ctx->inflated_buf, &ctx->inflated_size,
                     avpkt->data + 2, avpkt->size - 2);
    if (ret) {
        av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
        return AVERROR_UNKNOWN;
    }

    /* When a keyframe is found, copy it (flipped) */
    if (keyframe)
        av_image_copy_plane(ctx->current->data[0] +
                            ctx->current->linesize[0] * (avctx->height - 1),
                            -1 * ctx->current->linesize[0],
                            ctx->inflated_buf, avctx->width * 3,
                            avctx->width * 3, avctx->height);
    /* Otherwise sum the delta on top of the current frame */
    else
        sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
                          ctx->inflated_buf, avctx->width * 3,
                          avctx->width * 3, avctx->height);

    /* Frame is ready to be output */
    ret = av_frame_ref(frame, ctx->current);
    if (ret < 0)
        return ret;

    /* Usual properties */
    if (keyframe) {
        frame->pict_type = AV_PICTURE_TYPE_I;
        frame->key_frame = 1;
    } else {
        frame->pict_type = AV_PICTURE_TYPE_P;
    }
    *got_frame = 1;

    return 0;
}