[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