From: Peter Ross <pross@xvid.org> To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH 2/2] avcodec/ildadec: ILDA Image Data Transfer Format decoder Date: Mon, 22 Aug 2022 20:00:10 +1000 Message-ID: <e380bcfa3d3ab8229dc8a2db7d80fd31b9bb14d8.1661162335.git.pross@xvid.org> (raw) In-Reply-To: <c85a6be48a46f0169c883537a926eb9ed9018e97.1661162335.git.pross@xvid.org> [-- Attachment #1.1: Type: text/plain, Size: 11086 bytes --] Signed-off-by: Peter Ross <pross@xvid.org> --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/ildadec.c | 297 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 307 insertions(+) create mode 100644 libavcodec/ildadec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index cb80f73d99..943144ef7d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -435,6 +435,7 @@ OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o OBJS-$(CONFIG_IDF_DECODER) += bintext.o cga_data.o OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o OBJS-$(CONFIG_ILBC_DECODER) += ilbcdec.o +OBJS-$(CONFIG_ILDA_DECODER) += ildadec.o OBJS-$(CONFIG_IMC_DECODER) += imc.o OBJS-$(CONFIG_IMM4_DECODER) += imm4.o OBJS-$(CONFIG_IMM5_DECODER) += imm5.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 6939a4e25f..42a891bf77 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -171,6 +171,7 @@ extern const FFCodec ff_huffyuv_decoder; extern const FFCodec ff_hymt_decoder; extern const FFCodec ff_idcin_decoder; extern const FFCodec ff_iff_ilbm_decoder; +extern const FFCodec ff_ilda_decoder; extern const FFCodec ff_imm4_decoder; extern const FFCodec ff_imm5_decoder; extern const FFCodec ff_indeo2_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 06dfe55d0f..177a25a5ce 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1909,6 +1909,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("WBMP (Wireless Application Protocol Bitmap) image"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_ILDA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ilda", + .long_name = NULL_IF_CONFIG_SMALL("ILDA Image Data Transfer Format"), + .props = AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 2247bc0309..0152cc57a8 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -318,6 +318,7 @@ enum AVCodecID { AV_CODEC_ID_PHM, AV_CODEC_ID_RADIANCE_HDR, AV_CODEC_ID_WBMP, + AV_CODEC_ID_ILDA, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/ildadec.c b/libavcodec/ildadec.c new file mode 100644 index 0000000000..b5810c911d --- /dev/null +++ b/libavcodec/ildadec.c @@ -0,0 +1,297 @@ +/* + * ILDA Image Data Transfer Format decoder + * Copyright (C) 2020 Peter Ross <pross@xvid.org> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * ILDA Image Data Transfer Format decoder + */ + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/frame.h" +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "codec_internal.h" +#include "internal.h" +#include "mathops.h" + +static const uint8_t default_palette[64][3]={ + {255,0,0}, + {255,16,0}, + {255,32,0}, + {255,48,0}, + {255,64,0}, + {255,80,0}, + {255,96,0}, + {255,112,0}, + {255,128,0}, + {255,144,0}, + {255,160,0}, + {255,176,0}, + {255,192,0}, + {255,208,0}, + {255,224,0}, + {255,240,0}, + {255,255,0}, + {224,255,0}, + {192,255,0}, + {160,255,0}, + {128,255,0}, + {96,255,0}, + {64,255,0}, + {32,255,0}, + {0,255,0}, + {0,255,36}, + {0,255,73}, + {0,255,109}, + {0,255,146}, + {0,255,182}, + {0,255,219}, + {0,255,255}, + {0,227,255}, + {0,198,255}, + {0,170,255}, + {0,142,255}, + {0,113,255}, + {0,85,255}, + {0,56,255}, + {0,28,255}, + {0,0,255}, + {32,0,255}, + {64,0,255}, + {96,0,255}, + {128,0,255}, + {160,0,255}, + {192,0,255}, + {224,0,255}, + {255,0,255}, + {255,32,255}, + {255,64,255}, + {255,96,255}, + {255,128,255}, + {255,160,255}, + {255,192,255}, + {255,224,255}, + {255,255,255}, + {255,224,224}, + {255,192,192}, + {255,160,160}, + {255,128,128}, + {255,96,96}, + {255,64,64}, + {255,32,32}, +}; + +typedef struct { + AVFrame * frame; + uint8_t palette[256][3]; +} ILDAContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + ILDAContext *s = avctx->priv_data; + + if (!avctx->width || !avctx->height) { + int ret = ff_set_dimensions(avctx, 1024, 1024); + if (ret < 0) + return ret; + } + + avctx->pix_fmt = AV_PIX_FMT_RGB24; + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + memcpy(s->palette, default_palette, sizeof(default_palette)); + memset(s->palette + FF_ARRAY_ELEMS(default_palette), 0xFF, sizeof(s->palette) - sizeof(default_palette)); + return 0; +}; + +static void draw_point(uint8_t *const pixels, int linesize, int width, int height, + int x, int y, + const uint8_t *const rgbcolor) +{ + for (int j = FFMAX(y - 1, 0); j < FFMIN(y + 1, height); j++) + for (int i = FFMAX(x - 1, 0); i < FFMIN(x + 1, width); i++) { + pixels[j * linesize + i * 3 + 0] = rgbcolor[0]; + pixels[j * linesize + i * 3 + 1] = rgbcolor[1]; + pixels[j * linesize + i * 3 + 2] = rgbcolor[2]; + } + +} + +static void draw_line(uint8_t *const pixels, int linesize, + int x0, int y0, int x1, int y1, const uint8_t *const rgbcolor) +{ + int dx = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = (dx > dy ? dx : -dy) / 2, e2; + + for (;;) { + pixels[y0 * linesize + x0 * 3 + 0] = rgbcolor[0]; + pixels[y0 * linesize + x0 * 3 + 1] = rgbcolor[1]; + pixels[y0 * linesize + x0 * 3 + 2] = rgbcolor[2]; + + if (x0 == x1 && y0 == y1) + break; + + e2 = err; + + if (e2 >-dx) { + err -= dy; + x0 += sx; + } + + if (e2 < dy) { + err += dx; + y0 += sy; + } + } +} + +static int decode_indexed(AVCodecContext *avctx, const uint8_t *buf, + const uint8_t *buf_end, int nb_entries, int zaxis, int truecolor) +{ + ILDAContext *s = avctx->priv_data; + int ret, x0, y0; + uint8_t * dst; + + ret = ff_reget_buffer(avctx, s->frame, 0); + if (ret < 0) + return ret; + + dst = s->frame->data[0]; + for (int i = 0; i < avctx->height; i++) { + memset(dst, 0, avctx->width * 3); + dst += s->frame->linesize[0]; + } + + if (nb_entries < 2 || buf_end - buf < 6 + zaxis + truecolor) + return 0; + +#define coord(x) sign_extend(AV_RB16(buf + x), 16) +#define get_x ((32768 + coord(0)) * avctx->width) / 65536 +#define get_y (-(coord(2) - 32767) * avctx->height) / 65536 + + x0 = get_x; + y0 = get_y; + buf += 6 + zaxis + truecolor; + + for (int i = 1; i < nb_entries && buf_end - buf >= 6 + zaxis + truecolor; i++) { + int x1 = get_x; + int y1 = get_y; + uint8_t rgb[3]; + uint8_t * color; + if (truecolor) { + rgb[0] = buf[7 + zaxis]; + rgb[1] = buf[6 + zaxis]; + rgb[2] = buf[5 + zaxis]; + color = rgb; + } else + color = s->palette[buf[5 + zaxis]]; + + if (!(buf[4 + zaxis] & 0x40)) { + if (x0 != x1 || y0 != y1) + draw_line(s->frame->data[0], s->frame->linesize[0], x0, y0, x1, y1, color); + else + draw_point(s->frame->data[0], s->frame->linesize[0], avctx->width, avctx->height, x0, y0, color); + } + + x0 = x1; + y0 = y1; + + buf += 6 + zaxis + truecolor; + } + return 0; +} + +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) +{ + ILDAContext *s = avctx->priv_data; + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end = buf + buf_size; + int ret, format, nb_entries; + + if (buf_size < 32) + return -1; + + format = buf[7]; + nb_entries = AV_RB16(buf + 24); + + buf += 32; + + switch (format) { + case 0: + ret = decode_indexed(avctx, buf, buf_end, nb_entries, 2, 0); + break; + case 1: + ret = decode_indexed(avctx, buf, buf_end, nb_entries, 0, 0); + break; + case 2: + memcpy(s->palette, buf, FFMIN((buf_end - buf) / 3, nb_entries) * 3); + return buf_size; + case 4: + ret = decode_indexed(avctx, buf, buf_end, nb_entries, 2, 2); + break; + case 5: + ret = decode_indexed(avctx, buf, buf_end, nb_entries, 0, 2); + break; + default: + avpriv_request_sample(avctx, "unsupported format %d", format); + return buf_size; + } + + if (ret < 0) + return ret; + + *got_frame = 1; + + ret = av_frame_ref(rframe, s->frame); + if (ret < 0) + return ret; + + return buf_size; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + ILDAContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + return 0; +} + +const FFCodec ff_ilda_decoder = { + .p.name = "anm", + .p.long_name = NULL_IF_CONFIG_SMALL("ILDA Image Data Transfer Format"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ILDA, + .priv_data_size = sizeof(ILDAContext), + .init = decode_init, + .close = decode_close, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, +}; -- 2.35.1 -- Peter (A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B) [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] [-- Attachment #2: Type: text/plain, Size: 251 bytes --] _______________________________________________ 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".
prev parent reply other threads:[~2022-08-22 10:00 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-08-22 9:59 [FFmpeg-devel] [PATCH 1/2] avformat/ildadec: ILDA Image Data Transfer Format demuxer Peter Ross 2022-08-22 10:00 ` Peter Ross [this message]
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=e380bcfa3d3ab8229dc8a2db7d80fd31b9bb14d8.1661162335.git.pross@xvid.org \ --to=pross@xvid.org \ --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