From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> To: ffmpeg-devel@ffmpeg.org Cc: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Subject: [FFmpeg-devel] [PATCH 3/7] avcodec/sgidec: Avoid redundant private context Date: Fri, 30 Sep 2022 19:05:11 +0200 Message-ID: <GV1P250MB0737DD7909017F021886B9328F569@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM> (raw) In-Reply-To: <GV1P250MB073747D27D2794CFC913647A8F569@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM> 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. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- 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, }; -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-09-30 17:05 UTC|newest] Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-09-30 17:02 [FFmpeg-devel] [PATCH 1/7] avcodec/sunrast: Use ptrdiff_t for stride Andreas Rheinhardt 2022-09-30 17:05 ` [FFmpeg-devel] [PATCH 2/7] avcodec/sgidec: Support negative linesizes Andreas Rheinhardt 2022-09-30 17:05 ` Andreas Rheinhardt [this message] 2022-10-04 14:42 ` [FFmpeg-devel] [PATCH 3/7] avcodec/sgidec: Avoid redundant private context Tomas Härdin 2022-09-30 17:05 ` [FFmpeg-devel] [PATCH 4/7] avcodec/sgidec: Use planar pixel formats Andreas Rheinhardt 2022-09-30 17:05 ` [FFmpeg-devel] [PATCH 5/7] avcodec/c93: Fix segfault when using negative linesizes Andreas Rheinhardt 2022-09-30 17:05 ` [FFmpeg-devel] [PATCH 6/7] avcodec/escape124: Fix segfault with " Andreas Rheinhardt 2022-09-30 17:05 ` [FFmpeg-devel] [PATCH 7/7] avcodec/fraps: " Andreas Rheinhardt 2022-10-03 22:05 ` [FFmpeg-devel] [PATCH 1/7] avcodec/sunrast: Use ptrdiff_t for stride Andreas Rheinhardt 2022-10-04 0:03 ` James Almer 2022-10-04 0:25 ` Andreas Rheinhardt
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=GV1P250MB0737DD7909017F021886B9328F569@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM \ --to=andreas.rheinhardt@outlook.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git