| @@ -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; | |||
| } | |||