/** * Perform decode operation * @param dst pointer to destination image buffer * @param dst_end pointer to end of destination image buffer * @param gb GetByteContext (optional, see below) * @param pixel Fill color (optional, see below) * @param count Pixel count * @param x Pointer to x-axis counter * @param width Image width * @param linesize Destination image buffer linesize * @return non-zero if destination buffer is exhausted * * a copy operation is achieved when 'gb' is set * a fill operation is achieved when 'gb' is null and pixel is >= 0 * a skip operation is achieved when 'gb' is null and pixel is < 0 */ static inline int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize) { int remaining = width - *x; while(count > 0) { int striplen = FFMIN(count, remaining); if (gb) { if (bytestream2_get_bytes_left(gb) < striplen) goto exhausted; bytestream2_get_bufferu(gb, *dst, striplen); } else if (pixel >= 0) memset(*dst, pixel, striplen); *dst += striplen; remaining -= striplen; count -= striplen; if (remaining <= 0) { *dst += linesize - width; remaining = width; } if (linesize > 0) { if (*dst >= dst_end) goto exhausted; } else { if (*dst <= dst_end) goto exhausted; } } *x = width - remaining; return 0; exhausted: *x = width - remaining; return 1; }
static int gif_read_header1(GifState *s) { uint8_t sig[6]; int v, n; int background_color_index; if (bytestream2_get_bytes_left(&s->gb) < 13) return AVERROR_INVALIDDATA; /* read gif signature */ bytestream2_get_bufferu(&s->gb, sig, 6); if (memcmp(sig, gif87a_sig, 6) != 0 && memcmp(sig, gif89a_sig, 6) != 0) return AVERROR_INVALIDDATA; /* read screen header */ s->transparent_color_index = -1; s->screen_width = bytestream2_get_le16u(&s->gb); s->screen_height = bytestream2_get_le16u(&s->gb); if( (unsigned)s->screen_width > 32767 || (unsigned)s->screen_height > 32767){ av_log(s->avctx, AV_LOG_ERROR, "picture size too large\n"); return AVERROR_INVALIDDATA; } av_fast_malloc(&s->idx_line, &s->idx_line_size, s->screen_width); if (!s->idx_line) return AVERROR(ENOMEM); v = bytestream2_get_byteu(&s->gb); s->color_resolution = ((v & 0x70) >> 4) + 1; s->has_global_palette = (v & 0x80); s->bits_per_pixel = (v & 0x07) + 1; background_color_index = bytestream2_get_byteu(&s->gb); n = bytestream2_get_byteu(&s->gb); if (n) { s->avctx->sample_aspect_ratio.num = n + 15; s->avctx->sample_aspect_ratio.den = 64; } av_dlog(s->avctx, "screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", s->screen_width, s->screen_height, s->bits_per_pixel, s->has_global_palette); if (s->has_global_palette) { s->background_color_index = background_color_index; n = 1 << s->bits_per_pixel; if (bytestream2_get_bytes_left(&s->gb) < n * 3) return AVERROR_INVALIDDATA; gif_read_palette(s, s->global_palette, n); s->bg_color = s->global_palette[s->background_color_index]; } else s->background_color_index = -1; return 0; }
static int gif_read_header1(GifState *s) { uint8_t sig[6]; int v, n; int background_color_index; if (bytestream2_get_bytes_left(&s->gb) < 13) return AVERROR_INVALIDDATA; /* read gif signature */ bytestream2_get_bufferu(&s->gb, sig, 6); if (memcmp(sig, gif87a_sig, 6) && memcmp(sig, gif89a_sig, 6)) return AVERROR_INVALIDDATA; /* read screen header */ s->transparent_color_index = -1; s->screen_width = bytestream2_get_le16u(&s->gb); s->screen_height = bytestream2_get_le16u(&s->gb); v = bytestream2_get_byteu(&s->gb); s->color_resolution = ((v & 0x70) >> 4) + 1; s->has_global_palette = (v & 0x80); s->bits_per_pixel = (v & 0x07) + 1; background_color_index = bytestream2_get_byteu(&s->gb); n = bytestream2_get_byteu(&s->gb); if (n) { s->avctx->sample_aspect_ratio.num = n + 15; s->avctx->sample_aspect_ratio.den = 64; } ff_dlog(s->avctx, "screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", s->screen_width, s->screen_height, s->bits_per_pixel, s->has_global_palette); if (s->has_global_palette) { s->background_color_index = background_color_index; n = 1 << s->bits_per_pixel; if (bytestream2_get_bytes_left(&s->gb) < n * 3) return AVERROR_INVALIDDATA; gif_read_palette(s, s->global_palette, n); s->bg_color = s->global_palette[s->background_color_index]; } else s->background_color_index = -1; return 0; }
static int tiff_decode_tag(TiffContext *s, AVFrame *frame) { unsigned tag, type, count, off, value = 0, value2 = 0; int i, start; int pos; int ret; double *dp; ret = ff_tread_tag(&s->gb, s->le, &tag, &type, &count, &start); if (ret < 0) { goto end; } off = bytestream2_tell(&s->gb); if (count == 1) { switch (type) { case TIFF_BYTE: case TIFF_SHORT: case TIFF_LONG: value = ff_tget(&s->gb, type, s->le); break; case TIFF_RATIONAL: value = ff_tget(&s->gb, TIFF_LONG, s->le); value2 = ff_tget(&s->gb, TIFF_LONG, s->le); break; case TIFF_STRING: if (count <= 4) { break; } default: value = UINT_MAX; } } switch (tag) { case TIFF_WIDTH: s->width = value; break; case TIFF_HEIGHT: s->height = value; break; case TIFF_BPP: s->bppcount = count; if (count > 4) { av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", s->bpp, count); return AVERROR_INVALIDDATA; } if (count == 1) s->bpp = value; else { switch (type) { case TIFF_BYTE: case TIFF_SHORT: case TIFF_LONG: s->bpp = 0; if (bytestream2_get_bytes_left(&s->gb) < type_sizes[type] * count) return AVERROR_INVALIDDATA; for (i = 0; i < count; i++) s->bpp += ff_tget(&s->gb, type, s->le); break; default: s->bpp = -1; } } break; case TIFF_SAMPLES_PER_PIXEL: if (count != 1) { av_log(s->avctx, AV_LOG_ERROR, "Samples per pixel requires a single value, many provided\n"); return AVERROR_INVALIDDATA; } if (value > 4U) { av_log(s->avctx, AV_LOG_ERROR, "Samples per pixel %d is too large\n", value); return AVERROR_INVALIDDATA; } if (s->bppcount == 1) s->bpp *= value; s->bppcount = value; break; case TIFF_COMPR: s->compr = value; s->predictor = 0; switch (s->compr) { case TIFF_RAW: case TIFF_PACKBITS: case TIFF_LZW: case TIFF_CCITT_RLE: break; case TIFF_G3: case TIFF_G4: s->fax_opts = 0; break; case TIFF_DEFLATE: case TIFF_ADOBE_DEFLATE: #if CONFIG_ZLIB break; #else av_log(s->avctx, AV_LOG_ERROR, "Deflate: ZLib not compiled in\n"); return AVERROR(ENOSYS); #endif case TIFF_JPEG: case TIFF_NEWJPEG: avpriv_report_missing_feature(s->avctx, "JPEG compression"); return AVERROR_PATCHWELCOME; default: av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", s->compr); return AVERROR_INVALIDDATA; } break; case TIFF_ROWSPERSTRIP: if (!value || (type == TIFF_LONG && value == UINT_MAX)) value = s->height; s->rps = FFMIN(value, s->height); break; case TIFF_STRIP_OFFS: if (count == 1) { s->strippos = 0; s->stripoff = value; } else s->strippos = off; s->strips = count; if (s->strips == 1) s->rps = s->height; s->sot = type; break; case TIFF_STRIP_SIZE: if (count == 1) { s->stripsizesoff = 0; s->stripsize = value; s->strips = 1; } else { s->stripsizesoff = off; } s->strips = count; s->sstype = type; break; case TIFF_XRES: case TIFF_YRES: set_sar(s, tag, value, value2); break; case TIFF_TILE_BYTE_COUNTS: case TIFF_TILE_LENGTH: case TIFF_TILE_OFFSETS: case TIFF_TILE_WIDTH: av_log(s->avctx, AV_LOG_ERROR, "Tiled images are not supported\n"); return AVERROR_PATCHWELCOME; break; case TIFF_PREDICTOR: s->predictor = value; break; case TIFF_PHOTOMETRIC: switch (value) { case TIFF_PHOTOMETRIC_WHITE_IS_ZERO: case TIFF_PHOTOMETRIC_BLACK_IS_ZERO: case TIFF_PHOTOMETRIC_RGB: case TIFF_PHOTOMETRIC_PALETTE: case TIFF_PHOTOMETRIC_YCBCR: s->photometric = value; break; case TIFF_PHOTOMETRIC_ALPHA_MASK: case TIFF_PHOTOMETRIC_SEPARATED: case TIFF_PHOTOMETRIC_CIE_LAB: case TIFF_PHOTOMETRIC_ICC_LAB: case TIFF_PHOTOMETRIC_ITU_LAB: case TIFF_PHOTOMETRIC_CFA: case TIFF_PHOTOMETRIC_LOG_L: case TIFF_PHOTOMETRIC_LOG_LUV: case TIFF_PHOTOMETRIC_LINEAR_RAW: avpriv_report_missing_feature(s->avctx, "PhotometricInterpretation 0x%04X", value); return AVERROR_PATCHWELCOME; default: av_log(s->avctx, AV_LOG_ERROR, "PhotometricInterpretation %u is " "unknown\n", value); return AVERROR_INVALIDDATA; } break; case TIFF_FILL_ORDER: if (value < 1 || value > 2) { av_log(s->avctx, AV_LOG_ERROR, "Unknown FillOrder value %d, trying default one\n", value); value = 1; } s->fill_order = value - 1; break; case TIFF_PAL: { GetByteContext pal_gb[3]; off = type_sizes[type]; if (count / 3 > 256 || bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3) return AVERROR_INVALIDDATA; pal_gb[0] = pal_gb[1] = pal_gb[2] = s->gb; bytestream2_skip(&pal_gb[1], count / 3 * off); bytestream2_skip(&pal_gb[2], count / 3 * off * 2); off = (type_sizes[type] - 1) << 3; for (i = 0; i < count / 3; i++) { uint32_t p = 0xFF000000; p |= (ff_tget(&pal_gb[0], type, s->le) >> off) << 16; p |= (ff_tget(&pal_gb[1], type, s->le) >> off) << 8; p |= ff_tget(&pal_gb[2], type, s->le) >> off; s->palette[i] = p; } s->palette_is_set = 1; break; } case TIFF_PLANAR: s->planar = value == 2; break; case TIFF_YCBCR_SUBSAMPLING: if (count != 2) { av_log(s->avctx, AV_LOG_ERROR, "subsample count invalid\n"); return AVERROR_INVALIDDATA; } for (i = 0; i < count; i++) s->subsampling[i] = ff_tget(&s->gb, type, s->le); break; case TIFF_T4OPTIONS: if (s->compr == TIFF_G3) s->fax_opts = value; break; case TIFF_T6OPTIONS: if (s->compr == TIFF_G4) s->fax_opts = value; break; #define ADD_METADATA(count, name, sep)\ if ((ret = add_metadata(count, type, name, sep, s, frame)) < 0) {\ av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");\ goto end;\ } case TIFF_MODEL_PIXEL_SCALE: ADD_METADATA(count, "ModelPixelScaleTag", NULL); break; case TIFF_MODEL_TRANSFORMATION: ADD_METADATA(count, "ModelTransformationTag", NULL); break; case TIFF_MODEL_TIEPOINT: ADD_METADATA(count, "ModelTiepointTag", NULL); break; case TIFF_GEO_KEY_DIRECTORY: ADD_METADATA(1, "GeoTIFF_Version", NULL); ADD_METADATA(2, "GeoTIFF_Key_Revision", "."); s->geotag_count = ff_tget_short(&s->gb, s->le); if (s->geotag_count > count / 4 - 1) { s->geotag_count = count / 4 - 1; av_log(s->avctx, AV_LOG_WARNING, "GeoTIFF key directory buffer shorter than specified\n"); } if (bytestream2_get_bytes_left(&s->gb) < s->geotag_count * sizeof(int16_t) * 4) { s->geotag_count = 0; return -1; } s->geotags = av_mallocz_array(s->geotag_count, sizeof(TiffGeoTag)); if (!s->geotags) { av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); s->geotag_count = 0; goto end; } for (i = 0; i < s->geotag_count; i++) { s->geotags[i].key = ff_tget_short(&s->gb, s->le); s->geotags[i].type = ff_tget_short(&s->gb, s->le); s->geotags[i].count = ff_tget_short(&s->gb, s->le); if (!s->geotags[i].type) s->geotags[i].val = get_geokey_val(s->geotags[i].key, ff_tget_short(&s->gb, s->le)); else s->geotags[i].offset = ff_tget_short(&s->gb, s->le); } break; case TIFF_GEO_DOUBLE_PARAMS: if (count >= INT_MAX / sizeof(int64_t)) return AVERROR_INVALIDDATA; if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t)) return AVERROR_INVALIDDATA; dp = av_malloc_array(count, sizeof(double)); if (!dp) { av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); goto end; } for (i = 0; i < count; i++) dp[i] = ff_tget_double(&s->gb, s->le); for (i = 0; i < s->geotag_count; i++) { if (s->geotags[i].type == TIFF_GEO_DOUBLE_PARAMS) { if (s->geotags[i].count == 0 || s->geotags[i].offset + s->geotags[i].count > count) { av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key); } else { char *ap = doubles2str(&dp[s->geotags[i].offset], s->geotags[i].count, ", "); if (!ap) { av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); av_freep(&dp); return AVERROR(ENOMEM); } s->geotags[i].val = ap; } } } av_freep(&dp); break; case TIFF_GEO_ASCII_PARAMS: pos = bytestream2_tell(&s->gb); for (i = 0; i < s->geotag_count; i++) { if (s->geotags[i].type == TIFF_GEO_ASCII_PARAMS) { if (s->geotags[i].count == 0 || s->geotags[i].offset + s->geotags[i].count > count) { av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key); } else { char *ap; bytestream2_seek(&s->gb, pos + s->geotags[i].offset, SEEK_SET); if (bytestream2_get_bytes_left(&s->gb) < s->geotags[i].count) return AVERROR_INVALIDDATA; ap = av_malloc(s->geotags[i].count); if (!ap) { av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); return AVERROR(ENOMEM); } bytestream2_get_bufferu(&s->gb, ap, s->geotags[i].count); ap[s->geotags[i].count - 1] = '\0'; //replace the "|" delimiter with a 0 byte s->geotags[i].val = ap; } } } break; case TIFF_ARTIST: ADD_METADATA(count, "artist", NULL); break; case TIFF_COPYRIGHT: ADD_METADATA(count, "copyright", NULL); break; case TIFF_DATE: ADD_METADATA(count, "date", NULL); break; case TIFF_DOCUMENT_NAME: ADD_METADATA(count, "document_name", NULL); break; case TIFF_HOST_COMPUTER: ADD_METADATA(count, "computer", NULL); break; case TIFF_IMAGE_DESCRIPTION: ADD_METADATA(count, "description", NULL); break; case TIFF_MAKE: ADD_METADATA(count, "make", NULL); break; case TIFF_MODEL: ADD_METADATA(count, "model", NULL); break; case TIFF_PAGE_NAME: ADD_METADATA(count, "page_name", NULL); break; case TIFF_PAGE_NUMBER: ADD_METADATA(count, "page_number", " / "); break; case TIFF_SOFTWARE_NAME: ADD_METADATA(count, "software", NULL); break; default: if (s->avctx->err_recognition & AV_EF_EXPLODE) { av_log(s->avctx, AV_LOG_ERROR, "Unknown or unsupported tag %d/0X%0X\n", tag, tag); return AVERROR_INVALIDDATA; } } end: bytestream2_seek(&s->gb, start, SEEK_SET); return 0; }
static int xwd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { AVFrame *p = data; const uint8_t *buf = avpkt->data; int i, ret, buf_size = avpkt->size; uint32_t version, header_size, vclass, ncolors; uint32_t xoffset, be, bpp, lsize, rsize; uint32_t pixformat, pixdepth, bunit, bitorder, bpad; uint32_t rgb[3]; uint8_t *ptr; GetByteContext gb; if (buf_size < XWD_HEADER_SIZE) return AVERROR_INVALIDDATA; bytestream2_init(&gb, buf, buf_size); header_size = bytestream2_get_be32u(&gb); version = bytestream2_get_be32u(&gb); if (version != XWD_VERSION) { av_log(avctx, AV_LOG_ERROR, "unsupported version\n"); return AVERROR_INVALIDDATA; } if (buf_size < header_size || header_size < XWD_HEADER_SIZE) { av_log(avctx, AV_LOG_ERROR, "invalid header size\n"); return AVERROR_INVALIDDATA; } pixformat = bytestream2_get_be32u(&gb); pixdepth = bytestream2_get_be32u(&gb); avctx->width = bytestream2_get_be32u(&gb); avctx->height = bytestream2_get_be32u(&gb); xoffset = bytestream2_get_be32u(&gb); be = bytestream2_get_be32u(&gb); bunit = bytestream2_get_be32u(&gb); bitorder = bytestream2_get_be32u(&gb); bpad = bytestream2_get_be32u(&gb); bpp = bytestream2_get_be32u(&gb); lsize = bytestream2_get_be32u(&gb); vclass = bytestream2_get_be32u(&gb); rgb[0] = bytestream2_get_be32u(&gb); rgb[1] = bytestream2_get_be32u(&gb); rgb[2] = bytestream2_get_be32u(&gb); bytestream2_skipu(&gb, 8); ncolors = bytestream2_get_be32u(&gb); bytestream2_skipu(&gb, header_size - (XWD_HEADER_SIZE - 20)); av_log(avctx, AV_LOG_DEBUG, "pixformat %"PRIu32", pixdepth %"PRIu32", bunit %"PRIu32", bitorder %"PRIu32", bpad %"PRIu32"\n", pixformat, pixdepth, bunit, bitorder, bpad); av_log(avctx, AV_LOG_DEBUG, "vclass %"PRIu32", ncolors %"PRIu32", bpp %"PRIu32", be %"PRIu32", lsize %"PRIu32", xoffset %"PRIu32"\n", vclass, ncolors, bpp, be, lsize, xoffset); av_log(avctx, AV_LOG_DEBUG, "red %0"PRIx32", green %0"PRIx32", blue %0"PRIx32"\n", rgb[0], rgb[1], rgb[2]); if (pixformat > XWD_Z_PIXMAP) { av_log(avctx, AV_LOG_ERROR, "invalid pixmap format\n"); return AVERROR_INVALIDDATA; } if (pixdepth == 0 || pixdepth > 32) { av_log(avctx, AV_LOG_ERROR, "invalid pixmap depth\n"); return AVERROR_INVALIDDATA; } if (xoffset) { avpriv_request_sample(avctx, "xoffset %"PRIu32"", xoffset); return AVERROR_PATCHWELCOME; } if (be > 1) { av_log(avctx, AV_LOG_ERROR, "invalid byte order\n"); return AVERROR_INVALIDDATA; } if (bitorder > 1) { av_log(avctx, AV_LOG_ERROR, "invalid bitmap bit order\n"); return AVERROR_INVALIDDATA; } if (bunit != 8 && bunit != 16 && bunit != 32) { av_log(avctx, AV_LOG_ERROR, "invalid bitmap unit\n"); return AVERROR_INVALIDDATA; } if (bpad != 8 && bpad != 16 && bpad != 32) { av_log(avctx, AV_LOG_ERROR, "invalid bitmap scan-line pad\n"); return AVERROR_INVALIDDATA; } if (bpp == 0 || bpp > 32) { av_log(avctx, AV_LOG_ERROR, "invalid bits per pixel\n"); return AVERROR_INVALIDDATA; } if (ncolors > 256) { av_log(avctx, AV_LOG_ERROR, "invalid number of entries in colormap\n"); return AVERROR_INVALIDDATA; } if ((ret = av_image_check_size(avctx->width, avctx->height, 0, NULL)) < 0) return ret; rsize = FFALIGN(avctx->width * bpp, bpad) / 8; if (lsize < rsize) { av_log(avctx, AV_LOG_ERROR, "invalid bytes per scan-line\n"); return AVERROR_INVALIDDATA; } if (bytestream2_get_bytes_left(&gb) < ncolors * XWD_CMAP_SIZE + (uint64_t)avctx->height * lsize) { av_log(avctx, AV_LOG_ERROR, "input buffer too small\n"); return AVERROR_INVALIDDATA; } if (pixformat != XWD_Z_PIXMAP) { avpriv_report_missing_feature(avctx, "Pixmap format %"PRIu32, pixformat); return AVERROR_PATCHWELCOME; } avctx->pix_fmt = AV_PIX_FMT_NONE; switch (vclass) { case XWD_STATIC_GRAY: case XWD_GRAY_SCALE: if (bpp != 1 && bpp != 8) return AVERROR_INVALIDDATA; if (bpp == 1 && pixdepth == 1) { avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; } else if (bpp == 8 && pixdepth == 8) { avctx->pix_fmt = AV_PIX_FMT_GRAY8; } break; case XWD_STATIC_COLOR: case XWD_PSEUDO_COLOR: if (bpp == 8) avctx->pix_fmt = AV_PIX_FMT_PAL8; break; case XWD_TRUE_COLOR: case XWD_DIRECT_COLOR: if (bpp != 16 && bpp != 24 && bpp != 32) return AVERROR_INVALIDDATA; if (bpp == 16 && pixdepth == 15) { if (rgb[0] == 0x7C00 && rgb[1] == 0x3E0 && rgb[2] == 0x1F) avctx->pix_fmt = be ? AV_PIX_FMT_RGB555BE : AV_PIX_FMT_RGB555LE; else if (rgb[0] == 0x1F && rgb[1] == 0x3E0 && rgb[2] == 0x7C00) avctx->pix_fmt = be ? AV_PIX_FMT_BGR555BE : AV_PIX_FMT_BGR555LE; } else if (bpp == 16 && pixdepth == 16) { if (rgb[0] == 0xF800 && rgb[1] == 0x7E0 && rgb[2] == 0x1F) avctx->pix_fmt = be ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_RGB565LE; else if (rgb[0] == 0x1F && rgb[1] == 0x7E0 && rgb[2] == 0xF800) avctx->pix_fmt = be ? AV_PIX_FMT_BGR565BE : AV_PIX_FMT_BGR565LE; } else if (bpp == 24) { if (rgb[0] == 0xFF0000 && rgb[1] == 0xFF00 && rgb[2] == 0xFF) avctx->pix_fmt = be ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_BGR24; else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) avctx->pix_fmt = be ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_RGB24; } else if (bpp == 32) { if (rgb[0] == 0xFF0000 && rgb[1] == 0xFF00 && rgb[2] == 0xFF) avctx->pix_fmt = be ? AV_PIX_FMT_ARGB : AV_PIX_FMT_BGRA; else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) avctx->pix_fmt = be ? AV_PIX_FMT_ABGR : AV_PIX_FMT_RGBA; } bytestream2_skipu(&gb, ncolors * XWD_CMAP_SIZE); break; default: av_log(avctx, AV_LOG_ERROR, "invalid visual class\n"); return AVERROR_INVALIDDATA; } if (avctx->pix_fmt == AV_PIX_FMT_NONE) { avpriv_request_sample(avctx, "Unknown file: bpp %"PRIu32", pixdepth %"PRIu32", vclass %"PRIu32"", bpp, pixdepth, vclass); return AVERROR_PATCHWELCOME; } if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->key_frame = 1; p->pict_type = AV_PICTURE_TYPE_I; if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { uint32_t *dst = (uint32_t *)p->data[1]; uint8_t red, green, blue; for (i = 0; i < ncolors; i++) { bytestream2_skipu(&gb, 4); // skip colormap entry number red = bytestream2_get_byteu(&gb); bytestream2_skipu(&gb, 1); green = bytestream2_get_byteu(&gb); bytestream2_skipu(&gb, 1); blue = bytestream2_get_byteu(&gb); bytestream2_skipu(&gb, 3); // skip bitmask flag and padding dst[i] = 0xFFU << 24 | red << 16 | green << 8 | blue; } } ptr = p->data[0]; for (i = 0; i < avctx->height; i++) { bytestream2_get_bufferu(&gb, ptr, rsize); bytestream2_skipu(&gb, lsize - rsize); ptr += p->linesize[0]; } *got_frame = 1; return buf_size; }
static int redspark_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; RedSparkContext *redspark = s->priv_data; AVCodecParameters *par; GetByteContext gbc; int i, coef_off, ret = 0; uint32_t key, data; uint8_t header[HEADER_SIZE]; AVStream *st; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); par = st->codecpar; /* Decrypt header */ data = avio_rb32(pb); key = data ^ 0x52656453; data ^= key; AV_WB32(header, data); key = rol(key, 11); for (i = 4; i < HEADER_SIZE; i += 4) { key += rol(key, 3); data = avio_rb32(pb) ^ key; AV_WB32(header + i, data); } par->codec_id = AV_CODEC_ID_ADPCM_THP; par->codec_type = AVMEDIA_TYPE_AUDIO; bytestream2_init(&gbc, header, HEADER_SIZE); bytestream2_seek(&gbc, 0x3c, SEEK_SET); par->sample_rate = bytestream2_get_be32u(&gbc); if (par->sample_rate <= 0 || par->sample_rate > 96000) { av_log(s, AV_LOG_ERROR, "Invalid sample rate: %d\n", par->sample_rate); return AVERROR_INVALIDDATA; } st->duration = bytestream2_get_be32u(&gbc) * 14; redspark->samples_count = 0; bytestream2_skipu(&gbc, 10); par->channels = bytestream2_get_byteu(&gbc); if (!par->channels) { return AVERROR_INVALIDDATA; } coef_off = 0x54 + par->channels * 8; if (bytestream2_get_byteu(&gbc)) // Loop flag coef_off += 16; if (coef_off + par->channels * (32 + 14) > HEADER_SIZE) { return AVERROR_INVALIDDATA; } if (ff_alloc_extradata(par, 32 * par->channels)) { return AVERROR_INVALIDDATA; } /* Get the ADPCM table */ bytestream2_seek(&gbc, coef_off, SEEK_SET); for (i = 0; i < par->channels; i++) { if (bytestream2_get_bufferu(&gbc, par->extradata + i * 32, 32) != 32) { return AVERROR_INVALIDDATA; } bytestream2_skipu(&gbc, 14); } avpriv_set_pts_info(st, 64, 1, par->sample_rate); return ret; }