From 34efb8a169e4551326e069be47125c6c2cb7ab90 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Sat, 18 Apr 2015 17:25:20 +0100 Subject: quickdraw: Support direct pixel blocks Data is stored in separated components so rework decode_rle() to support stepping and offsets. --- Changelog | 1 + libavcodec/qdrw.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++----- libavcodec/version.h | 2 +- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/Changelog b/Changelog index 2fd1583c6e..9d73449b09 100644 --- a/Changelog +++ b/Changelog @@ -29,6 +29,7 @@ version : - DTS decoding through libdcadec - Canopus HQ/HQA decoder - Automatically rotate videos based on metadata in avconv +- improved Quickdraw compatibility version 11: diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index a70449d779..1eb2a76691 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -35,6 +35,8 @@ enum QuickdrawOpcodes { PACKBITSRECT = 0x0098, PACKBITSRGN, + DIRECTBITSRECT, + DIRECTBITSRGN, EOP = 0x00FF, }; @@ -64,14 +66,17 @@ static int parse_palette(AVCodecContext *avctx, GetByteContext *gbc, return 0; } -static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc) +static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc, + int step) { - int i; + int i, j; + int offset = avctx->width * step; uint8_t *outdata = p->data[0]; for (i = 0; i < avctx->height; i++) { int size, left, code, pix; uint8_t *out = outdata; + int pos = 0; /* size of packed line */ size = left = bytestream2_get_be16(gbc); @@ -83,12 +88,24 @@ static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc) code = bytestream2_get_byte(gbc); if (code & 0x80 ) { /* run */ pix = bytestream2_get_byte(gbc); - memset(out, pix, 257 - code); - out += 257 - code; + for (j = 0; j < 257 - code; j++) { + out[pos] = pix; + pos += step; + if (pos >= offset) { + pos -= offset; + pos++; + } + } left -= 2; } else { /* copy */ - bytestream2_get_buffer(gbc, out, code + 1); - out += code + 1; + for (j = 0; j < code + 1; j++) { + out[pos] = bytestream2_get_byte(gbc); + pos += step; + if (pos >= offset) { + pos -= offset; + pos++; + } + } left -= 2 + code; } } @@ -134,6 +151,7 @@ static int decode_frame(AVCodecContext *avctx, while (bytestream2_get_bytes_left(&gbc) >= 4) { int bppcnt, bpp; + int rowbytes, pack_type; int opcode = bytestream2_get_be16(&gbc); switch(opcode) { @@ -185,7 +203,63 @@ static int decode_frame(AVCodecContext *avctx, avpriv_report_missing_feature(avctx, "Packbit mask region"); } - ret = decode_rle(avctx, p, &gbc); + ret = decode_rle(avctx, p, &gbc, bppcnt); + if (ret < 0) + return ret; + *got_frame = 1; + break; + case DIRECTBITSRECT: + case DIRECTBITSRGN: + av_log(avctx, AV_LOG_DEBUG, "Parsing Directbit opcode\n"); + + bytestream2_skip(&gbc, 4); + rowbytes = bytestream2_get_be16(&gbc) & 0x3FFF; + if (rowbytes <= 250) { + avpriv_report_missing_feature(avctx, "Short rowbytes"); + return AVERROR_PATCHWELCOME; + } + + bytestream2_skip(&gbc, 10); + pack_type = bytestream2_get_be16(&gbc); + + bytestream2_skip(&gbc, 16); + bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */ + bpp = bytestream2_get_be16(&gbc); /* cmpSize */ + + av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); + if (bppcnt == 3 && bpp == 8) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else if (bppcnt == 4 && bpp == 8) { + avctx->pix_fmt = AV_PIX_FMT_ARGB; + } else { + av_log(avctx, AV_LOG_ERROR, + "Invalid pixel format (bppcnt %d bpp %d) in Directbit\n", + bppcnt, bpp); + return AVERROR_INVALIDDATA; + } + + /* set packing when default is selected */ + if (pack_type == 0) + pack_type = bppcnt; + + if (pack_type != 3 && pack_type != 4) { + avpriv_request_sample(avctx, "Pack type %d", pack_type); + return AVERROR_PATCHWELCOME; + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + /* jump to data */ + bytestream2_skip(&gbc, 30); + + if (opcode == DIRECTBITSRGN) { + bytestream2_skip(&gbc, 2 + 8); /* size + rect */ + avpriv_report_missing_feature(avctx, "DirectBit mask region"); + } + + ret = decode_rle(avctx, p, &gbc, bppcnt); if (ret < 0) return ret; *got_frame = 1; diff --git a/libavcodec/version.h b/libavcodec/version.h index 76020d39e2..50c2b48258 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #define LIBAVCODEC_VERSION_MAJOR 56 #define LIBAVCODEC_VERSION_MINOR 23 -#define LIBAVCODEC_VERSION_MICRO 1 +#define LIBAVCODEC_VERSION_MICRO 2 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ -- cgit v1.2.3