diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2015-09-08 14:34:09 +0200 |
---|---|---|
committer | Hendrik Leppkes <h.leppkes@gmail.com> | 2015-09-08 14:34:09 +0200 |
commit | 72773203a64af0a66a4e37fa03bf8744116f517a (patch) | |
tree | e441fca6793e47ee0ca5bf38186838edaf25e2f1 /libavcodec/dxtory.c | |
parent | 8537e249276b36deecfee7cba52d40fdf044d630 (diff) | |
parent | d0f7e4a57fbffa0efb204d4274c3dd56fbfff946 (diff) | |
download | ffmpeg-72773203a64af0a66a4e37fa03bf8744116f517a.tar.gz |
Merge commit 'd0f7e4a57fbffa0efb204d4274c3dd56fbfff946'
* commit 'd0f7e4a57fbffa0efb204d4274c3dd56fbfff946':
dxtory: Unify and rework the decoding routines
Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
Diffstat (limited to 'libavcodec/dxtory.c')
-rw-r--r-- | libavcodec/dxtory.c | 403 |
1 files changed, 164 insertions, 239 deletions
diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index 79e7ab2064..6f68c10889 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -260,144 +260,183 @@ static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8], return val; } -static int dx2_decode_slice_565(GetBitContext *gb, int width, int height, - uint8_t *dst, int stride, int is_565) -{ - int x, y; - int r, g, b; - uint8_t lru[3][8]; - - memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); - memcpy(lru[1], is_565 ? def_lru_565 : def_lru_555, 8 * sizeof(*def_lru)); - memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - b = decode_sym_565(gb, lru[0], 5); - g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); - r = decode_sym_565(gb, lru[2], 5); - dst[x * 3 + 0] = (r << 3) | (r >> 2); - dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2); - dst[x * 3 + 2] = (b << 3) | (b >> 2); - } +typedef int (*decode_slice_func)(GetBitContext *gb, AVFrame *frame, + int line, int height, uint8_t lru[3][8]); - dst += stride; - } - - return 0; -} +typedef void (*setup_lru_func)(uint8_t lru[3][8]); -static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size, int is_565) +static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, + const uint8_t *src, int src_size, + decode_slice_func decode_slice, + setup_lru_func setup_lru, + enum AVPixelFormat fmt) { GetByteContext gb; GetBitContext gb2; - int nslices, slice, slice_height; + int nslices, slice, line = 0; uint32_t off, slice_size; - uint8_t *dst; + uint8_t lru[3][8]; int ret; ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); if (ret < 0) return ret; - slice_height = avctx->height / nslices; - avctx->pix_fmt = AV_PIX_FMT_RGB24; + avctx->pix_fmt = fmt; if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - dst = pic->data[0]; for (slice = 0; slice < nslices; slice++) { slice_size = bytestream2_get_le32(&gb); + setup_lru(lru); + ret = check_slice_size(avctx, src, src_size, slice_size, off); if (ret < 0) return ret; if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) return ret; - dx2_decode_slice_565(&gb2, avctx->width, slice_height, dst, - pic->linesize[0], is_565); - dst += pic->linesize[0] * slice_height; + line += decode_slice(&gb2, pic, line, avctx->height - line, lru); + off += slice_size; } + if (avctx->height - line) { + av_log(avctx, AV_LOG_VERBOSE, + "Not enough slice data available, " + "cropping the frame by %d pixels\n", + avctx->height - line); + avctx->height = line; + } + return 0; } -static int dx2_decode_slice_rgb(GetBitContext *gb, int width, int height, - uint8_t *dst, int stride) +av_always_inline +static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8], + int is_565) { - int x, y, i; - uint8_t lru[3][8]; - - for (i = 0; i < 3; i++) - memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); + int x, y; + int r, g, b; + int width = frame->width; + int stride = frame->linesize[0]; + uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < height; y++) { + for (y = 0; y < left && get_bits_left(gb) > 16; y++) { for (x = 0; x < width; x++) { - dst[x * 3 + 0] = decode_sym(gb, lru[0]); - dst[x * 3 + 1] = decode_sym(gb, lru[1]); - dst[x * 3 + 2] = decode_sym(gb, lru[2]); + b = decode_sym_565(gb, lru[0], 5); + g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); + r = decode_sym_565(gb, lru[2], 5); + dst[x * 3 + 0] = (r << 3) | (r >> 2); + dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2); + dst[x * 3 + 2] = (b << 3) | (b >> 2); } dst += stride; } - return 0; + return y; } -static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) +static void setup_lru_555(uint8_t lru[3][8]) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height; - uint32_t off, slice_size; - uint8_t *dst; - int ret; + memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); + memcpy(lru[1], def_lru_555, 8 * sizeof(*def_lru)); + memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); +} - ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); - if (ret < 0) - return ret; +static void setup_lru_565(uint8_t lru[3][8]) +{ + memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); + memcpy(lru[1], def_lru_565, 8 * sizeof(*def_lru)); + memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); +} - slice_height = avctx->height / nslices; - avctx->pix_fmt = AV_PIX_FMT_BGR24; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; +static int dx2_decode_slice_555(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8]) +{ + return dx2_decode_slice_5x5(gb, frame, line, left, lru, 0); +} - dst = pic->data[0]; - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); +static int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8]) +{ + return dx2_decode_slice_5x5(gb, frame, line, left, lru, 1); +} - ret = check_slice_size(avctx, src, src_size, slice_size, off); - if (ret < 0) - return ret; +static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, + const uint8_t *src, int src_size, int is_565) +{ + enum AVPixelFormat fmt = AV_PIX_FMT_RGB24; + if (is_565) + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_565, + setup_lru_565, + fmt); + else + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_555, + setup_lru_555, + fmt); +} - if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) - return ret; - dx2_decode_slice_rgb(&gb2, avctx->width, slice_height, dst, - pic->linesize[0]); +static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8]) +{ + int x, y; + int width = frame->width; + int stride = frame->linesize[0]; + uint8_t *dst = frame->data[0] + stride * line; - dst += pic->linesize[0] * slice_height; - off += slice_size; + for (y = 0; y < left && get_bits_left(gb) > 16; y++) { + for (x = 0; x < width; x++) { + dst[x * 3 + 0] = decode_sym(gb, lru[0]); + dst[x * 3 + 1] = decode_sym(gb, lru[1]); + dst[x * 3 + 2] = decode_sym(gb, lru[2]); + } + + dst += stride; } - return 0; + return y; } -static int dx2_decode_slice_410(GetBitContext *gb, int width, int height, - uint8_t *Y, uint8_t *U, uint8_t *V, - int ystride, int ustride, int vstride) +static void default_setup_lru(uint8_t lru[3][8]) { - int x, y, i, j; - uint8_t lru[3][8]; + int i; for (i = 0; i < 3; i++) memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); +} + +static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, + const uint8_t *src, int src_size) +{ + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_rgb, + default_setup_lru, + AV_PIX_FMT_BGR24); +} + +static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, + int line, int left, + uint8_t lru[3][8]) +{ + int x, y, i, j; + int width = frame->width; + + int ystride = frame->linesize[0]; + int ustride = frame->linesize[1]; + int vstride = frame->linesize[2]; - for (y = 0; y < height; y += 4) { + uint8_t *Y = frame->data[0] + ystride * line; + uint8_t *U = frame->data[1] + (ustride >> 2) * line; + uint8_t *V = frame->data[2] + (vstride >> 2) * line; + + for (y = 0; y < left - 3 && get_bits_left(gb) > 16; y += 4) { for (x = 0; x < width; x += 4) { for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) @@ -411,75 +450,37 @@ static int dx2_decode_slice_410(GetBitContext *gb, int width, int height, V += vstride; } - return 0; + return y; } + static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height; - int cur_y, next_y; - uint32_t off, slice_size; - uint8_t *Y, *U, *V; - int ret; - - ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); - if (ret < 0) - return ret; - - if ((avctx->width & 3) || (avctx->height & 3)) { - avpriv_request_sample(avctx, "Frame dimensions %dx%d", - avctx->width, avctx->height); - } - - avctx->pix_fmt = AV_PIX_FMT_YUV410P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; - - Y = pic->data[0]; - U = pic->data[1]; - V = pic->data[2]; - - cur_y = 0; - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - next_y = ((slice + 1) * avctx->height) / nslices; - slice_height = (next_y & ~3) - (cur_y & ~3); - - ret = check_slice_size(avctx, src, src_size, slice_size, off); - if (ret < 0) - return ret; - - if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) - return ret; + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_410, + default_setup_lru, + AV_PIX_FMT_YUV410P); +} - dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V, - pic->linesize[0], pic->linesize[1], - pic->linesize[2]); +static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, + int line, int left, + uint8_t lru[3][8]) +{ + int x, y; - Y += pic->linesize[0] * slice_height; - U += pic->linesize[1] * (slice_height >> 2); - V += pic->linesize[2] * (slice_height >> 2); - off += slice_size; - cur_y = next_y; - } + int width = frame->width; - return 0; -} + int ystride = frame->linesize[0]; + int ustride = frame->linesize[1]; + int vstride = frame->linesize[2]; -static int dx2_decode_slice_420(GetBitContext *gb, int width, int height, - uint8_t *Y, uint8_t *U, uint8_t *V, - int ystride, int ustride, int vstride) -{ - int x, y, i; - uint8_t lru[3][8]; + uint8_t *Y = frame->data[0] + ystride * line; + uint8_t *U = frame->data[1] + (ustride >> 1) * line; + uint8_t *V = frame->data[2] + (vstride >> 1) * line; - for (i = 0; i < 3; i++) - memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); - for (y = 0; y < height; y+=2) { + for (y = 0; y < left - 1 && get_bits_left(gb) > 16; y += 2) { for (x = 0; x < width; x += 2) { Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); @@ -494,74 +495,35 @@ static int dx2_decode_slice_420(GetBitContext *gb, int width, int height, V += vstride; } - return 0; + return y; } static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height; - int cur_y, next_y; - uint32_t off, slice_size; - uint8_t *Y, *U, *V; - int ret; - - ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); - if (ret < 0) - return ret; - - if ((avctx->width & 1) || (avctx->height & 1)) { - avpriv_request_sample(avctx, "Frame dimensions %dx%d", - avctx->width, avctx->height); - } - - avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; - - Y = pic->data[0]; - U = pic->data[1]; - V = pic->data[2]; - - cur_y = 0; - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - next_y = ((slice + 1) * avctx->height) / nslices; - slice_height = (next_y & ~1) - (cur_y & ~1); - - ret = check_slice_size(avctx, src, src_size, slice_size, off); - if (ret < 0) - return ret; - - if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) - return ret; - dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V, - pic->linesize[0], pic->linesize[1], - pic->linesize[2]); - - Y += pic->linesize[0] * slice_height; - U += pic->linesize[1] * (slice_height >> 1); - V += pic->linesize[2] * (slice_height >> 1); - off += slice_size; - cur_y = next_y; - } - - return 0; + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_420, + default_setup_lru, + AV_PIX_FMT_YUV420P); } -static int dx2_decode_slice_444(GetBitContext *gb, int width, int height, - uint8_t *Y, uint8_t *U, uint8_t *V, - int ystride, int ustride, int vstride) +static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, + int line, int left, + uint8_t lru[3][8]) { - int x, y, i; - uint8_t lru[3][8]; + int x, y; - for (i = 0; i < 3; i++) - memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); + int width = frame->width; + + int ystride = frame->linesize[0]; + int ustride = frame->linesize[1]; + int vstride = frame->linesize[2]; + + uint8_t *Y = frame->data[0] + ystride * line; + uint8_t *U = frame->data[1] + ustride * line; + uint8_t *V = frame->data[2] + vstride * line; - for (y = 0; y < height; y++) { + for (y = 0; y < left && get_bits_left(gb) > 16; y++) { for (x = 0; x < width; x++) { Y[x] = decode_sym(gb, lru[0]); U[x] = decode_sym(gb, lru[1]) ^ 0x80; @@ -573,53 +535,16 @@ static int dx2_decode_slice_444(GetBitContext *gb, int width, int height, V += vstride; } - return 0; + return y; } static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height; - uint32_t off, slice_size; - uint8_t *Y, *U, *V; - int ret; - - ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); - if (ret < 0) - return ret; - - slice_height = avctx->height / nslices; - - avctx->pix_fmt = AV_PIX_FMT_YUV444P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; - - Y = pic->data[0]; - U = pic->data[1]; - V = pic->data[2]; - - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - - ret = check_slice_size(avctx, src, src_size, slice_size, off); - if (ret < 0) - return ret; - - if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) - return ret; - dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V, - pic->linesize[0], pic->linesize[1], - pic->linesize[2]); - - Y += pic->linesize[0] * slice_height; - U += pic->linesize[1] * slice_height; - V += pic->linesize[2] * slice_height; - off += slice_size; - } - - return 0; + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_444, + default_setup_lru, + AV_PIX_FMT_YUV444P); } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, |