1/* 2 * innoHeim/Rsupport Screen Capture Codec 3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com> 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * innoHeim/Rsupport Screen Capture Codec decoder 25 * 26 * Fourcc: ISCC, RSCC 27 * 28 * Lossless codec, data stored in tiles, with optional deflate compression. 29 * 30 * Header contains the number of tiles in a frame with the tile coordinates, 31 * and it can be deflated or not. Similarly, pixel data comes after the header 32 * and a variable size value, and it can be deflated or just raw. 33 * 34 * Supports: PAL8, BGRA, BGR24, RGB555 35 */ 36 37#include <stdint.h> 38#include <string.h> 39#include <zlib.h> 40 41#include "libavutil/imgutils.h" 42#include "libavutil/internal.h" 43 44#include "avcodec.h" 45#include "bytestream.h" 46#include "codec_internal.h" 47#include "decode.h" 48#include "internal.h" 49 50#define TILE_SIZE 8 51 52typedef struct Tile { 53 int x, y; 54 int w, h; 55} Tile; 56 57typedef struct RsccContext { 58 GetByteContext gbc; 59 AVFrame *reference; 60 Tile *tiles; 61 unsigned int tiles_size; 62 int component_size; 63 64 uint8_t palette[AVPALETTE_SIZE]; 65 66 /* zlib interaction */ 67 uint8_t *inflated_buf; 68 uLongf inflated_size; 69 int valid_pixels; 70} RsccContext; 71 72static av_cold int rscc_init(AVCodecContext *avctx) 73{ 74 RsccContext *ctx = avctx->priv_data; 75 76 /* These needs to be set to estimate uncompressed buffer */ 77 int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); 78 if (ret < 0) { 79 av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", 80 avctx->width, avctx->height); 81 return ret; 82 } 83 84 /* Allocate reference frame */ 85 ctx->reference = av_frame_alloc(); 86 if (!ctx->reference) 87 return AVERROR(ENOMEM); 88 89 /* Get pixel format and the size of the pixel */ 90 if (avctx->codec_tag == MKTAG('I', 'S', 'C', 'C')) { 91 if (avctx->extradata && avctx->extradata_size == 4) { 92 if ((avctx->extradata[0] >> 1) & 1) { 93 avctx->pix_fmt = AV_PIX_FMT_BGRA; 94 ctx->component_size = 4; 95 } else { 96 avctx->pix_fmt = AV_PIX_FMT_BGR24; 97 ctx->component_size = 3; 98 } 99 } else { 100 avctx->pix_fmt = AV_PIX_FMT_BGRA; 101 ctx->component_size = 4; 102 } 103 } else if (avctx->codec_tag == MKTAG('R', 'S', 'C', 'C')) { 104 ctx->component_size = avctx->bits_per_coded_sample / 8; 105 switch (avctx->bits_per_coded_sample) { 106 case 8: 107 avctx->pix_fmt = AV_PIX_FMT_PAL8; 108 break; 109 case 16: 110 avctx->pix_fmt = AV_PIX_FMT_RGB555LE; 111 break; 112 case 24: 113 avctx->pix_fmt = AV_PIX_FMT_BGR24; 114 break; 115 case 32: 116 avctx->pix_fmt = AV_PIX_FMT_BGR0; 117 break; 118 default: 119 av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n", 120 avctx->bits_per_coded_sample); 121 return AVERROR_INVALIDDATA; 122 } 123 } else { 124 avctx->pix_fmt = AV_PIX_FMT_BGR0; 125 ctx->component_size = 4; 126 av_log(avctx, AV_LOG_WARNING, "Invalid codec tag\n"); 127 } 128 129 /* Store the value to check for keyframes */ 130 ctx->inflated_size = avctx->width * avctx->height * ctx->component_size; 131 132 /* Allocate maximum size possible, a full frame */ 133 ctx->inflated_buf = av_malloc(ctx->inflated_size); 134 if (!ctx->inflated_buf) 135 return AVERROR(ENOMEM); 136 137 return 0; 138} 139 140static av_cold int rscc_close(AVCodecContext *avctx) 141{ 142 RsccContext *ctx = avctx->priv_data; 143 144 av_freep(&ctx->tiles); 145 av_freep(&ctx->inflated_buf); 146 av_frame_free(&ctx->reference); 147 148 return 0; 149} 150 151static int rscc_decode_frame(AVCodecContext *avctx, AVFrame *frame, 152 int *got_frame, AVPacket *avpkt) 153{ 154 RsccContext *ctx = avctx->priv_data; 155 GetByteContext *gbc = &ctx->gbc; 156 GetByteContext tiles_gbc; 157 const uint8_t *pixels, *raw; 158 uint8_t *inflated_tiles = NULL; 159 int tiles_nb, packed_size, pixel_size = 0; 160 int i, ret = 0; 161 162 bytestream2_init(gbc, avpkt->data, avpkt->size); 163 164 /* Size check */ 165 if (bytestream2_get_bytes_left(gbc) < 12) { 166 av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size); 167 return AVERROR_INVALIDDATA; 168 } 169 170 /* Read number of tiles, and allocate the array */ 171 tiles_nb = bytestream2_get_le16(gbc); 172 173 if (tiles_nb == 0) { 174 av_log(avctx, AV_LOG_DEBUG, "no tiles\n"); 175 return avpkt->size; 176 } 177 178 av_fast_malloc(&ctx->tiles, &ctx->tiles_size, 179 tiles_nb * sizeof(*ctx->tiles)); 180 if (!ctx->tiles) { 181 ret = AVERROR(ENOMEM); 182 goto end; 183 } 184 185 av_log(avctx, AV_LOG_DEBUG, "Frame with %d tiles.\n", tiles_nb); 186 187 /* When there are more than 5 tiles, they are packed together with 188 * a size header. When that size does not match the number of tiles 189 * times the tile size, it means it needs to be inflated as well */ 190 if (tiles_nb > 5) { 191 uLongf packed_tiles_size; 192 193 if (tiles_nb < 32) 194 packed_tiles_size = bytestream2_get_byte(gbc); 195 else 196 packed_tiles_size = bytestream2_get_le16(gbc); 197 198 ff_dlog(avctx, "packed tiles of size %lu.\n", packed_tiles_size); 199 200 /* If necessary, uncompress tiles, and hijack the bytestream reader */ 201 if (packed_tiles_size != tiles_nb * TILE_SIZE) { 202 uLongf length = tiles_nb * TILE_SIZE; 203 204 if (bytestream2_get_bytes_left(gbc) < packed_tiles_size) { 205 ret = AVERROR_INVALIDDATA; 206 goto end; 207 } 208 209 inflated_tiles = av_malloc(length); 210 if (!inflated_tiles) { 211 ret = AVERROR(ENOMEM); 212 goto end; 213 } 214 215 ret = uncompress(inflated_tiles, &length, 216 gbc->buffer, packed_tiles_size); 217 if (ret) { 218 av_log(avctx, AV_LOG_ERROR, "Tile deflate error %d.\n", ret); 219 ret = AVERROR_UNKNOWN; 220 goto end; 221 } 222 223 /* Skip the compressed tile section in the main byte reader, 224 * and point it to read the newly uncompressed data */ 225 bytestream2_skip(gbc, packed_tiles_size); 226 bytestream2_init(&tiles_gbc, inflated_tiles, length); 227 gbc = &tiles_gbc; 228 } 229 } 230 231 /* Fill in array of tiles, keeping track of how many pixels are updated */ 232 for (i = 0; i < tiles_nb; i++) { 233 ctx->tiles[i].x = bytestream2_get_le16(gbc); 234 ctx->tiles[i].w = bytestream2_get_le16(gbc); 235 ctx->tiles[i].y = bytestream2_get_le16(gbc); 236 ctx->tiles[i].h = bytestream2_get_le16(gbc); 237 238 if (pixel_size + ctx->tiles[i].w * (int64_t)ctx->tiles[i].h * ctx->component_size > INT_MAX) { 239 av_log(avctx, AV_LOG_ERROR, "Invalid tile dimensions\n"); 240 ret = AVERROR_INVALIDDATA; 241 goto end; 242 } 243 244 pixel_size += ctx->tiles[i].w * ctx->tiles[i].h * ctx->component_size; 245 246 ff_dlog(avctx, "tile %d orig(%d,%d) %dx%d.\n", i, 247 ctx->tiles[i].x, ctx->tiles[i].y, 248 ctx->tiles[i].w, ctx->tiles[i].h); 249 250 if (ctx->tiles[i].w == 0 || ctx->tiles[i].h == 0) { 251 av_log(avctx, AV_LOG_ERROR, 252 "invalid tile %d at (%d.%d) with size %dx%d.\n", i, 253 ctx->tiles[i].x, ctx->tiles[i].y, 254 ctx->tiles[i].w, ctx->tiles[i].h); 255 ret = AVERROR_INVALIDDATA; 256 goto end; 257 } else if (ctx->tiles[i].x + ctx->tiles[i].w > avctx->width || 258 ctx->tiles[i].y + ctx->tiles[i].h > avctx->height) { 259 av_log(avctx, AV_LOG_ERROR, 260 "out of bounds tile %d at (%d.%d) with size %dx%d.\n", i, 261 ctx->tiles[i].x, ctx->tiles[i].y, 262 ctx->tiles[i].w, ctx->tiles[i].h); 263 ret = AVERROR_INVALIDDATA; 264 goto end; 265 } 266 } 267 268 /* Reset the reader in case it had been modified before */ 269 gbc = &ctx->gbc; 270 271 /* Extract how much pixel data the tiles contain */ 272 if (pixel_size < 0x100) 273 packed_size = bytestream2_get_byte(gbc); 274 else if (pixel_size < 0x10000) 275 packed_size = bytestream2_get_le16(gbc); 276 else if (pixel_size < 0x1000000) 277 packed_size = bytestream2_get_le24(gbc); 278 else 279 packed_size = bytestream2_get_le32(gbc); 280 281 ff_dlog(avctx, "pixel_size %d packed_size %d.\n", pixel_size, packed_size); 282 283 if (packed_size < 0) { 284 av_log(avctx, AV_LOG_ERROR, "Invalid tile size %d\n", packed_size); 285 ret = AVERROR_INVALIDDATA; 286 goto end; 287 } 288 289 /* Get pixels buffer, it may be deflated or just raw */ 290 if (pixel_size == packed_size) { 291 if (bytestream2_get_bytes_left(gbc) < pixel_size) { 292 av_log(avctx, AV_LOG_ERROR, "Insufficient input for %d\n", pixel_size); 293 ret = AVERROR_INVALIDDATA; 294 goto end; 295 } 296 pixels = gbc->buffer; 297 } else { 298 uLongf len = ctx->inflated_size; 299 if (bytestream2_get_bytes_left(gbc) < packed_size) { 300 av_log(avctx, AV_LOG_ERROR, "Insufficient input for %d\n", packed_size); 301 ret = AVERROR_INVALIDDATA; 302 goto end; 303 } 304 if (ctx->inflated_size < pixel_size) { 305 ret = AVERROR_INVALIDDATA; 306 goto end; 307 } 308 ret = uncompress(ctx->inflated_buf, &len, gbc->buffer, packed_size); 309 if (ret) { 310 av_log(avctx, AV_LOG_ERROR, "Pixel deflate error %d.\n", ret); 311 ret = AVERROR_UNKNOWN; 312 goto end; 313 } 314 pixels = ctx->inflated_buf; 315 } 316 317 /* Allocate when needed */ 318 ret = ff_reget_buffer(avctx, ctx->reference, 0); 319 if (ret < 0) 320 goto end; 321 322 /* Pointer to actual pixels, will be updated when data is consumed */ 323 raw = pixels; 324 for (i = 0; i < tiles_nb; i++) { 325 uint8_t *dst = ctx->reference->data[0] + ctx->reference->linesize[0] * 326 (avctx->height - ctx->tiles[i].y - 1) + 327 ctx->tiles[i].x * ctx->component_size; 328 av_image_copy_plane(dst, -1 * ctx->reference->linesize[0], 329 raw, ctx->tiles[i].w * ctx->component_size, 330 ctx->tiles[i].w * ctx->component_size, 331 ctx->tiles[i].h); 332 raw += ctx->tiles[i].w * ctx->component_size * ctx->tiles[i].h; 333 } 334 335 /* Frame is ready to be output */ 336 ret = av_frame_ref(frame, ctx->reference); 337 if (ret < 0) 338 goto end; 339 340 /* Keyframe when the number of pixels updated matches the whole surface */ 341 if (pixel_size == ctx->inflated_size) { 342 frame->pict_type = AV_PICTURE_TYPE_I; 343 frame->key_frame = 1; 344 } else { 345 frame->pict_type = AV_PICTURE_TYPE_P; 346 } 347 348 /* Palette handling */ 349 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { 350 frame->palette_has_changed = ff_copy_palette(ctx->palette, avpkt, avctx); 351 memcpy(frame->data[1], ctx->palette, AVPALETTE_SIZE); 352 } 353 // We only return a picture when enough of it is undamaged, this avoids copying nearly broken frames around 354 if (ctx->valid_pixels < ctx->inflated_size) 355 ctx->valid_pixels += pixel_size; 356 if (ctx->valid_pixels >= ctx->inflated_size * (100 - avctx->discard_damaged_percentage) / 100) 357 *got_frame = 1; 358 359 ret = avpkt->size; 360end: 361 av_free(inflated_tiles); 362 return ret; 363} 364 365const FFCodec ff_rscc_decoder = { 366 .p.name = "rscc", 367 .p.long_name = NULL_IF_CONFIG_SMALL("innoHeim/Rsupport Screen Capture Codec"), 368 .p.type = AVMEDIA_TYPE_VIDEO, 369 .p.id = AV_CODEC_ID_RSCC, 370 .init = rscc_init, 371 FF_CODEC_DECODE_CB(rscc_decode_frame), 372 .close = rscc_close, 373 .priv_data_size = sizeof(RsccContext), 374 .p.capabilities = AV_CODEC_CAP_DR1, 375 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | 376 FF_CODEC_CAP_INIT_CLEANUP, 377}; 378