On Thu, Mar 20, 2014 at 01:10:06PM +0100, Vittorio Giovara wrote: > --- > Amended as requested. > Thanks for the reviews. > Vittorio > > Changelog | 1 + > doc/general.texi | 2 + > libavcodec/Makefile | 2 + > libavcodec/aliaspixdec.c | 115 +++++++++++++++++++++++++++++++++++++++++ > libavcodec/aliaspixenc.c | 130 > +++++++++++++++++++++++++++++++++++++++++++++++ > libavcodec/allcodecs.c | 1 + > libavcodec/avcodec.h | 1 + > libavcodec/codec_desc.c | 7 +++ > libavcodec/version.h | 4 +- > libavformat/img2.c | 1 + > libavformat/img2enc.c | 2 +- > 11 files changed, 263 insertions(+), 3 deletions(-) > create mode 100644 libavcodec/aliaspixdec.c > create mode 100644 libavcodec/aliaspixenc.c > > diff --git a/Changelog b/Changelog > index 279c0d8..0f1007d 100644 > --- a/Changelog > +++ b/Changelog > @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. > version <next>: > - compand audio filter > - shuffleplanes filter > +- Alias PIX image encoder and decoder > > > version 10: > diff --git a/doc/general.texi b/doc/general.texi > index 8c0cb1b..dce4c0a 100644 > --- a/doc/general.texi > +++ b/doc/general.texi > @@ -424,6 +424,8 @@ following image formats are supported: > @item Name @tab Encoding @tab Decoding @tab Comments > @item .Y.U.V @tab X @tab X > @tab one raw file per component > +@item Alias PIX @tab X @tab X > + @tab Alias/Wavefront PIX image format > @item animated GIF @tab X @tab X > @tab Only uncompressed GIFs are generated. > @item BMP @tab X @tab X > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index c04b3f1..8f531fc 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -88,6 +88,8 @@ OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o > ac3enc.o ac3tab.o ac3.o > OBJS-$(CONFIG_AIC_DECODER) += aic.o > OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o > OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o > +OBJS-$(CONFIG_ALIAS_PIX_DECODER) += aliaspixdec.o > +OBJS-$(CONFIG_ALIAS_PIX_ENCODER) += aliaspixenc.o > OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mpeg4audio.o > OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ > celp_math.o acelp_filters.o \ > diff --git a/libavcodec/aliaspixdec.c b/libavcodec/aliaspixdec.c > new file mode 100644 > index 0000000..aeaa748 > --- /dev/null > +++ b/libavcodec/aliaspixdec.c > @@ -0,0 +1,115 @@ > +/* > + * Alias PIX image
Alias PIX image decoder > + * Copyright (C) 2014 Vittorio Giovara <vittorio.giov...@gmail.com> > + * > + * This file is part of Libav. > + * > + * Libav 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. > + * > + * Libav 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 Libav; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include "avcodec.h" > +#include "bytestream.h" > +#include "internal.h" > + > +#define ALIAS_HEADER_SIZE 10 > + > +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, > + AVPacket *avpkt) > +{ > + AVFrame *f = data; > + GetByteContext gb; > + int width, height, ret, format; > + uint8_t *out_buf; > + uint8_t count, r, g, b; > + int y = 0; > + > + bytestream2_init(&gb, avpkt->data, avpkt->size); > + > + if (bytestream2_get_bytes_left(&gb) < ALIAS_HEADER_SIZE) { > + av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", > avpkt->size); > + return AVERROR_INVALIDDATA; > + } > + > + width = bytestream2_get_be16(&gb); > + height = bytestream2_get_be16(&gb); > + bytestream2_skip(&gb, 4); // obsolete X, Y offset > + format = bytestream2_get_be16(&gb); > + > + if (format == 24) > + avctx->pix_fmt = AV_PIX_FMT_BGR24; > + else if (format == 8) > + avctx->pix_fmt = AV_PIX_FMT_GRAY8; > + else { > + av_log(avctx, AV_LOG_ERROR, "invalid format\n"); > + return AVERROR_INVALIDDATA; > + } > + > + ret = ff_set_dimensions(avctx, width, height); > + if (ret < 0) > + return ret; > + > + ret = ff_get_buffer(avctx, f, 0); > + if (ret < 0) > + return ret; > + > + f->pict_type = AV_PICTURE_TYPE_I; > + f->key_frame = 1; > + > + while (bytestream2_get_bytes_left(&gb) > 0) { > + int i; > + > + /* set buffer at the right position at every new line */ > + if (width == avctx->width) { > + width = 0; > + out_buf = f->data[0] + f->linesize[0] * y++; check for y > height too > + } > + > + /* read packet and copy data */ > + count = bytestream2_get_byte(&gb); > + if (width + count > avctx->width) { > + av_log(avctx, AV_LOG_ERROR, "buffer overrun\n"); nah, too early - but if you don't check then it might happen "invalid run length" or "run length out of bounds" is a better message here > + return AVERROR_INVALIDDATA; > + } > + > + if (avctx->pix_fmt == AV_PIX_FMT_BGR24) { > + r = bytestream2_get_byte(&gb); > + g = bytestream2_get_byte(&gb); > + b = bytestream2_get_byte(&gb); > + for (i = 0; i < count; i++) { > + *out_buf++ = r; > + *out_buf++ = g; > + *out_buf++ = b; > + } > + } else { // AV_PIX_FMT_GRAY8 > + g = bytestream2_get_byte(&gb); > + for (i = 0; i < count; i++) > + *out_buf++ = g; > + } > + > + width += i; > + } > + > + *got_frame = 1; > + return avpkt->size; > +} > + > +AVCodec ff_alias_pix_decoder = { > + .name = "alias_pix", > + .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), > + .type = AVMEDIA_TYPE_VIDEO, > + .id = AV_CODEC_ID_ALIAS_PIX, > + .decode = decode_frame, > + .capabilities = CODEC_CAP_DR1, > +}; > diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c > new file mode 100644 > index 0000000..a969dda > --- /dev/null > +++ b/libavcodec/aliaspixenc.c > @@ -0,0 +1,130 @@ > +/* > + * Alias PIX image Alias PIX image encoder > + * Copyright (C) 2014 Vittorio Giovara <vittorio.giov...@gmail.com> > + * > + * This file is part of Libav. > + * > + * Libav 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. > + * > + * Libav 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 Libav; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include "libavutil/intreadwrite.h" > + > +#include "avcodec.h" > +#include "bytestream.h" > +#include "internal.h" > + > +#define ALIAS_HEADER_SIZE 10 > + > +static av_cold int encode_init(AVCodecContext *avctx) > +{ > + avctx->coded_frame = av_frame_alloc(); > + if (!avctx->coded_frame) > + return AVERROR(ENOMEM); > + return 0; > +} > + > +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, > + const AVFrame *frame, int *got_packet) > +{ > + int width, height, depth, i, j, length, ret; > + uint8_t *in_buf, *buf; > + > + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; > + avctx->coded_frame->key_frame = 1; > + > + width = avctx->width; > + height = avctx->height; > + > + if (width > 65535 || height > 65536) { > + av_log(avctx, AV_LOG_ERROR, "unsupported size %dx%d\n", width, > height); > + return AVERROR_INVALIDDATA; > + } > + > + switch (avctx->pix_fmt) { > + case AV_PIX_FMT_GRAY8: > + depth = 8; > + break; > + case AV_PIX_FMT_RGB24: > + depth = 24; > + break; > + default: > + return AVERROR_INVALIDDATA; > + } > + > + length = ALIAS_HEADER_SIZE + 4 * width * height; // max possible overflow check is missing > + if ((ret = ff_alloc_packet(pkt, length)) < 0) { > + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size > %d.\n", length); > + return ret; > + } > + > + buf = pkt->data; > + > + /* Encode header. */ > + bytestream_put_be16(&buf, width); > + bytestream_put_be16(&buf, height); > + bytestream_put_be32(&buf, 0L); /* X, Y offset */ > + bytestream_put_be16(&buf, depth); > + > + for (j = 0; j < height; j++) { > + in_buf = frame->data[0] + frame->linesize[0] * j; > + for (i = 0; i < width; ) { > + int count = 0; > + int pixel; > + > + if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) { > + pixel = *in_buf; > + while (count < 255 && count + i < width && pixel == *in_buf) > { > + count++; > + in_buf++; > + } > + } else { /* AV_PIX_FMT_RGB24 */ > + pixel = AV_RN32(in_buf) & 0x00FFFFFF; > + while (count < 255 && count + i < width && > + pixel == (AV_RN32(in_buf) & 0x00FFFFFF)) { > + count++; > + in_buf += 3; > + } > + } > + i += count; > + bytestream_put_be32(&buf, (count << depth) | pixel); > + } > + } > + > + /* Total length */ > + pkt->size = buf - pkt->data; > + pkt->flags |= AV_PKT_FLAG_KEY; valign a bit maybe? > + *got_packet = 1; > + > + return 0; > +} > + > +static av_cold int encode_close(AVCodecContext *avctx) > +{ > + av_frame_free(&avctx->coded_frame); > + return 0; > +} > + > +AVCodec ff_alias_pix_encoder = { > + .name = "alias_pix", > + .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), > + .type = AVMEDIA_TYPE_VIDEO, > + .id = AV_CODEC_ID_ALIAS_PIX, > + .init = encode_init, > + .encode2 = encode_frame, > + .close = encode_close, > + .pix_fmts = (const enum AVPixelFormat[]) { > + AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE > + }, > +}; _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel