static int sgi_read(ByteIOContext *f, int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque) { SGIInfo sgi_info, *s = &sgi_info; AVImageInfo info1, *info = &info1; int ret; read_sgi_header(f, s); if (s->bytes_per_channel != 1) { return AVERROR_INVALIDDATA; } /* check for supported image dimensions */ if (s->dimension != 2 && s->dimension != 3) { return AVERROR_INVALIDDATA; } if (s->zsize == SGI_GRAYSCALE) { info->pix_fmt = PIX_FMT_GRAY8; } else if (s->zsize == SGI_RGB) { info->pix_fmt = PIX_FMT_RGB24; } else if (s->zsize == SGI_RGBA) { info->pix_fmt = PIX_FMT_RGBA32; } else { return AVERROR_INVALIDDATA; } info->width = s->xsize; info->height = s->ysize; ret = alloc_cb(opaque, info); if (ret) return ret; if (s->rle) { return read_rle_sgi(s, &info->pict, f); } else { return read_uncompressed_sgi(s, &info->pict, f); } return 0; /* not reached */ }
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 *data_size, const uint8_t *in_buf, int buf_size) { SgiState *s = avctx->priv_data; AVFrame *picture = data; AVFrame *p = &s->picture; const uint8_t *in_end = in_buf + buf_size; unsigned int dimension, bytes_per_channel, rle; int ret = 0; uint8_t *out_buf, *out_end; if (buf_size < SGI_HEADER_SIZE){ av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", buf_size); return -1; } /* Test for SGI magic. */ if (bytestream_get_be16(&in_buf) != SGI_MAGIC) { av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); return -1; } rle = bytestream_get_byte(&in_buf); bytes_per_channel = bytestream_get_byte(&in_buf); dimension = bytestream_get_be16(&in_buf); s->width = bytestream_get_be16(&in_buf); s->height = bytestream_get_be16(&in_buf); s->depth = bytestream_get_be16(&in_buf); if (bytes_per_channel != 1) { 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 = PIX_FMT_GRAY8; } else if (s->depth == SGI_RGB) { avctx->pix_fmt = PIX_FMT_RGB24; } else if (s->depth == SGI_RGBA) { avctx->pix_fmt = PIX_FMT_RGBA; } else { av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); return -1; } if (avcodec_check_dimensions(avctx, s->width, s->height)) return -1; avcodec_set_dimensions(avctx, s->width, s->height); if (p->data[0]) avctx->release_buffer(avctx, p); p->reference = 0; if (avctx->get_buffer(avctx, p) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n"); return -1; } p->pict_type = FF_I_TYPE; 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. */ in_buf += SGI_HEADER_SIZE - 12; if (rle) { ret = read_rle_sgi(out_end, in_buf, in_end, s); } else { ret = read_uncompressed_sgi(out_buf, out_end, in_buf, in_end, s); } if (ret == 0) { *picture = s->picture; *data_size = sizeof(AVPicture); return buf_size; } else { return -1; } }