From e771223ec1be32da96e72d8319a8677aa9776204 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Sep 2022 16:05:49 +0200 Subject: [PATCH] avcodec/sgidec: Avoid redundant private context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SGI is intra-frame only; the decoder therefore does not maintain any state between frames, so remove the private context. Also rename depth to nb_components. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavcodec/sgidec.c | 158 ++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 85 deletions(-) diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c index a449859bf8..bd49a3510d 100644 --- a/libavcodec/sgidec.c +++ b/libavcodec/sgidec.c @@ -25,25 +25,17 @@ #include "decode.h" #include "sgi.h" -typedef struct SgiState { - AVCodecContext *avctx; - unsigned int width; - int height; - unsigned int depth; - unsigned int bytes_per_channel; - int linesize; - GetByteContext g; -} SgiState; - /** * Expand an RLE row into a channel. - * @param s the current image state + * @param logctx a logcontext * @param out_buf Points to one line after the output buffer. + * @param g GetByteContext used to read input from * @param len length of out_buf in bytes * @param pixelstride pixel stride of input buffer * @return size of output in bytes, else return error code. */ -static int expand_rle_row8(SgiState *s, uint8_t *out_buf, +static int expand_rle_row8(void *logctx, uint8_t *out_buf, + GetByteContext *g, int len, int pixelstride) { unsigned char pixel, count; @@ -51,26 +43,26 @@ static int expand_rle_row8(SgiState *s, uint8_t *out_buf, uint8_t *out_end = out_buf + len; while (out_buf < out_end) { - if (bytestream2_get_bytes_left(&s->g) < 1) + if (bytestream2_get_bytes_left(g) < 1) return AVERROR_INVALIDDATA; - pixel = bytestream2_get_byteu(&s->g); + pixel = bytestream2_get_byteu(g); if (!(count = (pixel & 0x7f))) { break; } /* Check for buffer overflow. */ if (out_end - out_buf <= pixelstride * (count - 1)) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid pixel count.\n"); + av_log(logctx, AV_LOG_ERROR, "Invalid pixel count.\n"); return AVERROR_INVALIDDATA; } if (pixel & 0x80) { while (count--) { - *out_buf = bytestream2_get_byte(&s->g); + *out_buf = bytestream2_get_byte(g); out_buf += pixelstride; } } else { - pixel = bytestream2_get_byte(&s->g); + pixel = bytestream2_get_byte(g); while (count--) { *out_buf = pixel; @@ -81,7 +73,8 @@ static int expand_rle_row8(SgiState *s, uint8_t *out_buf, return (out_buf - orig) / pixelstride; } -static int expand_rle_row16(SgiState *s, uint16_t *out_buf, +static int expand_rle_row16(void *logctx, uint16_t *out_buf, + GetByteContext *g, int len, int pixelstride) { unsigned short pixel; @@ -90,26 +83,26 @@ static int expand_rle_row16(SgiState *s, uint16_t *out_buf, uint16_t *out_end = out_buf + len; while (out_buf < out_end) { - if (bytestream2_get_bytes_left(&s->g) < 2) + if (bytestream2_get_bytes_left(g) < 2) return AVERROR_INVALIDDATA; - pixel = bytestream2_get_be16u(&s->g); + pixel = bytestream2_get_be16u(g); if (!(count = (pixel & 0x7f))) break; /* Check for buffer overflow. */ if (out_end - out_buf <= pixelstride * (count - 1)) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid pixel count.\n"); + av_log(logctx, AV_LOG_ERROR, "Invalid pixel count.\n"); return AVERROR_INVALIDDATA; } if (pixel & 0x80) { while (count--) { - pixel = bytestream2_get_ne16(&s->g); + pixel = bytestream2_get_ne16(g); AV_WN16A(out_buf, pixel); out_buf += pixelstride; } } else { - pixel = bytestream2_get_ne16(&s->g); + pixel = bytestream2_get_ne16(g); while (count--) { AV_WN16A(out_buf, pixel); @@ -127,34 +120,38 @@ static int expand_rle_row16(SgiState *s, uint16_t *out_buf, * @param s the current image state * @return 0 if no error, else return error code. */ -static int read_rle_sgi(uint8_t *last_line, SgiState *s) +static int read_rle_sgi(void *logctx, uint8_t *last_line, GetByteContext *g, + ptrdiff_t stride, unsigned width, unsigned height, + unsigned nb_components, unsigned bytes_per_channel) { uint8_t *dest_row; - unsigned int len = s->height * s->depth * 4; - GetByteContext g_table = s->g; + unsigned int len = height * nb_components * 4; + GetByteContext g_table = *g; unsigned int start_offset; int linesize, ret; /* size of RLE offset and length tables */ - if (len * 2 > bytestream2_get_bytes_left(&s->g)) { + if (len * 2 > bytestream2_get_bytes_left(g)) { return AVERROR_INVALIDDATA; } - for (unsigned z = 0; z < s->depth; z++) { + for (unsigned z = 0; z < nb_components; z++) { dest_row = last_line; - for (int remaining_lines = s->height;;) { - linesize = s->width * s->depth; + for (unsigned remaining_lines = height;;) { + linesize = width * nb_components; start_offset = bytestream2_get_be32(&g_table); - bytestream2_seek(&s->g, start_offset, SEEK_SET); - if (s->bytes_per_channel == 1) - ret = expand_rle_row8(s, dest_row + z, linesize, s->depth); + bytestream2_seek(g, start_offset, SEEK_SET); + if (bytes_per_channel == 1) + ret = expand_rle_row8(logctx, dest_row + z, g, + linesize, nb_components); else - ret = expand_rle_row16(s, (uint16_t *)dest_row + z, linesize, s->depth); - if (ret != s->width) + ret = expand_rle_row16(logctx, (uint16_t *)dest_row + z, g, + linesize, nb_components); + if (ret != width) return AVERROR_INVALIDDATA; if (--remaining_lines == 0) break; - dest_row -= s->linesize; + dest_row -= stride; } } return 0; @@ -166,33 +163,34 @@ static int read_rle_sgi(uint8_t *last_line, SgiState *s) * @param s the current image state * @return 0 if read success, else return error code. */ -static int read_uncompressed_sgi(unsigned char *out_buf, SgiState *s) +static int read_uncompressed_sgi(unsigned char *out_buf, GetByteContext *g, + ptrdiff_t stride, unsigned width, unsigned height, + unsigned nb_components, unsigned bytes_per_channel) { - int x, y, z; - unsigned int offset = s->height * s->width * s->bytes_per_channel; + unsigned int offset = height * width * bytes_per_channel; GetByteContext gp[4]; uint8_t *out_end; /* Test buffer size. */ - if (offset * s->depth > bytestream2_get_bytes_left(&s->g)) + if (offset * nb_components > bytestream2_get_bytes_left(g)) return AVERROR_INVALIDDATA; /* Create a reader for each plane */ - for (z = 0; z < s->depth; z++) { - gp[z] = s->g; + for (unsigned z = 0; z < nb_components; z++) { + gp[z] = *g; bytestream2_skip(&gp[z], z * offset); } - for (y = s->height - 1; y >= 0; y--) { - out_end = out_buf + (y * s->linesize); - if (s->bytes_per_channel == 1) { - for (x = s->width; x > 0; x--) - for (z = 0; z < s->depth; z++) + for (int y = height - 1; y >= 0; y--) { + out_end = out_buf + y * stride; + if (bytes_per_channel == 1) { + for (unsigned x = width; x > 0; x--) + for (unsigned z = 0; z < nb_components; z++) *out_end++ = bytestream2_get_byteu(&gp[z]); } else { uint16_t *out16 = (uint16_t *)out_end; - for (x = s->width; x > 0; x--) - for (z = 0; z < s->depth; z++) + for (unsigned x = width; x > 0; x--) + for (unsigned z = 0; z < nb_components; z++) *out16++ = bytestream2_get_ne16u(&gp[z]); } } @@ -202,31 +200,32 @@ static int read_uncompressed_sgi(unsigned char *out_buf, SgiState *s) static int decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { - SgiState *s = avctx->priv_data; - unsigned int dimension, rle; + GetByteContext g; + unsigned int bytes_per_channel, nb_components, dimension, rle, width; + int height; int ret = 0; uint8_t *out_buf, *last_line; - bytestream2_init(&s->g, avpkt->data, avpkt->size); - if (bytestream2_get_bytes_left(&s->g) < SGI_HEADER_SIZE) { + bytestream2_init(&g, avpkt->data, avpkt->size); + if (bytestream2_get_bytes_left(&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_be16u(&s->g) != SGI_MAGIC) { + if (bytestream2_get_be16u(&g) != SGI_MAGIC) { av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); return AVERROR_INVALIDDATA; } - rle = bytestream2_get_byteu(&s->g); - s->bytes_per_channel = bytestream2_get_byteu(&s->g); - dimension = bytestream2_get_be16u(&s->g); - s->width = bytestream2_get_be16u(&s->g); - s->height = bytestream2_get_be16u(&s->g); - s->depth = bytestream2_get_be16u(&s->g); + rle = bytestream2_get_byteu(&g); + bytes_per_channel = bytestream2_get_byteu(&g); + dimension = bytestream2_get_be16u(&g); + width = bytestream2_get_be16u(&g); + height = bytestream2_get_be16u(&g); + nb_components = bytestream2_get_be16u(&g); - if (s->bytes_per_channel != 1 && s->bytes_per_channel != 2) { + if (bytes_per_channel != 1 && bytes_per_channel != 2) { av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); return AVERROR_INVALIDDATA; } @@ -237,18 +236,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, return AVERROR_INVALIDDATA; } - 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; + if (nb_components == SGI_GRAYSCALE) { + avctx->pix_fmt = bytes_per_channel == 2 ? AV_PIX_FMT_GRAY16BE : AV_PIX_FMT_GRAY8; + } else if (nb_components == SGI_RGB) { + avctx->pix_fmt = bytes_per_channel == 2 ? AV_PIX_FMT_RGB48BE : AV_PIX_FMT_RGB24; + } else if (nb_components == SGI_RGBA) { + avctx->pix_fmt = bytes_per_channel == 2 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGBA; } else { av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); return AVERROR_INVALIDDATA; } - ret = ff_set_dimensions(avctx, s->width, s->height); + ret = ff_set_dimensions(avctx, width, height); if (ret < 0) return ret; @@ -259,16 +258,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, p->key_frame = 1; out_buf = p->data[0]; - last_line = out_buf + p->linesize[0] * (s->height - 1); - - s->linesize = p->linesize[0]; + last_line = out_buf + p->linesize[0] * (height - 1); /* Skip header. */ - bytestream2_seek(&s->g, SGI_HEADER_SIZE, SEEK_SET); + bytestream2_seek(&g, SGI_HEADER_SIZE, SEEK_SET); if (rle) { - ret = read_rle_sgi(last_line, s); + ret = read_rle_sgi(avctx, last_line, &g, p->linesize[0], + width, height, nb_components, bytes_per_channel); } else { - ret = read_uncompressed_sgi(out_buf, s); + ret = read_uncompressed_sgi(out_buf, &g, p->linesize[0], + width, height, nb_components, bytes_per_channel); } if (ret) return ret; @@ -277,22 +276,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, return avpkt->size; } -static av_cold int sgi_decode_init(AVCodecContext *avctx) -{ - SgiState *s = avctx->priv_data; - - s->avctx = avctx; - - return 0; -} - const FFCodec ff_sgi_decoder = { .p.name = "sgi", CODEC_LONG_NAME("SGI image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SGI, - .priv_data_size = sizeof(SgiState), FF_CODEC_DECODE_CB(decode_frame), - .init = sgi_decode_init, .p.capabilities = AV_CODEC_CAP_DR1, };