[FFmpeg-devel] [PATCH] IFF: Add the HAM stuff
Stefano Sabatini
stefano.sabatini-lala
Tue May 11 00:31:52 CEST 2010
On date Sunday 2010-05-09 21:31:53 +0200, Sebastian Vater encoded:
> So now the third part, the new HAM6/8 support patch depending on the two
> other patches:
> IFF: Make lavf/iff.c stop using ff_cmap_read_palette
> IFF: Make ff_cmap_read_palette static, remove ff_ prefix
>
> It's really shorter now and should be much easier to review ;)
Indeed, small patch -> great patch :-).
[...]
> @@ -85,20 +101,71 @@ static const uint64_t plane8_lut[8][256] = {
> static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
> {
> int count, i;
> + IffContext *s = avctx->priv_data;
>
> if (avctx->bits_per_coded_sample > 8) {
> av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
> return AVERROR_INVALIDDATA;
> + } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR) {
> + av_log(avctx, AV_LOG_ERROR, "Transparency not supported\n");
> + return AVERROR_PATCHWELCOME;
> + } else if (s->masking != MASK_NONE) {
> + av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
> + return AVERROR_PATCHWELCOME;
> }
>
> - count = 1 << avctx->bits_per_coded_sample;
> - if (avctx->extradata_size < count * 3) {
> - av_log(avctx, AV_LOG_ERROR, "palette data underflow\n");
> - return AVERROR_INVALIDDATA;
> + if (s->ham) { // adjust HAM color palette
> + count = 1 << s->ham;
> + } else if (s->ehb) { // EHB (ExtraHalfBrite) color palette
> + av_log(avctx, AV_LOG_ERROR, "ExtraHalfBrite (EHB) mode not supported\n");
> + return AVERROR_PATCHWELCOME;
> + } else {
> + count = 1 << avctx->bits_per_coded_sample;
> }
> + if (avctx->extradata_size >= IFF_EXTRA_CONTEXT_SIZE) {
> + count = FFMIN((avctx->extradata_size - IFF_EXTRA_CONTEXT_SIZE) / 3, count);
> + } else {
> + count = FFMIN(avctx->extradata_size / 3, count);
> + }
> + if (pal) { // PIX_FMT_PAL8 or PIX_FMT_GRAY8
> + if (count > 0) {
> for (i=0; i < count; i++) {
> pal[i] = 0xFF000000 | AV_RB24( avctx->extradata + i*3 );
> }
> + } else { // PIX_FMT_GRAY8 has no color palette, create one
> + uint8_t *gray_pal = (uint8_t *) pal;
> + count = 1 << avctx->bits_per_coded_sample;
> +
> + for (i=0; i < count; i++) {
> + gray_pal[i] = (i * 255) >> avctx->bits_per_coded_sample;
> + }
> + }
> + } else { // PIX_FMT_BGR32 for HAM requires color palette
> + s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
> + if (!s->ham_buf)
> + return AVERROR(ENOMEM);
> +
> + if (count > 0) { // HAM with normal color palette
> + s->ham_palbuf = av_malloc((count * sizeof (uint32_t)) + FF_INPUT_BUFFER_PADDING_SIZE);
> + if (!s->ham_palbuf) {
> + av_freep(&s->ham_buf);
> + return AVERROR(ENOMEM);
> + }
> + for (i=0; i < count; i++) {
> + s->ham_palbuf[i] = AV_RL24( avctx->extradata + i*3 );
> + }
> + } else { // HAM with grayscale color palette
> + count = 1 << s->ham;
> + s->ham_palbuf = av_malloc((count * sizeof (uint32_t)) + FF_INPUT_BUFFER_PADDING_SIZE);
> + if (!s->ham_palbuf) {
> + av_freep(&s->ham_buf);
> + return AVERROR(ENOMEM);
> + }
> + for (i=0; i < count; i++) {
> + s->ham_palbuf[i] = le2me_32(GRAY2RGB((i * 255) >> s->ham));
> + }
> + }
> + }
> return 0;
> }
>
> @@ -106,9 +173,19 @@ static av_cold int decode_init(AVCodecContext *avctx)
> {
> IffContext *s = avctx->priv_data;
> int err;
> + const uint8_t *ex = GET_EXTRA_CONTEXT(avctx);
>
> - if (avctx->bits_per_coded_sample <= 8) {
> - avctx->pix_fmt = PIX_FMT_PAL8;
> + if (ex) {
> + s->compression = bytestream_get_byte(&ex);
> + s->ham = bytestream_get_byte(&ex);
> + s->ehb = bytestream_get_byte(&ex);
> + s->masking = bytestream_get_byte(&ex);
> + s->transparency = bytestream_get_be16(&ex);
> + }
> + if ((avctx->bits_per_coded_sample <= 8) && !s->ham) {
> + avctx->pix_fmt = ((avctx->extradata_size == IFF_EXTRA_CONTEXT_SIZE) ||
> + (avctx->extradata_size == 0)) ? PIX_FMT_GRAY8
> + : PIX_FMT_PAL8;
> } else if (avctx->bits_per_coded_sample <= 32) {
> avctx->pix_fmt = PIX_FMT_BGR32;
> } else {
> @@ -167,6 +244,56 @@ static void decodeplane32(uint32_t *dst, const uint8_t *const buf, int buf_size,
> }
> }
>
> +/**
> + * Converts one line of HAM6/8-encoded chunky buffer to 24bpp
> + *
> + * @param dst the destination 24bpp buffer
> + * @param buf the source 8bpp chunky buffer
> + * @param pal lavc palette with alpha channel always at 0
> + * @param buf_size
> + * @param hbits 4 for HAM5/HAM6, 6 for HAM7/HAM8
> + */
> +static void decodehamplane32(uint32_t *dst,
> + const uint8_t *buf,
> + const uint32_t *const pal,
> + const unsigned buf_size,
> + const unsigned hbits)
> +{
> + uint32_t prev = 0;
> + const uint32_t *end = dst + (buf_size * 8);
> + const unsigned mbits = 8 - hbits;
> + const uint32_t mask = (1 << hbits) - 1;
> +
> + for(; dst < end; dst++) {
> + uint32_t tmp;
> + const uint32_t v = *buf++;
> + switch (v >> hbits) {
> + case 0: // take direct color value from palette
> + prev = pal[v & mask];
> + break;
> +
> + case 1: // just modify blue color component
> + tmp = (v & mask) << mbits;
> + tmp |= tmp >> hbits;
> + prev = (prev & 0x00FFFF) | (tmp << 16);
> + break;
> +
> + case 2: // just modify red color component
> + tmp = (v & mask) << mbits;
> + tmp |= tmp >> hbits;
> + prev = (prev & 0xFFFF00) | tmp;
> + break;
> +
> + case 3: // just modify green color component
> + tmp = (v & mask) << mbits;
> + tmp |= tmp >> hbits;
> + prev = (prev & 0xFF00FF) | (tmp << 8);
> + break;
Really just a bikeshed, but this can be slightly factorized:
var = v >> hbits;
if (var == 0) {
...
} else {
tmp = (v & mask) << mbits;
tmp |= tmp >> hbits;
prev = var == 1 ? (prev & 0xFFFF00) | tmp : // blue ...
var == 2 ? ... : // red ...
...
}
> + }
> + *dst = prev;
> + }
> +}
> +
> static int decode_frame_ilbm(AVCodecContext *avctx,
> void *data, int *data_size,
> AVPacket *avpkt)
> @@ -183,7 +310,7 @@ static int decode_frame_ilbm(AVCodecContext *avctx,
> }
>
> if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
> - if (avctx->pix_fmt == PIX_FMT_PAL8) {
> + if ((avctx->pix_fmt == PIX_FMT_PAL8) || (avctx->pix_fmt == PIX_FMT_GRAY8)) {
> for(y = 0; y < avctx->height; y++ ) {
> uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
> memset(row, 0, avctx->width);
> @@ -192,6 +319,16 @@ static int decode_frame_ilbm(AVCodecContext *avctx,
> buf += s->planesize;
> }
> }
> + } else if (s->ham) { // HAM to PIX_FMT_BGR32
> + for(y = 0; y < avctx->height; y++ ) {
> + uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
> + memset(s->ham_buf, 0, avctx->width);
> + for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
> + decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), avctx->bits_per_coded_sample, plane);
> + buf += s->planesize;
> + }
> + decodehamplane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize, s->ham);
> + }
> } else { // PIX_FMT_BGR32
> for(y = 0; y < avctx->height; y++ ) {
> uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
> @@ -202,12 +339,19 @@ static int decode_frame_ilbm(AVCodecContext *avctx,
> }
> }
> }
> - } else if (avctx->pix_fmt == PIX_FMT_PAL8) { // IFF-PBM
> + } else if ((avctx->pix_fmt == PIX_FMT_PAL8) || (avctx->pix_fmt == PIX_FMT_GRAY8)) { // IFF-PBM
> for(y = 0; y < avctx->height; y++ ) {
> uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
> memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
> buf += avctx->width;
> }
> + } else { // IFF-PBM: HAM to PIX_FMT_BGR32
> + for(y = 0; y < avctx->height; y++ ) {
> + uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
> + memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
> + buf += avctx->width;
> + decodehamplane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize, s->ham);
> + }
> }
>
> *data_size = sizeof(AVFrame);
> @@ -231,7 +375,7 @@ static int decode_frame_byterun1(AVCodecContext *avctx,
> }
>
> if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
> - if (avctx->pix_fmt == PIX_FMT_PAL8) {
> + if ((avctx->pix_fmt == PIX_FMT_PAL8) || (avctx->pix_fmt == PIX_FMT_GRAY8)) {
> for(y = 0; y < avctx->height ; y++ ) {
> uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
> memset(row, 0, avctx->width);
> @@ -254,6 +398,30 @@ static int decode_frame_byterun1(AVCodecContext *avctx,
> decodeplane8(row, s->planebuf, s->planesize, avctx->bits_per_coded_sample, plane);
> }
> }
> + } else if (s->ham) { // HAM to PIX_FMT_BGR32
> + for(y = 0; y < avctx->height ; y++ ) {
> + uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
> + memset(s->ham_buf, 0, avctx->width);
> + for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
> + for(x = 0; x < s->planesize && buf < buf_end; ) {
> + const int8_t value = *buf++;
> + unsigned length;
> + if (value >= 0) {
> + length = value + 1;
> + memcpy(s->planebuf + x, buf, FFMIN3(length, s->planesize - x, buf_end - buf));
> + buf += length;
> + } else if (value > -128) {
> + length = -value + 1;
> + memset(s->planebuf + x, *buf++, FFMIN(length, s->planesize - x));
> + } else { // noop
> + continue;
> + }
> + x += length;
> + }
***1
> + decodeplane8(s->ham_buf, s->planebuf, s->planesize, avctx->bits_per_coded_sample, plane);
> + }
> + decodehamplane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize, s->ham);
> + }
> } else { //PIX_FMT_BGR32
> for(y = 0; y < avctx->height ; y++ ) {
> uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
> @@ -278,7 +446,7 @@ static int decode_frame_byterun1(AVCodecContext *avctx,
> }
> }
> }
> - } else {
> + } else if ((avctx->pix_fmt == PIX_FMT_PAL8) || (avctx->pix_fmt == PIX_FMT_GRAY8)) { // IFF-PBM
> for(y = 0; y < avctx->height ; y++ ) {
> uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
> for(x = 0; x < avctx->width && buf < buf_end; ) {
> @@ -297,6 +465,26 @@ static int decode_frame_byterun1(AVCodecContext *avctx,
> x += length;
> }
> }
> + } else { // IFF-PBM: HAM to PIX_FMT_BGR32
> + for(y = 0; y < avctx->height ; y++ ) {
> + uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
> + for(x = 0; x < avctx->width && buf < buf_end; ) {
> + const int8_t value = *buf++;
> + unsigned length;
> + if (value >= 0) {
> + length = value + 1;
> + memcpy(s->ham_buf + x, buf, FFMIN3(length, buf_end - buf, avctx->width - x));
> + buf += length;
> + } else if (value > -128) {
> + length = -value + 1;
> + memset(s->ham_buf + x, *buf++, FFMIN(length, avctx->width - x));
> + } else { // noop
> + continue;
> + }
> + x += length;
***2
Please factorize these (a macro should be fine).
[...]
Regards.
--
FFmpeg = Free & Fostering Mega Ponderous Ecstatic Gadget
More information about the ffmpeg-devel
mailing list