From 2d16b6bd3e18f31dbd53f10e337d13ddb4ba6ba0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 2 Sep 2020 17:38:26 +0200 Subject: [PATCH] avcodec/dxtory: add support for vertically flipped frames --- libavcodec/dxtory.c | 144 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 113 insertions(+), 31 deletions(-) diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index 4dd675316b..bc19f27951 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -32,9 +32,44 @@ #include "internal.h" #include "unary.h" +static void do_vflip(AVCodecContext *avctx, AVFrame *pic, int vflip) +{ + if (!vflip) + return; + + switch (pic->format) { + case AV_PIX_FMT_YUV444P: + pic->data[1] += (avctx->height - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += (avctx->height - 1) * pic->linesize[2]; + pic->linesize[2] = -pic->linesize[2]; + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_RGB24: + pic->data[0] += (avctx->height - 1) * pic->linesize[0]; + pic->linesize[0] = -pic->linesize[0]; + break; + case AV_PIX_FMT_YUV410P: + pic->data[0] += (avctx->height - 1) * pic->linesize[0]; + pic->linesize[0] = -pic->linesize[0]; + pic->data[1] += ((avctx->height >> 2) - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += ((avctx->height >> 2) - 1) * pic->linesize[2]; + pic->linesize[2] = -pic->linesize[2]; + break; + case AV_PIX_FMT_YUV420P: + pic->data[0] += (avctx->height - 1) * pic->linesize[0]; + pic->linesize[0] = -pic->linesize[0]; + pic->data[1] += ((avctx->height >> 1) - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += ((avctx->height >> 1) - 1) * pic->linesize[2]; + pic->linesize[2] = -pic->linesize[2]; + break; + } +} + static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, - int id, int bpp) + int id, int bpp, uint32_t vflipped) { int h; uint8_t *dst; @@ -49,6 +84,8 @@ static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + dst = pic->data[0]; for (h = 0; h < avctx->height; h++) { memcpy(dst, src, avctx->width * bpp); @@ -56,11 +93,14 @@ static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, dst += pic->linesize[0]; } + do_vflip(avctx, pic, vflipped); + return 0; } static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { int h, w; uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V; @@ -75,6 +115,8 @@ static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + Y1 = pic->data[0]; Y2 = pic->data[0] + pic->linesize[0]; Y3 = pic->data[0] + pic->linesize[0] * 2; @@ -99,11 +141,14 @@ static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, V += pic->linesize[2]; } + do_vflip(avctx, pic, vflipped); + return 0; } static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { int h, w; uint8_t *Y1, *Y2, *U, *V; @@ -118,6 +163,8 @@ static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + Y1 = pic->data[0]; Y2 = pic->data[0] + pic->linesize[0]; U = pic->data[1]; @@ -136,11 +183,14 @@ static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, V += pic->linesize[2]; } + do_vflip(avctx, pic, vflipped); + return 0; } static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { int h, w; uint8_t *Y, *U, *V; @@ -155,6 +205,8 @@ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + Y = pic->data[0]; U = pic->data[1]; V = pic->data[2]; @@ -169,6 +221,8 @@ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, V += pic->linesize[2]; } + do_vflip(avctx, pic, vflipped); + return 0; } @@ -270,7 +324,8 @@ 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) + enum AVPixelFormat fmt, + uint32_t vflipped) { GetByteContext gb, gb_check; GetBitContext gb2; @@ -301,6 +356,8 @@ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + for (slice = 0; slice < nslices; slice++) { slice_size = bytestream2_get_le32(&gb); @@ -322,6 +379,8 @@ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, avpriv_request_sample(avctx, "Not enough slice data available"); } + do_vflip(avctx, pic, vflipped); + return 0; } @@ -379,19 +438,20 @@ static int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame, } static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size, int is_565) + const uint8_t *src, int src_size, int is_565, + uint32_t vflipped) { 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); + fmt, vflipped); else return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_555, setup_lru_555, - fmt); + fmt, vflipped); } static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, @@ -424,12 +484,13 @@ static void default_setup_lru(uint8_t lru[3][8]) } static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_rgb, default_setup_lru, - AV_PIX_FMT_BGR24); + AV_PIX_FMT_BGR24, vflipped); } static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, @@ -466,12 +527,13 @@ static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_410, default_setup_lru, - AV_PIX_FMT_YUV410P); + AV_PIX_FMT_YUV410P, vflipped); } static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, @@ -510,12 +572,13 @@ static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, } static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_420, default_setup_lru, - AV_PIX_FMT_YUV420P); + AV_PIX_FMT_YUV420P, vflipped); } static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, @@ -550,12 +613,13 @@ static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, } static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_444, default_setup_lru, - AV_PIX_FMT_YUV444P); + AV_PIX_FMT_YUV444P, vflipped); } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, @@ -563,57 +627,75 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, { AVFrame *pic = data; const uint8_t *src = avpkt->data; - int ret; + uint32_t type; + int vflipped, ret; if (avpkt->size < 16) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } - switch (AV_RB32(src)) { + type = AV_RB32(src); + vflipped = !!(type & 0x20); + + switch (type) { + case 0x01000021: case 0x01000001: ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, - AV_PIX_FMT_BGR24, 3); + AV_PIX_FMT_BGR24, 3, vflipped); break; + case 0x01000029: case 0x01000009: - ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x02000021: case 0x02000001: - ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x02000029: case 0x02000009: - ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x03000021: case 0x03000001: - ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x03000029: case 0x03000009: - ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x04000021: case 0x04000001: - ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x04000029: case 0x04000009: - ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x17000021: case 0x17000001: ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, - AV_PIX_FMT_RGB565LE, 2); + AV_PIX_FMT_RGB565LE, 2, vflipped); break; + case 0x17000029: case 0x17000009: - ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1); + ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1, vflipped); break; + case 0x18000021: + case 0x19000021: case 0x18000001: case 0x19000001: ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, - AV_PIX_FMT_RGB555LE, 2); + AV_PIX_FMT_RGB555LE, 2, vflipped); break; + case 0x18000029: + case 0x19000029: case 0x18000009: case 0x19000009: - ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0); + ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0, vflipped); break; default: - avpriv_request_sample(avctx, "Frame header %"PRIX32, AV_RB32(src)); + avpriv_request_sample(avctx, "Frame header %"PRIX32, type); return AVERROR_PATCHWELCOME; }