X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fdxtory.c;h=914131e74249d9d6936b3958b06b2446a64cdf8c;hb=a247ac640df3da573cd661065bf53f37863e2b46;hp=285ca38efb8b48875c09130cc2cf65c7e796adb6;hpb=47e12966b75490cfa5fb8ed65a48a9a3d84a7bce;p=ffmpeg diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index 285ca38efb8..914131e7424 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -31,24 +31,84 @@ #include "get_bits.h" #include "internal.h" #include "unary.h" +#include "thread.h" + +static int64_t get_raw_size(enum AVPixelFormat fmt, int width, int height) +{ + switch (fmt) { + case AV_PIX_FMT_RGB555LE: + case AV_PIX_FMT_RGB565LE: + return width * height * 2LL; + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_YUV444P: + return width * height * 3LL; + case AV_PIX_FMT_YUV420P: + return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 1) * AV_CEIL_RSHIFT(height, 1); + case AV_PIX_FMT_YUV410P: + return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 2) * AV_CEIL_RSHIFT(height, 2); + } + + return 0; +} + +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_RGB555LE: + case AV_PIX_FMT_RGB565LE: + 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] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += (AV_CEIL_RSHIFT(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] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += (AV_CEIL_RSHIFT(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) { + ThreadFrame frame = { .f = pic }; int h; uint8_t *dst; int ret; - if (src_size < avctx->width * avctx->height * (int64_t)bpp) { + if (src_size < get_raw_size(id, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = id; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 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,33 +116,47 @@ 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) { + ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V; + int height, width, hmargin, vmargin; + int huvborder; int ret; - if (src_size < FFALIGN(avctx->width, 4) * FFALIGN(avctx->height, 4) * 9LL / 8) { + if (src_size < get_raw_size(AV_PIX_FMT_YUV410P, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = AV_PIX_FMT_YUV410P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + + height = avctx->height & ~3; + width = avctx->width & ~3; + hmargin = avctx->width - width; + vmargin = avctx->height - height; + huvborder = AV_CEIL_RSHIFT(avctx->width, 2) - 1; + Y1 = pic->data[0]; Y2 = pic->data[0] + pic->linesize[0]; Y3 = pic->data[0] + pic->linesize[0] * 2; Y4 = pic->data[0] + pic->linesize[0] * 3; U = pic->data[1]; V = pic->data[2]; - for (h = 0; h < avctx->height; h += 4) { - for (w = 0; w < avctx->width; w += 4) { + for (h = 0; h < height; h += 4) { + for (w = 0; w < width; w += 4) { AV_COPY32U(Y1 + w, src); AV_COPY32U(Y2 + w, src + 4); AV_COPY32U(Y3 + w, src + 8); @@ -91,70 +165,151 @@ static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, V[w >> 2] = src[17] + 0x80; src += 18; } - Y1 += pic->linesize[0] << 2; - Y2 += pic->linesize[0] << 2; - Y3 += pic->linesize[0] << 2; - Y4 += pic->linesize[0] << 2; + if (hmargin) { + for (w = 0; w < hmargin; w++) { + Y1[width + w] = src[w]; + Y2[width + w] = src[w + hmargin * 1]; + Y3[width + w] = src[w + hmargin * 2]; + Y4[width + w] = src[w + hmargin * 3]; + } + src += 4 * hmargin; + U[huvborder] = src[0] + 0x80; + V[huvborder] = src[1] + 0x80; + src += 2; + } + Y1 += pic->linesize[0] * 4; + Y2 += pic->linesize[0] * 4; + Y3 += pic->linesize[0] * 4; + Y4 += pic->linesize[0] * 4; U += pic->linesize[1]; V += pic->linesize[2]; } + if (vmargin) { + for (w = 0; w < width; w += 4) { + AV_COPY32U(Y1 + w, src); + if (vmargin > 1) + AV_COPY32U(Y2 + w, src + 4); + if (vmargin > 2) + AV_COPY32U(Y3 + w, src + 8); + src += 4 * vmargin; + U[w >> 2] = src[0] + 0x80; + V[w >> 2] = src[1] + 0x80; + src += 2; + } + if (hmargin) { + for (w = 0; w < hmargin; w++) { + AV_COPY32U(Y1 + w, src); + if (vmargin > 1) + AV_COPY32U(Y2 + w, src + 4); + if (vmargin > 2) + AV_COPY32U(Y3 + w, src + 8); + src += 4 * vmargin; + } + U[huvborder] = src[0] + 0x80; + V[huvborder] = src[1] + 0x80; + src += 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) { + ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y1, *Y2, *U, *V; + int height, width, hmargin, vmargin; + int huvborder; int ret; - if (src_size < FFALIGN(avctx->width, 2) * FFALIGN(avctx->height, 2) * 3LL / 2) { + if (src_size < get_raw_size(AV_PIX_FMT_YUV420P, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + + height = avctx->height & ~1; + width = avctx->width & ~1; + hmargin = avctx->width - width; + vmargin = avctx->height - height; + huvborder = AV_CEIL_RSHIFT(avctx->width, 1) - 1; + Y1 = pic->data[0]; Y2 = pic->data[0] + pic->linesize[0]; U = pic->data[1]; V = pic->data[2]; - for (h = 0; h < avctx->height; h += 2) { - for (w = 0; w < avctx->width; w += 2) { + for (h = 0; h < height; h += 2) { + for (w = 0; w < width; w += 2) { AV_COPY16(Y1 + w, src); AV_COPY16(Y2 + w, src + 2); U[w >> 1] = src[4] + 0x80; V[w >> 1] = src[5] + 0x80; src += 6; } - Y1 += pic->linesize[0] << 1; - Y2 += pic->linesize[0] << 1; + if (hmargin) { + Y1[width + 1] = src[0]; + Y2[width + 1] = src[1]; + U[huvborder] = src[2] + 0x80; + V[huvborder] = src[3] + 0x80; + src += 4; + } + Y1 += pic->linesize[0] * 2; + Y2 += pic->linesize[0] * 2; U += pic->linesize[1]; V += pic->linesize[2]; } + if (vmargin) { + for (w = 0; w < width; w += 2) { + AV_COPY16U(Y1 + w, src); + U[w >> 1] = src[0] + 0x80; + V[w >> 1] = src[1] + 0x80; + src += 4; + } + if (hmargin) { + Y1[w] = src[0]; + U[huvborder] = src[1] + 0x80; + V[huvborder] = src[2] + 0x80; + src += 3; + } + } + + 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) { + ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y, *U, *V; int ret; - if (src_size < avctx->width * avctx->height * 3LL) { + if (src_size < get_raw_size(AV_PIX_FMT_YUV444P, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = AV_PIX_FMT_YUV444P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + Y = pic->data[0]; U = pic->data[1]; V = pic->data[2]; @@ -169,6 +324,8 @@ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, V += pic->linesize[2]; } + do_vflip(avctx, pic, vflipped); + return 0; } @@ -270,12 +427,15 @@ 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; + ThreadFrame frame = { .f = pic }; + GetByteContext gb, gb_check; GetBitContext gb2; int nslices, slice, line = 0; uint32_t off, slice_size; + uint64_t off_check; uint8_t lru[3][8]; int ret; @@ -283,10 +443,25 @@ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, if (ret < 0) return ret; + off_check = off; + gb_check = gb; + for (slice = 0; slice < nslices; slice++) { + slice_size = bytestream2_get_le32(&gb_check); + + if (slice_size <= 16 + (avctx->height * avctx->width / (8 * nslices))) + return AVERROR_INVALIDDATA; + off_check += slice_size; + } + + if (off_check - avctx->discard_damaged_percentage*off_check/100 > src_size) + return AVERROR_INVALIDDATA; + avctx->pix_fmt = fmt; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + for (slice = 0; slice < nslices; slice++) { slice_size = bytestream2_get_le32(&gb); @@ -308,6 +483,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; } @@ -322,7 +499,7 @@ static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame, int stride = frame->linesize[0]; uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { + for (y = 0; y < left && get_bits_left(gb) >= 3 * width; 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); @@ -365,19 +542,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, @@ -388,7 +566,7 @@ static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, int stride = frame->linesize[0]; uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { + for (y = 0; y < left && get_bits_left(gb) >= 3 * width; 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]); @@ -410,12 +588,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, @@ -433,31 +612,68 @@ static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, 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) > 9 * width; y += 4) { - for (x = 0; x < width; x += 4) { + int h, w, hmargin, vmargin; + int huvborder; + + h = frame->height & ~3; + w = frame->width & ~3; + hmargin = frame->width - w; + vmargin = frame->height - h; + huvborder = AV_CEIL_RSHIFT(frame->width, 2) - 1; + + for (y = 0; y < left - 3 && get_bits_left(gb) >= 18 * w / 4 + hmargin * 4 + (!!hmargin * 2); y += 4) { + for (x = 0; x < w; x += 4) { for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) Y[x + i + j * ystride] = decode_sym(gb, lru[0]); U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; } + if (hmargin) { + for (j = 0; j < 4; j++) + for (i = 0; i < hmargin; i++) + Y[x + i + j * ystride] = decode_sym(gb, lru[0]); + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } - Y += ystride << 2; + Y += ystride * 4; U += ustride; V += vstride; } + if (vmargin && y + vmargin == left) { + for (x = 0; x < width; x += 4) { + for (j = 0; j < vmargin; j++) + for (i = 0; i < 4; i++) + Y[x + i + j * ystride] = decode_sym(gb, lru[0]); + U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; + V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; + } + if (hmargin) { + for (j = 0; j < vmargin; j++) { + for (i = 0; i < hmargin; i++) + Y[x + i + j * ystride] = decode_sym(gb, lru[0]); + } + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } + + y += vmargin; + } + return y; } 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, @@ -476,9 +692,17 @@ static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, uint8_t *U = frame->data[1] + (ustride >> 1) * line; uint8_t *V = frame->data[2] + (vstride >> 1) * line; + int h, w, hmargin, vmargin; + int huvborder; - for (y = 0; y < left - 1 && get_bits_left(gb) > 6 * width; y += 2) { - for (x = 0; x < width; x += 2) { + h = frame->height & ~1; + w = frame->width & ~1; + hmargin = frame->width - w; + vmargin = frame->height - h; + huvborder = AV_CEIL_RSHIFT(frame->width, 1) - 1; + + for (y = 0; y < left - 1 && get_bits_left(gb) >= 3 * w + hmargin * 4; y += 2) { + for (x = 0; x < w; x += 2) { Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]); @@ -486,22 +710,42 @@ static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; } + if (hmargin) { + Y[x + 0 * ystride] = decode_sym(gb, lru[0]); + Y[x + 1 * ystride] = decode_sym(gb, lru[0]); + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } - Y += ystride << 1; + Y += ystride * 2; U += ustride; V += vstride; } + if (vmargin) { + for (x = 0; x < width; x += 2) { + Y[x + 0] = decode_sym(gb, lru[0]); + U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; + V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; + } + if (hmargin) { + Y[x] = decode_sym(gb, lru[0]); + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } + } + return y; } 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, @@ -520,7 +764,7 @@ static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, uint8_t *U = frame->data[1] + ustride * line; uint8_t *V = frame->data[2] + vstride * line; - for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { + for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { for (x = 0; x < width; x++) { Y[x] = decode_sym(gb, lru[0]); U[x] = decode_sym(gb, lru[1]) ^ 0x80; @@ -536,12 +780,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, @@ -549,57 +794,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; } @@ -613,11 +876,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -AVCodec ff_dxtory_decoder = { +const AVCodec ff_dxtory_decoder = { .name = "dxtory", .long_name = NULL_IF_CONFIG_SMALL("Dxtory"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_DXTORY, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, };