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; }