X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fcdxl.c;h=465867c098b8547c00b606572e53787bc7a58789;hb=bdd1567c355a8092e7746ef99e831d579e34fa6a;hp=e23b93421aff7a5a4f03fcb3bc9b0c7a7bcf0ac2;hpb=126daeb5507425d5e9906731d70015d79045d131;p=ffmpeg diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c index e23b93421af..465867c098b 100644 --- a/libavcodec/cdxl.c +++ b/libavcodec/cdxl.c @@ -23,11 +23,20 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "get_bits.h" +#include "internal.h" + +#define BIT_PLANAR 0x00 +#define BYTE_PLANAR 0x20 +#define CHUNKY 0x40 +#define BIT_LINE 0x80 +#define BYTE_LINE 0xC0 typedef struct { AVCodecContext *avctx; AVFrame frame; int bpp; + int format; + int padded_bits; const uint8_t *palette; int palette_size; const uint8_t *video; @@ -40,7 +49,6 @@ static av_cold int cdxl_decode_init(AVCodecContext *avctx) { CDXLVideoContext *c = avctx->priv_data; - avcodec_get_frame_defaults(&c->frame); c->new_video_size = 0; c->avctx = avctx; @@ -62,30 +70,57 @@ static void import_palette(CDXLVideoContext *c, uint32_t *new_palette) static void bitplanar2chunky(CDXLVideoContext *c, int linesize, uint8_t *out) { - int skip = FFALIGN(c->avctx->width, 16) - c->avctx->width; GetBitContext gb; int x, y, plane; init_get_bits(&gb, c->video, c->video_size * 8); - memset(out, 0, linesize * c->avctx->height); for (plane = 0; plane < c->bpp; plane++) { for (y = 0; y < c->avctx->height; y++) { for (x = 0; x < c->avctx->width; x++) out[linesize * y + x] |= get_bits1(&gb) << plane; - skip_bits(&gb, skip); + skip_bits(&gb, c->padded_bits); } } } -static void cdxl_decode_rgb(CDXLVideoContext *c) +static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out) { - uint32_t *new_palette = (uint32_t *)c->frame.data[1]; + GetBitContext gb; + int x, y, plane; + + init_get_bits(&gb, c->video, c->video_size * 8); + for (y = 0; y < c->avctx->height; y++) { + for (plane = 0; plane < c->bpp; plane++) { + for (x = 0; x < c->avctx->width; x++) + out[linesize * y + x] |= get_bits1(&gb) << plane; + skip_bits(&gb, c->padded_bits); + } + } +} + +static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out) +{ + memset(out, 0, linesize * c->avctx->height); + + switch (c->format) { + case BIT_PLANAR: + bitplanar2chunky(c, linesize, out); + break; + case BIT_LINE: + bitline2chunky(c, linesize, out); + break; + } +} + +static void cdxl_decode_rgb(CDXLVideoContext *c, AVFrame *frame) +{ + uint32_t *new_palette = (uint32_t *)frame->data[1]; import_palette(c, new_palette); - bitplanar2chunky(c, c->frame.linesize[0], c->frame.data[0]); + import_format(c, frame->linesize[0], frame->data[0]); } -static void cdxl_decode_ham6(CDXLVideoContext *c) +static void cdxl_decode_ham6(CDXLVideoContext *c, AVFrame *frame) { AVCodecContext *avctx = c->avctx; uint32_t new_palette[16], r, g, b; @@ -93,10 +128,10 @@ static void cdxl_decode_ham6(CDXLVideoContext *c) int x, y; ptr = c->new_video; - out = c->frame.data[0]; + out = frame->data[0]; import_palette(c, new_palette); - bitplanar2chunky(c, avctx->width, c->new_video); + import_format(c, avctx->width, c->new_video); for (y = 0; y < avctx->height; y++) { r = new_palette[0] & 0xFF0000; @@ -124,11 +159,11 @@ static void cdxl_decode_ham6(CDXLVideoContext *c) } AV_WL24(out + x * 3, r | g | b); } - out += c->frame.linesize[0]; + out += frame->linesize[0]; } } -static void cdxl_decode_ham8(CDXLVideoContext *c) +static void cdxl_decode_ham8(CDXLVideoContext *c, AVFrame *frame) { AVCodecContext *avctx = c->avctx; uint32_t new_palette[64], r, g, b; @@ -136,10 +171,10 @@ static void cdxl_decode_ham8(CDXLVideoContext *c) int x, y; ptr = c->new_video; - out = c->frame.data[0]; + out = frame->data[0]; import_palette(c, new_palette); - bitplanar2chunky(c, avctx->width, c->new_video); + import_format(c, avctx->width, c->new_video); for (y = 0; y < avctx->height; y++) { r = new_palette[0] & 0xFF0000; @@ -167,22 +202,22 @@ static void cdxl_decode_ham8(CDXLVideoContext *c) } AV_WL24(out + x * 3, r | g | b); } - out += c->frame.linesize[0]; + out += frame->linesize[0]; } } static int cdxl_decode_frame(AVCodecContext *avctx, void *data, - int *data_size, AVPacket *pkt) + int *got_frame, AVPacket *pkt) { CDXLVideoContext *c = avctx->priv_data; - AVFrame * const p = &c->frame; - int ret, w, h, encoding, format, buf_size = pkt->size; + AVFrame * const p = data; + int ret, w, h, encoding, aligned_width, buf_size = pkt->size; const uint8_t *buf = pkt->data; if (buf_size < 32) return AVERROR_INVALIDDATA; encoding = buf[1] & 7; - format = buf[1] & 0xE0; + c->format = buf[1] & 0xE0; w = AV_RB16(&buf[14]); h = AV_RB16(&buf[16]); c->bpp = buf[19]; @@ -197,12 +232,8 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; if (c->bpp < 1) return AVERROR_INVALIDDATA; - if (c->bpp > 8) { - av_log_ask_for_sample(avctx, "unsupported pixel size: %d\n", c->bpp); - return AVERROR_PATCHWELCOME; - } - if (format) { - av_log_ask_for_sample(avctx, "unsupported pixel format: %d\n", format); + if (c->format != BIT_PLANAR && c->format != BIT_LINE) { + av_log_ask_for_sample(avctx, "unsupported pixel format: 0x%0x\n", c->format); return AVERROR_PATCHWELCOME; } @@ -211,25 +242,23 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data, if (w != avctx->width || h != avctx->height) avcodec_set_dimensions(avctx, w, h); - if (c->video_size < FFALIGN(avctx->width, 16) * avctx->height * c->bpp / 8) + aligned_width = FFALIGN(c->avctx->width, 16); + c->padded_bits = aligned_width - c->avctx->width; + if (c->video_size < aligned_width * avctx->height * c->bpp / 8) return AVERROR_INVALIDDATA; if (!encoding && c->palette_size && c->bpp <= 8) { - avctx->pix_fmt = PIX_FMT_PAL8; + avctx->pix_fmt = AV_PIX_FMT_PAL8; } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) { if (c->palette_size != (1 << (c->bpp - 1))) return AVERROR_INVALIDDATA; - avctx->pix_fmt = PIX_FMT_BGR24; + avctx->pix_fmt = AV_PIX_FMT_BGR24; } else { av_log_ask_for_sample(avctx, "unsupported encoding %d and bpp %d\n", encoding, c->bpp); return AVERROR_PATCHWELCOME; } - if (p->data[0]) - avctx->release_buffer(avctx, p); - - p->reference = 0; - if ((ret = avctx->get_buffer(avctx, p)) < 0) { + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } @@ -241,14 +270,13 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data, if (!c->new_video) return AVERROR(ENOMEM); if (c->bpp == 8) - cdxl_decode_ham8(c); + cdxl_decode_ham8(c, p); else - cdxl_decode_ham6(c); + cdxl_decode_ham6(c, p); } else { - cdxl_decode_rgb(c); + cdxl_decode_rgb(c, p); } - *data_size = sizeof(AVFrame); - *(AVFrame*)data = c->frame; + *got_frame = 1; return buf_size; } @@ -258,8 +286,6 @@ static av_cold int cdxl_decode_end(AVCodecContext *avctx) CDXLVideoContext *c = avctx->priv_data; av_free(c->new_video); - if (c->frame.data[0]) - avctx->release_buffer(avctx, &c->frame); return 0; } @@ -267,7 +293,7 @@ static av_cold int cdxl_decode_end(AVCodecContext *avctx) AVCodec ff_cdxl_decoder = { .name = "cdxl", .type = AVMEDIA_TYPE_VIDEO, - .id = CODEC_ID_CDXL, + .id = AV_CODEC_ID_CDXL, .priv_data_size = sizeof(CDXLVideoContext), .init = cdxl_decode_init, .close = cdxl_decode_end,