static int hqa_decode_frame(HQContext *ctx, AVFrame *pic, size_t data_size) { GetBitContext gb; const int num_slices = 8; uint32_t slice_off[9]; int i, slice, ret; int width, height, quant; const uint8_t *src = ctx->gbc.buffer; width = bytestream2_get_be16(&ctx->gbc); height = bytestream2_get_be16(&ctx->gbc); ctx->avctx->coded_width = FFALIGN(width, 16); ctx->avctx->coded_height = FFALIGN(height, 16); ctx->avctx->width = width; ctx->avctx->height = height; ctx->avctx->bits_per_raw_sample = 8; ctx->avctx->pix_fmt = AV_PIX_FMT_YUVA422P; av_log(ctx->avctx, AV_LOG_VERBOSE, "HQA Profile\n"); quant = bytestream2_get_byte(&ctx->gbc); bytestream2_skip(&ctx->gbc, 3); if (quant >= NUM_HQ_QUANTS) { av_log(ctx->avctx, AV_LOG_ERROR, "Invalid quantization matrix %d.\n", quant); return AVERROR_INVALIDDATA; } ret = ff_get_buffer(ctx->avctx, pic, 0); if (ret < 0) { av_log(ctx->avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); return ret; } /* Offsets are stored from HQA1 position, so adjust them accordingly. */ for (i = 0; i < num_slices + 1; i++) slice_off[i] = bytestream2_get_be32(&ctx->gbc) - 4; for (slice = 0; slice < num_slices; slice++) { if (slice_off[slice] < (num_slices + 1) * 3 || slice_off[slice] >= slice_off[slice + 1] || slice_off[slice + 1] > data_size) { av_log(ctx->avctx, AV_LOG_ERROR, "Invalid slice size %zu.\n", data_size); break; } init_get_bits(&gb, src + slice_off[slice], (slice_off[slice + 1] - slice_off[slice]) * 8); ret = hqa_decode_slice(ctx, pic, &gb, quant, slice, width, height); if (ret < 0) return ret; } return 0; }
static int pix_decode_header(PixHeader *out, GetByteContext *pgb) { unsigned int header_len = bytestream2_get_be32(pgb); out->format = bytestream2_get_byte(pgb); bytestream2_skip(pgb, 2); out->width = bytestream2_get_be16(pgb); out->height = bytestream2_get_be16(pgb); // the header is at least 11 bytes long; we read the first 7 if (header_len < 11) return AVERROR_INVALIDDATA; // skip the rest of the header bytestream2_skip(pgb, header_len - 7); return 0; }
static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc, int step) { int i, j; int offset = avctx->width * step; uint8_t *outdata = p->data[0]; for (i = 0; i < avctx->height; i++) { int size, left, code, pix; uint8_t *out = outdata; int pos = 0; /* size of packed line */ size = left = bytestream2_get_be16(gbc); if (bytestream2_get_bytes_left(gbc) < size) return AVERROR_INVALIDDATA; /* decode line */ while (left > 0) { code = bytestream2_get_byte(gbc); if (code & 0x80 ) { /* run */ pix = bytestream2_get_byte(gbc); for (j = 0; j < 257 - code; j++) { out[pos] = pix; pos += step; if (pos >= offset) { pos -= offset; pos++; } if (pos >= offset) return AVERROR_INVALIDDATA; } left -= 2; } else { /* copy */ for (j = 0; j < code + 1; j++) { out[pos] = bytestream2_get_byte(gbc); pos += step; if (pos >= offset) { pos -= offset; pos++; } if (pos >= offset) return AVERROR_INVALIDDATA; } left -= 2 + code; } } outdata += p->linesize[0]; } return 0; }
int ff_amf_get_string(GetByteContext *bc, uint8_t *str, int strsize, int *length) { int stringlen = 0; int readsize; stringlen = bytestream2_get_be16(bc); if (stringlen + 1 > strsize) return AVERROR(EINVAL); readsize = bytestream2_get_buffer(bc, str, stringlen); if (readsize != stringlen) { av_log(NULL, AV_LOG_WARNING, "Unable to read as many bytes as AMF string signaled\n"); } str[readsize] = '\0'; *length = FFMIN(stringlen, readsize); return 0; }
static int parse_palette(AVCodecContext *avctx, GetByteContext *gbc, uint32_t *pal, int colors) { int i; for (i = 0; i <= colors; i++) { uint8_t r, g, b; unsigned int idx = bytestream2_get_be16(gbc); /* color index */ if (idx > 255) { av_log(avctx, AV_LOG_WARNING, "Palette index out of range: %u\n", idx); bytestream2_skip(gbc, 6); continue; } r = bytestream2_get_byte(gbc); bytestream2_skip(gbc, 1); g = bytestream2_get_byte(gbc); bytestream2_skip(gbc, 1); b = bytestream2_get_byte(gbc); bytestream2_skip(gbc, 1); pal[idx] = (0xFFU << 24) | (r << 16) | (g << 8) | b; } return 0; }
unsigned ff_tget_short(GetByteContext *gb, int le) { unsigned v = le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); return v; }
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { SgiState *s = avctx->priv_data; AVFrame *p = data; unsigned int dimension, rle; int ret = 0; uint8_t *out_buf, *out_end; bytestream2_init(&s->g, avpkt->data, avpkt->size); if (bytestream2_get_bytes_left(&s->g) < SGI_HEADER_SIZE) { av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", avpkt->size); return AVERROR_INVALIDDATA; } /* Test for SGI magic. */ if (bytestream2_get_be16(&s->g) != SGI_MAGIC) { av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); return AVERROR_INVALIDDATA; } rle = bytestream2_get_byte(&s->g); s->bytes_per_channel = bytestream2_get_byte(&s->g); dimension = bytestream2_get_be16(&s->g); s->width = bytestream2_get_be16(&s->g); s->height = bytestream2_get_be16(&s->g); s->depth = bytestream2_get_be16(&s->g); if (s->bytes_per_channel != 1 && s->bytes_per_channel != 2) { av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); return -1; } /* Check for supported image dimensions. */ if (dimension != 2 && dimension != 3) { av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n"); return -1; } if (s->depth == SGI_GRAYSCALE) { avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_GRAY16BE : AV_PIX_FMT_GRAY8; } else if (s->depth == SGI_RGB) { avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_RGB48BE : AV_PIX_FMT_RGB24; } else if (s->depth == SGI_RGBA) { avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGBA; } else { av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); return -1; } ret = ff_set_dimensions(avctx, s->width, s->height); if (ret < 0) return ret; if (ff_get_buffer(avctx, p, 0) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n"); return -1; } p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; out_buf = p->data[0]; out_end = out_buf + p->linesize[0] * s->height; s->linesize = p->linesize[0]; /* Skip header. */ bytestream2_seek(&s->g, SGI_HEADER_SIZE, SEEK_SET); if (rle) { ret = read_rle_sgi(out_end, s); } else { ret = read_uncompressed_sgi(out_buf, s); } if (ret == 0) { *got_frame = 1; return avpkt->size; } else { return ret; } }
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { AVFrame * const p = data; GetByteContext gbc; int colors; int w, h, ret; int ver; bytestream2_init(&gbc, avpkt->data, avpkt->size); if ( bytestream2_get_bytes_left(&gbc) >= 552 && check_header(gbc.buffer + 512, bytestream2_get_bytes_left(&gbc) - 512) ) bytestream2_skip(&gbc, 512); ver = check_header(gbc.buffer, bytestream2_get_bytes_left(&gbc)); /* smallest PICT header */ if (bytestream2_get_bytes_left(&gbc) < 40) { av_log(avctx, AV_LOG_ERROR, "Frame is too small %d\n", bytestream2_get_bytes_left(&gbc)); return AVERROR_INVALIDDATA; } bytestream2_skip(&gbc, 6); h = bytestream2_get_be16(&gbc); w = bytestream2_get_be16(&gbc); ret = ff_set_dimensions(avctx, w, h); if (ret < 0) return ret; /* version 1 is identified by 0x1101 * it uses byte-aligned opcodes rather than word-aligned */ if (ver == 1) { avpriv_request_sample(avctx, "QuickDraw version 1"); return AVERROR_PATCHWELCOME; } else if (ver != 2) { avpriv_request_sample(avctx, "QuickDraw version unknown (%X)", bytestream2_get_be32(&gbc)); return AVERROR_PATCHWELCOME; } bytestream2_skip(&gbc, 4+26); while (bytestream2_get_bytes_left(&gbc) >= 4) { int bppcnt, bpp; int rowbytes, pack_type; int opcode = bytestream2_get_be16(&gbc); switch(opcode) { case PACKBITSRECT: case PACKBITSRGN: av_log(avctx, AV_LOG_DEBUG, "Parsing Packbit opcode\n"); bytestream2_skip(&gbc, 30); bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */ bpp = bytestream2_get_be16(&gbc); /* cmpSize */ av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); if (bppcnt == 1 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_PAL8; } else { av_log(avctx, AV_LOG_ERROR, "Invalid pixel format (bppcnt %d bpp %d) in Packbit\n", bppcnt, bpp); return AVERROR_INVALIDDATA; } /* jump to palette */ bytestream2_skip(&gbc, 18); colors = bytestream2_get_be16(&gbc); if (colors < 0 || colors > 256) { av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors); return AVERROR_INVALIDDATA; } if (bytestream2_get_bytes_left(&gbc) < (colors + 1) * 8) { av_log(avctx, AV_LOG_ERROR, "Palette is too small %d\n", bytestream2_get_bytes_left(&gbc)); return AVERROR_INVALIDDATA; } if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; parse_palette(avctx, &gbc, (uint32_t *)p->data[1], colors); p->palette_has_changed = 1; /* jump to image data */ bytestream2_skip(&gbc, 18); if (opcode == PACKBITSRGN) { bytestream2_skip(&gbc, 2 + 8); /* size + rect */ avpriv_report_missing_feature(avctx, "Packbit mask region"); } ret = decode_rle(avctx, p, &gbc, bppcnt); if (ret < 0) return ret; *got_frame = 1; break; case DIRECTBITSRECT: case DIRECTBITSRGN: av_log(avctx, AV_LOG_DEBUG, "Parsing Directbit opcode\n"); bytestream2_skip(&gbc, 4); rowbytes = bytestream2_get_be16(&gbc) & 0x3FFF; if (rowbytes <= 250) { avpriv_report_missing_feature(avctx, "Short rowbytes"); return AVERROR_PATCHWELCOME; } bytestream2_skip(&gbc, 10); pack_type = bytestream2_get_be16(&gbc); bytestream2_skip(&gbc, 16); bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */ bpp = bytestream2_get_be16(&gbc); /* cmpSize */ av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); if (bppcnt == 3 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_RGB24; } else if (bppcnt == 4 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_ARGB; } else { av_log(avctx, AV_LOG_ERROR, "Invalid pixel format (bppcnt %d bpp %d) in Directbit\n", bppcnt, bpp); return AVERROR_INVALIDDATA; } /* set packing when default is selected */ if (pack_type == 0) pack_type = bppcnt; if (pack_type != 3 && pack_type != 4) { avpriv_request_sample(avctx, "Pack type %d", pack_type); return AVERROR_PATCHWELCOME; } if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } /* jump to data */ bytestream2_skip(&gbc, 30); if (opcode == DIRECTBITSRGN) { bytestream2_skip(&gbc, 2 + 8); /* size + rect */ avpriv_report_missing_feature(avctx, "DirectBit mask region"); } ret = decode_rle(avctx, p, &gbc, bppcnt); if (ret < 0) return ret; *got_frame = 1; break; default: av_log(avctx, AV_LOG_TRACE, "Unknown 0x%04X opcode\n", opcode); break; } /* exit the loop when a known pixel block has been found */ if (*got_frame) { int eop, trail; /* re-align to a word */ bytestream2_skip(&gbc, bytestream2_get_bytes_left(&gbc) % 2); eop = bytestream2_get_be16(&gbc); trail = bytestream2_get_bytes_left(&gbc); if (eop != EOP) av_log(avctx, AV_LOG_WARNING, "Missing end of picture opcode (found 0x%04X)\n", eop); if (trail) av_log(avctx, AV_LOG_WARNING, "Got %d trailing bytes\n", trail); break; } } if (*got_frame) { p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; return avpkt->size; } else { av_log(avctx, AV_LOG_ERROR, "Frame contained no usable data\n"); return AVERROR_INVALIDDATA; } }