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 tgq_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt){ const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TgqContext *s = avctx->priv_data; int x,y; int big_endian; if (buf_size < 16) { av_log(avctx, AV_LOG_WARNING, "truncated header\n"); return -1; } big_endian = AV_RL32(&buf[4]) > 0x000FFFFF; bytestream2_init(&s->gb, buf + 8, buf_size - 8); if (big_endian) { s->width = bytestream2_get_be16u(&s->gb); s->height = bytestream2_get_be16u(&s->gb); } else { s->width = bytestream2_get_le16u(&s->gb); s->height = bytestream2_get_le16u(&s->gb); } if (s->avctx->width!=s->width || s->avctx->height!=s->height) { avcodec_set_dimensions(s->avctx, s->width, s->height); if (s->frame.data[0]) avctx->release_buffer(avctx, &s->frame); } tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb)); bytestream2_skip(&s->gb, 3); if (!s->frame.data[0]) { s->frame.key_frame = 1; s->frame.pict_type = AV_PICTURE_TYPE_I; s->frame.buffer_hints = FF_BUFFER_HINTS_VALID; if (ff_get_buffer(avctx, &s->frame)) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } } for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++) for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++) if (tgq_decode_mb(s, y, x) < 0) return AVERROR_INVALIDDATA; *got_frame = 1; *(AVFrame*)data = s->frame; return avpkt->size; }
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 tgq_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TgqContext *s = avctx->priv_data; AVFrame *frame = data; int x, y, ret; int big_endian; if (buf_size < 16) { av_log(avctx, AV_LOG_WARNING, "truncated header\n"); return AVERROR_INVALIDDATA; } big_endian = AV_RL32(&buf[4]) > 0x000FFFFF; bytestream2_init(&s->gb, buf + 8, buf_size - 8); if (big_endian) { s->width = bytestream2_get_be16u(&s->gb); s->height = bytestream2_get_be16u(&s->gb); } else { s->width = bytestream2_get_le16u(&s->gb); s->height = bytestream2_get_le16u(&s->gb); } ret = ff_set_dimensions(s->avctx, s->width, s->height); if (ret < 0) return ret; tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb)); bytestream2_skip(&s->gb, 3); if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; frame->key_frame = 1; frame->pict_type = AV_PICTURE_TYPE_I; for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++) for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++) if (tgq_decode_mb(s, frame, y, x) < 0) return AVERROR_INVALIDDATA; *got_frame = 1; return avpkt->size; }
static unsigned tget_short(GetByteContext *gb, int le) { unsigned v = le ? bytestream2_get_le16u(gb) : bytestream2_get_be16u(gb); return v; }
static int gif_read_image(GifState *s, AVFrame *frame) { int left, top, width, height, bits_per_pixel, code_size, flags, pw; int is_interleaved, has_local_palette, y, pass, y1, linesize, pal_size; uint32_t *ptr, *pal, *px, *pr, *ptr1; int ret; uint8_t *idx; /* At least 9 bytes of Image Descriptor. */ if (bytestream2_get_bytes_left(&s->gb) < 9) return AVERROR_INVALIDDATA; left = bytestream2_get_le16u(&s->gb); top = bytestream2_get_le16u(&s->gb); width = bytestream2_get_le16u(&s->gb); height = bytestream2_get_le16u(&s->gb); flags = bytestream2_get_byteu(&s->gb); is_interleaved = flags & 0x40; has_local_palette = flags & 0x80; bits_per_pixel = (flags & 0x07) + 1; av_dlog(s->avctx, "image x=%d y=%d w=%d h=%d\n", left, top, width, height); if (has_local_palette) { pal_size = 1 << bits_per_pixel; if (bytestream2_get_bytes_left(&s->gb) < pal_size * 3) return AVERROR_INVALIDDATA; gif_read_palette(s, s->local_palette, pal_size); pal = s->local_palette; } else { if (!s->has_global_palette) { av_log(s->avctx, AV_LOG_ERROR, "picture doesn't have either global or local palette.\n"); return AVERROR_INVALIDDATA; } pal = s->global_palette; } if (s->keyframe) { if (s->transparent_color_index == -1 && s->has_global_palette) { /* transparency wasn't set before the first frame, fill with background color */ gif_fill(frame, s->bg_color); } else { /* otherwise fill with transparent color. * this is necessary since by default picture filled with 0x80808080. */ gif_fill(frame, s->trans_color); } } /* verify that all the image is inside the screen dimensions */ if (!width || width > s->screen_width || left >= s->screen_width) { av_log(s->avctx, AV_LOG_ERROR, "Invalid image width.\n"); return AVERROR_INVALIDDATA; } if (!height || height > s->screen_height || top >= s->screen_height) { av_log(s->avctx, AV_LOG_ERROR, "Invalid image height.\n"); return AVERROR_INVALIDDATA; } if (left + width > s->screen_width) { /* width must be kept around to avoid lzw vs line desync */ pw = s->screen_width - left; av_log(s->avctx, AV_LOG_WARNING, "Image too wide by %d, truncating.\n", left + width - s->screen_width); } else { pw = width; } if (top + height > s->screen_height) { /* we don't care about the extra invisible lines */ av_log(s->avctx, AV_LOG_WARNING, "Image too high by %d, truncating.\n", top + height - s->screen_height); height = s->screen_height - top; } /* process disposal method */ if (s->gce_prev_disposal == GCE_DISPOSAL_BACKGROUND) { gif_fill_rect(frame, s->stored_bg_color, s->gce_l, s->gce_t, s->gce_w, s->gce_h); } else if (s->gce_prev_disposal == GCE_DISPOSAL_RESTORE) { gif_copy_img_rect(s->stored_img, (uint32_t *)frame->data[0], frame->linesize[0] / sizeof(uint32_t), s->gce_l, s->gce_t, s->gce_w, s->gce_h); } s->gce_prev_disposal = s->gce_disposal; if (s->gce_disposal != GCE_DISPOSAL_NONE) { s->gce_l = left; s->gce_t = top; s->gce_w = pw; s->gce_h = height; if (s->gce_disposal == GCE_DISPOSAL_BACKGROUND) { if (s->transparent_color_index >= 0) s->stored_bg_color = s->trans_color; else s->stored_bg_color = s->bg_color; } else if (s->gce_disposal == GCE_DISPOSAL_RESTORE) { av_fast_malloc(&s->stored_img, &s->stored_img_size, frame->linesize[0] * frame->height); if (!s->stored_img) return AVERROR(ENOMEM); gif_copy_img_rect((uint32_t *)frame->data[0], s->stored_img, frame->linesize[0] / sizeof(uint32_t), left, top, pw, height); } } /* Expect at least 2 bytes: 1 for lzw code size and 1 for block size. */ if (bytestream2_get_bytes_left(&s->gb) < 2) return AVERROR_INVALIDDATA; /* now get the image data */ code_size = bytestream2_get_byteu(&s->gb); if ((ret = ff_lzw_decode_init(s->lzw, code_size, s->gb.buffer, bytestream2_get_bytes_left(&s->gb), FF_LZW_GIF)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "LZW init failed\n"); return ret; } /* read all the image */ linesize = frame->linesize[0] / sizeof(uint32_t); ptr1 = (uint32_t *)frame->data[0] + top * linesize + left; ptr = ptr1; pass = 0; y1 = 0; for (y = 0; y < height; y++) { int count = ff_lzw_decode(s->lzw, s->idx_line, width); if (count != width) { if (count) av_log(s->avctx, AV_LOG_ERROR, "LZW decode failed\n"); goto decode_tail; } pr = ptr + pw; for (px = ptr, idx = s->idx_line; px < pr; px++, idx++) { if (*idx != s->transparent_color_index) *px = pal[*idx]; } if (is_interleaved) { switch(pass) { default: case 0: case 1: y1 += 8; ptr += linesize * 8; if (y1 >= height) { y1 = pass ? 2 : 4; ptr = ptr1 + linesize * y1; pass++; } break; case 2: y1 += 4; ptr += linesize * 4; if (y1 >= height) { y1 = 1; ptr = ptr1 + linesize; pass++; } break; case 3: y1 += 2; ptr += linesize * 2; break; } } else { ptr += linesize; } } decode_tail: /* read the garbage data until end marker is found */ ff_lzw_decode_tail(s->lzw); /* Graphic Control Extension's scope is single frame. * Remove its influence. */ s->transparent_color_index = -1; s->gce_disposal = GCE_DISPOSAL_NONE; return 0; }
static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { GetByteContext gb; AVFrame * const p = data; int compressed, xmin, ymin, xmax, ymax, ret; unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, bytes_per_scanline; uint8_t *ptr, *scanline; if (avpkt->size < 128) return AVERROR_INVALIDDATA; bytestream2_init(&gb, avpkt->data, avpkt->size); if (bytestream2_get_byteu(&gb) != 0x0a || bytestream2_get_byteu(&gb) > 5) { av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); return AVERROR_INVALIDDATA; } compressed = bytestream2_get_byteu(&gb); bits_per_pixel = bytestream2_get_byteu(&gb); xmin = bytestream2_get_le16u(&gb); ymin = bytestream2_get_le16u(&gb); xmax = bytestream2_get_le16u(&gb); ymax = bytestream2_get_le16u(&gb); avctx->sample_aspect_ratio.num = bytestream2_get_le16u(&gb); avctx->sample_aspect_ratio.den = bytestream2_get_le16u(&gb); if (xmax < xmin || ymax < ymin) { av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n"); return AVERROR_INVALIDDATA; } w = xmax - xmin + 1; h = ymax - ymin + 1; bytestream2_skipu(&gb, 49); nplanes = bytestream2_get_byteu(&gb); bytes_per_line = bytestream2_get_le16u(&gb); bytes_per_scanline = nplanes * bytes_per_line; if (bytes_per_scanline < (w * bits_per_pixel * nplanes + 7) / 8) { av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); return AVERROR_INVALIDDATA; } switch ((nplanes<<8) + bits_per_pixel) { case 0x0308: avctx->pix_fmt = AV_PIX_FMT_RGB24; break; case 0x0108: case 0x0104: case 0x0102: case 0x0101: case 0x0401: case 0x0301: case 0x0201: avctx->pix_fmt = AV_PIX_FMT_PAL8; break; default: av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n"); return AVERROR_INVALIDDATA; } bytestream2_skipu(&gb, 60); if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) return ret; if (w != avctx->width || h != avctx->height) avcodec_set_dimensions(avctx, w, h); if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } p->pict_type = AV_PICTURE_TYPE_I; ptr = p->data[0]; stride = p->linesize[0]; scanline = av_malloc(bytes_per_scanline + FF_INPUT_BUFFER_PADDING_SIZE); if (!scanline) return AVERROR(ENOMEM); if (nplanes == 3 && bits_per_pixel == 8) { for (y=0; y<h; y++) { pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); for (x=0; x<w; x++) { ptr[3*x ] = scanline[x ]; ptr[3*x+1] = scanline[x+ bytes_per_line ]; ptr[3*x+2] = scanline[x+(bytes_per_line<<1)]; } ptr += stride; } } else if (nplanes == 1 && bits_per_pixel == 8) { int palstart = avpkt->size - 769; for (y=0; y<h; y++, ptr+=stride) { pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); memcpy(ptr, scanline, w); } if (bytestream2_tell(&gb) != palstart) { av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n"); bytestream2_seek(&gb, palstart, SEEK_SET); } if (bytestream2_get_byte(&gb) != 12) { av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n"); ret = AVERROR_INVALIDDATA; goto end; } } else if (nplanes == 1) { /* all packed formats, max. 16 colors */ GetBitContext s; for (y=0; y<h; y++) { init_get_bits8(&s, scanline, bytes_per_scanline); pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); for (x=0; x<w; x++) ptr[x] = get_bits(&s, bits_per_pixel); ptr += stride; } } else { /* planar, 4, 8 or 16 colors */ int i; for (y=0; y<h; y++) { pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); for (x=0; x<w; x++) { int m = 0x80 >> (x&7), v = 0; for (i=nplanes - 1; i>=0; i--) { v <<= 1; v += !!(scanline[i*bytes_per_line + (x>>3)] & m); } ptr[x] = v; } ptr += stride; } } ret = bytestream2_tell(&gb); if (nplanes == 1 && bits_per_pixel == 8) { pcx_palette(&gb, (uint32_t *) p->data[1], 256); ret += 256 * 3; } else if (bits_per_pixel * nplanes == 1) { AV_WN32A(p->data[1] , 0xFF000000); AV_WN32A(p->data[1]+4, 0xFFFFFFFF); } else if (bits_per_pixel < 8) { bytestream2_seek(&gb, 16, SEEK_SET); pcx_palette(&gb, (uint32_t *) p->data[1], 16); } *got_frame = 1; end: av_free(scanline); return ret; }
static int dpcm_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { int buf_size = avpkt->size; DPCMContext *s = avctx->priv_data; int out = 0, ret; int predictor[2]; int ch = 0; int stereo = s->channels - 1; int16_t *output_samples, *samples_end; GetByteContext gb; if (stereo && (buf_size & 1)) buf_size--; bytestream2_init(&gb, avpkt->data, buf_size); /* calculate output size */ switch(avctx->codec->id) { case CODEC_ID_ROQ_DPCM: out = buf_size - 8; break; case CODEC_ID_INTERPLAY_DPCM: out = buf_size - 6 - s->channels; break; case CODEC_ID_XAN_DPCM: out = buf_size - 2 * s->channels; break; case CODEC_ID_SOL_DPCM: if (avctx->codec_tag != 3) out = buf_size * 2; else out = buf_size; break; } if (out <= 0) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); return AVERROR(EINVAL); } /* get output buffer */ s->frame.nb_samples = out / s->channels; if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } output_samples = (int16_t *)s->frame.data[0]; samples_end = output_samples + out; switch(avctx->codec->id) { case CODEC_ID_ROQ_DPCM: bytestream2_skipu(&gb, 6); if (stereo) { predictor[1] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16); predictor[0] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16); } else { predictor[0] = sign_extend(bytestream2_get_le16u(&gb), 16); } /* decode the samples */ while (output_samples < samples_end) { predictor[ch] += s->roq_square_array[bytestream2_get_byteu(&gb)]; predictor[ch] = av_clip_int16(predictor[ch]); *output_samples++ = predictor[ch]; /* toggle channel */ ch ^= stereo; } break; case CODEC_ID_INTERPLAY_DPCM: bytestream2_skipu(&gb, 6); /* skip over the stream mask and stream length */ for (ch = 0; ch < s->channels; ch++) { predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); *output_samples++ = predictor[ch]; } ch = 0; while (output_samples < samples_end) { predictor[ch] += interplay_delta_table[bytestream2_get_byteu(&gb)]; predictor[ch] = av_clip_int16(predictor[ch]); *output_samples++ = predictor[ch]; /* toggle channel */ ch ^= stereo; } break; case CODEC_ID_XAN_DPCM: { int shift[2] = { 4, 4 }; for (ch = 0; ch < s->channels; ch++) predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); ch = 0; while (output_samples < samples_end) { int diff = bytestream2_get_byteu(&gb); int n = diff & 3; if (n == 3) shift[ch]++; else shift[ch] -= (2 * n); diff = sign_extend((diff &~ 3) << 8, 16); /* saturate the shifter to a lower limit of 0 */ if (shift[ch] < 0) shift[ch] = 0; diff >>= shift[ch]; predictor[ch] += diff; predictor[ch] = av_clip_int16(predictor[ch]); *output_samples++ = predictor[ch]; /* toggle channel */ ch ^= stereo; } break; } case CODEC_ID_SOL_DPCM: if (avctx->codec_tag != 3) { uint8_t *output_samples_u8 = s->frame.data[0], *samples_end_u8 = output_samples_u8 + out; while (output_samples_u8 < samples_end_u8) { int n = bytestream2_get_byteu(&gb); s->sample[0] += s->sol_table[n >> 4]; s->sample[0] = av_clip_uint8(s->sample[0]); *output_samples_u8++ = s->sample[0]; s->sample[stereo] += s->sol_table[n & 0x0F]; s->sample[stereo] = av_clip_uint8(s->sample[stereo]); *output_samples_u8++ = s->sample[stereo]; } } else { while (output_samples < samples_end) {
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { PicContext *s = avctx->priv_data; uint32_t *palette; int bits_per_plane, bpp, etype, esize, npal, pos_after_pal; int i, x, y, plane, tmp; bytestream2_init(&s->g, avpkt->data, avpkt->size); if (bytestream2_get_bytes_left(&s->g) < 11) return AVERROR_INVALIDDATA; if (bytestream2_get_le16u(&s->g) != 0x1234) return AVERROR_INVALIDDATA; s->width = bytestream2_get_le16u(&s->g); s->height = bytestream2_get_le16u(&s->g); bytestream2_skip(&s->g, 4); tmp = bytestream2_get_byteu(&s->g); bits_per_plane = tmp & 0xF; s->nb_planes = (tmp >> 4) + 1; bpp = bits_per_plane * s->nb_planes; if (bits_per_plane > 8 || bpp < 1 || bpp > 32) { av_log_ask_for_sample(s, "unsupported bit depth\n"); return AVERROR_INVALIDDATA; } if (bytestream2_peek_byte(&s->g) == 0xFF) { bytestream2_skip(&s->g, 2); etype = bytestream2_get_le16(&s->g); esize = bytestream2_get_le16(&s->g); if (bytestream2_get_bytes_left(&s->g) < esize) return AVERROR_INVALIDDATA; } else { etype = -1; esize = 0; } avctx->pix_fmt = PIX_FMT_PAL8; if (s->width != avctx->width && s->height != avctx->height) { if (av_image_check_size(s->width, s->height, 0, avctx) < 0) return -1; avcodec_set_dimensions(avctx, s->width, s->height); if (s->frame.data[0]) avctx->release_buffer(avctx, &s->frame); } if (avctx->get_buffer(avctx, &s->frame) < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } memset(s->frame.data[0], 0, s->height * s->frame.linesize[0]); s->frame.pict_type = AV_PICTURE_TYPE_I; s->frame.palette_has_changed = 1; pos_after_pal = bytestream2_tell(&s->g) + esize; palette = (uint32_t*)s->frame.data[1]; if (etype == 1 && esize > 1 && bytestream2_peek_byte(&s->g) < 6) { int idx = bytestream2_get_byte(&s->g); npal = 4; for (i = 0; i < npal; i++) palette[i] = ff_cga_palette[ cga_mode45_index[idx][i] ]; } else if (etype == 2) { npal = FFMIN(esize, 16); for (i = 0; i < npal; i++) { int pal_idx = bytestream2_get_byte(&s->g); palette[i] = ff_cga_palette[FFMIN(pal_idx, 16)]; } } else if (etype == 3) { npal = FFMIN(esize, 16); for (i = 0; i < npal; i++) { int pal_idx = bytestream2_get_byte(&s->g); palette[i] = ff_ega_palette[FFMIN(pal_idx, 63)]; } } else if (etype == 4 || etype == 5) { npal = FFMIN(esize / 3, 256); for (i = 0; i < npal; i++) palette[i] = bytestream2_get_be24(&s->g) << 2; } else { if (bpp == 1) { npal = 2; palette[0] = 0x000000; palette[1] = 0xFFFFFF; } else if (bpp == 2) { npal = 4; for (i = 0; i < npal; i++) palette[i] = ff_cga_palette[ cga_mode45_index[0][i] ]; } else { npal = 16; memcpy(palette, ff_cga_palette, npal * 4); } } // fill remaining palette entries memset(palette + npal, 0, AVPALETTE_SIZE - npal * 4); // skip remaining palette bytes bytestream2_seek(&s->g, pos_after_pal, SEEK_SET); x = 0; y = s->height - 1; plane = 0; if (bytestream2_get_le16(&s->g)) { while (bytestream2_get_bytes_left(&s->g) >= 6) { int stop_size, marker, t1, t2; t1 = bytestream2_get_bytes_left(&s->g); t2 = bytestream2_get_le16(&s->g); stop_size = t1 - FFMIN(t1, t2); // ignore uncompressed block size bytestream2_skip(&s->g, 2); marker = bytestream2_get_byte(&s->g); while (plane < s->nb_planes && bytestream2_get_bytes_left(&s->g) > stop_size) { int run = 1; int val = bytestream2_get_byte(&s->g); if (val == marker) { run = bytestream2_get_byte(&s->g); if (run == 0) run = bytestream2_get_le16(&s->g); val = bytestream2_get_byte(&s->g); } if (!bytestream2_get_bytes_left(&s->g)) break; if (bits_per_plane == 8) { picmemset_8bpp(s, val, run, &x, &y); if (y < 0) break; } else { picmemset(s, val, run, &x, &y, &plane, bits_per_plane); } } } } else { av_log_ask_for_sample(s, "uncompressed image\n"); return avpkt->size; } *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; return avpkt->size; }