1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Dxtory decoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2011 Konstantin Shishkov 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <inttypes.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/common.h" 26cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#define BITSTREAM_READER_LE 29cabdff1aSopenharmony_ci#include "avcodec.h" 30cabdff1aSopenharmony_ci#include "bytestream.h" 31cabdff1aSopenharmony_ci#include "codec_internal.h" 32cabdff1aSopenharmony_ci#include "get_bits.h" 33cabdff1aSopenharmony_ci#include "unary.h" 34cabdff1aSopenharmony_ci#include "thread.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_cistatic int64_t get_raw_size(enum AVPixelFormat fmt, int width, int height) 37cabdff1aSopenharmony_ci{ 38cabdff1aSopenharmony_ci switch (fmt) { 39cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB555LE: 40cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB565LE: 41cabdff1aSopenharmony_ci return width * height * 2LL; 42cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB24: 43cabdff1aSopenharmony_ci case AV_PIX_FMT_BGR24: 44cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P: 45cabdff1aSopenharmony_ci return width * height * 3LL; 46cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 47cabdff1aSopenharmony_ci return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 1) * AV_CEIL_RSHIFT(height, 1); 48cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV410P: 49cabdff1aSopenharmony_ci return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 2) * AV_CEIL_RSHIFT(height, 2); 50cabdff1aSopenharmony_ci } 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci return 0; 53cabdff1aSopenharmony_ci} 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_cistatic void do_vflip(AVCodecContext *avctx, AVFrame *pic, int vflip) 56cabdff1aSopenharmony_ci{ 57cabdff1aSopenharmony_ci if (!vflip) 58cabdff1aSopenharmony_ci return; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci switch (pic->format) { 61cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P: 62cabdff1aSopenharmony_ci pic->data[1] += (avctx->height - 1) * pic->linesize[1]; 63cabdff1aSopenharmony_ci pic->linesize[1] = -pic->linesize[1]; 64cabdff1aSopenharmony_ci pic->data[2] += (avctx->height - 1) * pic->linesize[2]; 65cabdff1aSopenharmony_ci pic->linesize[2] = -pic->linesize[2]; 66cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB555LE: 67cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB565LE: 68cabdff1aSopenharmony_ci case AV_PIX_FMT_BGR24: 69cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB24: 70cabdff1aSopenharmony_ci pic->data[0] += (avctx->height - 1) * pic->linesize[0]; 71cabdff1aSopenharmony_ci pic->linesize[0] = -pic->linesize[0]; 72cabdff1aSopenharmony_ci break; 73cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV410P: 74cabdff1aSopenharmony_ci pic->data[0] += (avctx->height - 1) * pic->linesize[0]; 75cabdff1aSopenharmony_ci pic->linesize[0] = -pic->linesize[0]; 76cabdff1aSopenharmony_ci pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[1]; 77cabdff1aSopenharmony_ci pic->linesize[1] = -pic->linesize[1]; 78cabdff1aSopenharmony_ci pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[2]; 79cabdff1aSopenharmony_ci pic->linesize[2] = -pic->linesize[2]; 80cabdff1aSopenharmony_ci break; 81cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 82cabdff1aSopenharmony_ci pic->data[0] += (avctx->height - 1) * pic->linesize[0]; 83cabdff1aSopenharmony_ci pic->linesize[0] = -pic->linesize[0]; 84cabdff1aSopenharmony_ci pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[1]; 85cabdff1aSopenharmony_ci pic->linesize[1] = -pic->linesize[1]; 86cabdff1aSopenharmony_ci pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[2]; 87cabdff1aSopenharmony_ci pic->linesize[2] = -pic->linesize[2]; 88cabdff1aSopenharmony_ci break; 89cabdff1aSopenharmony_ci } 90cabdff1aSopenharmony_ci} 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_cistatic int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, 93cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 94cabdff1aSopenharmony_ci int id, int bpp, uint32_t vflipped) 95cabdff1aSopenharmony_ci{ 96cabdff1aSopenharmony_ci int h; 97cabdff1aSopenharmony_ci uint8_t *dst; 98cabdff1aSopenharmony_ci int ret; 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ci if (src_size < get_raw_size(id, avctx->width, avctx->height)) { 101cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "packet too small\n"); 102cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci avctx->pix_fmt = id; 106cabdff1aSopenharmony_ci if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) 107cabdff1aSopenharmony_ci return ret; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci dst = pic->data[0]; 112cabdff1aSopenharmony_ci for (h = 0; h < avctx->height; h++) { 113cabdff1aSopenharmony_ci memcpy(dst, src, avctx->width * bpp); 114cabdff1aSopenharmony_ci src += avctx->width * bpp; 115cabdff1aSopenharmony_ci dst += pic->linesize[0]; 116cabdff1aSopenharmony_ci } 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci return 0; 121cabdff1aSopenharmony_ci} 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_cistatic int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, 124cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 125cabdff1aSopenharmony_ci uint32_t vflipped) 126cabdff1aSopenharmony_ci{ 127cabdff1aSopenharmony_ci int h, w; 128cabdff1aSopenharmony_ci uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V; 129cabdff1aSopenharmony_ci int height, width, hmargin, vmargin; 130cabdff1aSopenharmony_ci int huvborder; 131cabdff1aSopenharmony_ci int ret; 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci if (src_size < get_raw_size(AV_PIX_FMT_YUV410P, avctx->width, avctx->height)) { 134cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "packet too small\n"); 135cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 136cabdff1aSopenharmony_ci } 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV410P; 139cabdff1aSopenharmony_ci if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) 140cabdff1aSopenharmony_ci return ret; 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci height = avctx->height & ~3; 145cabdff1aSopenharmony_ci width = avctx->width & ~3; 146cabdff1aSopenharmony_ci hmargin = avctx->width - width; 147cabdff1aSopenharmony_ci vmargin = avctx->height - height; 148cabdff1aSopenharmony_ci huvborder = AV_CEIL_RSHIFT(avctx->width, 2) - 1; 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci Y1 = pic->data[0]; 151cabdff1aSopenharmony_ci Y2 = pic->data[0] + pic->linesize[0]; 152cabdff1aSopenharmony_ci Y3 = pic->data[0] + pic->linesize[0] * 2; 153cabdff1aSopenharmony_ci Y4 = pic->data[0] + pic->linesize[0] * 3; 154cabdff1aSopenharmony_ci U = pic->data[1]; 155cabdff1aSopenharmony_ci V = pic->data[2]; 156cabdff1aSopenharmony_ci for (h = 0; h < height; h += 4) { 157cabdff1aSopenharmony_ci for (w = 0; w < width; w += 4) { 158cabdff1aSopenharmony_ci AV_COPY32U(Y1 + w, src); 159cabdff1aSopenharmony_ci AV_COPY32U(Y2 + w, src + 4); 160cabdff1aSopenharmony_ci AV_COPY32U(Y3 + w, src + 8); 161cabdff1aSopenharmony_ci AV_COPY32U(Y4 + w, src + 12); 162cabdff1aSopenharmony_ci U[w >> 2] = src[16] + 0x80; 163cabdff1aSopenharmony_ci V[w >> 2] = src[17] + 0x80; 164cabdff1aSopenharmony_ci src += 18; 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci if (hmargin) { 167cabdff1aSopenharmony_ci for (w = 0; w < hmargin; w++) { 168cabdff1aSopenharmony_ci Y1[width + w] = src[w]; 169cabdff1aSopenharmony_ci Y2[width + w] = src[w + hmargin * 1]; 170cabdff1aSopenharmony_ci Y3[width + w] = src[w + hmargin * 2]; 171cabdff1aSopenharmony_ci Y4[width + w] = src[w + hmargin * 3]; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci src += 4 * hmargin; 174cabdff1aSopenharmony_ci U[huvborder] = src[0] + 0x80; 175cabdff1aSopenharmony_ci V[huvborder] = src[1] + 0x80; 176cabdff1aSopenharmony_ci src += 2; 177cabdff1aSopenharmony_ci } 178cabdff1aSopenharmony_ci Y1 += pic->linesize[0] * 4; 179cabdff1aSopenharmony_ci Y2 += pic->linesize[0] * 4; 180cabdff1aSopenharmony_ci Y3 += pic->linesize[0] * 4; 181cabdff1aSopenharmony_ci Y4 += pic->linesize[0] * 4; 182cabdff1aSopenharmony_ci U += pic->linesize[1]; 183cabdff1aSopenharmony_ci V += pic->linesize[2]; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci if (vmargin) { 187cabdff1aSopenharmony_ci for (w = 0; w < width; w += 4) { 188cabdff1aSopenharmony_ci AV_COPY32U(Y1 + w, src); 189cabdff1aSopenharmony_ci if (vmargin > 1) 190cabdff1aSopenharmony_ci AV_COPY32U(Y2 + w, src + 4); 191cabdff1aSopenharmony_ci if (vmargin > 2) 192cabdff1aSopenharmony_ci AV_COPY32U(Y3 + w, src + 8); 193cabdff1aSopenharmony_ci src += 4 * vmargin; 194cabdff1aSopenharmony_ci U[w >> 2] = src[0] + 0x80; 195cabdff1aSopenharmony_ci V[w >> 2] = src[1] + 0x80; 196cabdff1aSopenharmony_ci src += 2; 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci if (hmargin) { 199cabdff1aSopenharmony_ci for (w = 0; w < hmargin; w++) { 200cabdff1aSopenharmony_ci AV_COPY32U(Y1 + w, src); 201cabdff1aSopenharmony_ci if (vmargin > 1) 202cabdff1aSopenharmony_ci AV_COPY32U(Y2 + w, src + 4); 203cabdff1aSopenharmony_ci if (vmargin > 2) 204cabdff1aSopenharmony_ci AV_COPY32U(Y3 + w, src + 8); 205cabdff1aSopenharmony_ci src += 4 * vmargin; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci U[huvborder] = src[0] + 0x80; 208cabdff1aSopenharmony_ci V[huvborder] = src[1] + 0x80; 209cabdff1aSopenharmony_ci src += 2; 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci return 0; 216cabdff1aSopenharmony_ci} 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_cistatic int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, 219cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 220cabdff1aSopenharmony_ci uint32_t vflipped) 221cabdff1aSopenharmony_ci{ 222cabdff1aSopenharmony_ci int h, w; 223cabdff1aSopenharmony_ci uint8_t *Y1, *Y2, *U, *V; 224cabdff1aSopenharmony_ci int height, width, hmargin, vmargin; 225cabdff1aSopenharmony_ci int huvborder; 226cabdff1aSopenharmony_ci int ret; 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ci if (src_size < get_raw_size(AV_PIX_FMT_YUV420P, avctx->width, avctx->height)) { 229cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "packet too small\n"); 230cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 231cabdff1aSopenharmony_ci } 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV420P; 234cabdff1aSopenharmony_ci if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) 235cabdff1aSopenharmony_ci return ret; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_ci height = avctx->height & ~1; 240cabdff1aSopenharmony_ci width = avctx->width & ~1; 241cabdff1aSopenharmony_ci hmargin = avctx->width - width; 242cabdff1aSopenharmony_ci vmargin = avctx->height - height; 243cabdff1aSopenharmony_ci huvborder = AV_CEIL_RSHIFT(avctx->width, 1) - 1; 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci Y1 = pic->data[0]; 246cabdff1aSopenharmony_ci Y2 = pic->data[0] + pic->linesize[0]; 247cabdff1aSopenharmony_ci U = pic->data[1]; 248cabdff1aSopenharmony_ci V = pic->data[2]; 249cabdff1aSopenharmony_ci for (h = 0; h < height; h += 2) { 250cabdff1aSopenharmony_ci for (w = 0; w < width; w += 2) { 251cabdff1aSopenharmony_ci AV_COPY16(Y1 + w, src); 252cabdff1aSopenharmony_ci AV_COPY16(Y2 + w, src + 2); 253cabdff1aSopenharmony_ci U[w >> 1] = src[4] + 0x80; 254cabdff1aSopenharmony_ci V[w >> 1] = src[5] + 0x80; 255cabdff1aSopenharmony_ci src += 6; 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci if (hmargin) { 258cabdff1aSopenharmony_ci Y1[width + 1] = src[0]; 259cabdff1aSopenharmony_ci Y2[width + 1] = src[1]; 260cabdff1aSopenharmony_ci U[huvborder] = src[2] + 0x80; 261cabdff1aSopenharmony_ci V[huvborder] = src[3] + 0x80; 262cabdff1aSopenharmony_ci src += 4; 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci Y1 += pic->linesize[0] * 2; 265cabdff1aSopenharmony_ci Y2 += pic->linesize[0] * 2; 266cabdff1aSopenharmony_ci U += pic->linesize[1]; 267cabdff1aSopenharmony_ci V += pic->linesize[2]; 268cabdff1aSopenharmony_ci } 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci if (vmargin) { 271cabdff1aSopenharmony_ci for (w = 0; w < width; w += 2) { 272cabdff1aSopenharmony_ci AV_COPY16U(Y1 + w, src); 273cabdff1aSopenharmony_ci U[w >> 1] = src[0] + 0x80; 274cabdff1aSopenharmony_ci V[w >> 1] = src[1] + 0x80; 275cabdff1aSopenharmony_ci src += 4; 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci if (hmargin) { 278cabdff1aSopenharmony_ci Y1[w] = src[0]; 279cabdff1aSopenharmony_ci U[huvborder] = src[1] + 0x80; 280cabdff1aSopenharmony_ci V[huvborder] = src[2] + 0x80; 281cabdff1aSopenharmony_ci src += 3; 282cabdff1aSopenharmony_ci } 283cabdff1aSopenharmony_ci } 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci return 0; 288cabdff1aSopenharmony_ci} 289cabdff1aSopenharmony_ci 290cabdff1aSopenharmony_cistatic int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, 291cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 292cabdff1aSopenharmony_ci uint32_t vflipped) 293cabdff1aSopenharmony_ci{ 294cabdff1aSopenharmony_ci int h, w; 295cabdff1aSopenharmony_ci uint8_t *Y, *U, *V; 296cabdff1aSopenharmony_ci int ret; 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci if (src_size < get_raw_size(AV_PIX_FMT_YUV444P, avctx->width, avctx->height)) { 299cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "packet too small\n"); 300cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 301cabdff1aSopenharmony_ci } 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV444P; 304cabdff1aSopenharmony_ci if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) 305cabdff1aSopenharmony_ci return ret; 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 308cabdff1aSopenharmony_ci 309cabdff1aSopenharmony_ci Y = pic->data[0]; 310cabdff1aSopenharmony_ci U = pic->data[1]; 311cabdff1aSopenharmony_ci V = pic->data[2]; 312cabdff1aSopenharmony_ci for (h = 0; h < avctx->height; h++) { 313cabdff1aSopenharmony_ci for (w = 0; w < avctx->width; w++) { 314cabdff1aSopenharmony_ci Y[w] = *src++; 315cabdff1aSopenharmony_ci U[w] = *src++ ^ 0x80; 316cabdff1aSopenharmony_ci V[w] = *src++ ^ 0x80; 317cabdff1aSopenharmony_ci } 318cabdff1aSopenharmony_ci Y += pic->linesize[0]; 319cabdff1aSopenharmony_ci U += pic->linesize[1]; 320cabdff1aSopenharmony_ci V += pic->linesize[2]; 321cabdff1aSopenharmony_ci } 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci return 0; 326cabdff1aSopenharmony_ci} 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_cistatic const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF }; 329cabdff1aSopenharmony_cistatic const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F }; 330cabdff1aSopenharmony_cistatic const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F }; 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_cistatic inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8]) 333cabdff1aSopenharmony_ci{ 334cabdff1aSopenharmony_ci uint8_t c, val; 335cabdff1aSopenharmony_ci 336cabdff1aSopenharmony_ci c = get_unary(gb, 0, 8); 337cabdff1aSopenharmony_ci if (!c) { 338cabdff1aSopenharmony_ci val = get_bits(gb, 8); 339cabdff1aSopenharmony_ci memmove(lru + 1, lru, sizeof(*lru) * (8 - 1)); 340cabdff1aSopenharmony_ci } else { 341cabdff1aSopenharmony_ci val = lru[c - 1]; 342cabdff1aSopenharmony_ci memmove(lru + 1, lru, sizeof(*lru) * (c - 1)); 343cabdff1aSopenharmony_ci } 344cabdff1aSopenharmony_ci lru[0] = val; 345cabdff1aSopenharmony_ci 346cabdff1aSopenharmony_ci return val; 347cabdff1aSopenharmony_ci} 348cabdff1aSopenharmony_ci 349cabdff1aSopenharmony_cistatic int check_slice_size(AVCodecContext *avctx, 350cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 351cabdff1aSopenharmony_ci int slice_size, int off) 352cabdff1aSopenharmony_ci{ 353cabdff1aSopenharmony_ci int cur_slice_size; 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci if (slice_size > src_size - off) { 356cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 357cabdff1aSopenharmony_ci "invalid slice size %d (only %d bytes left)\n", 358cabdff1aSopenharmony_ci slice_size, src_size - off); 359cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 360cabdff1aSopenharmony_ci } 361cabdff1aSopenharmony_ci if (slice_size <= 16) { 362cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", 363cabdff1aSopenharmony_ci slice_size); 364cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 365cabdff1aSopenharmony_ci } 366cabdff1aSopenharmony_ci 367cabdff1aSopenharmony_ci cur_slice_size = AV_RL32(src + off); 368cabdff1aSopenharmony_ci if (cur_slice_size != slice_size - 16) { 369cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 370cabdff1aSopenharmony_ci "Slice sizes mismatch: got %d instead of %d\n", 371cabdff1aSopenharmony_ci cur_slice_size, slice_size - 16); 372cabdff1aSopenharmony_ci } 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci return 0; 375cabdff1aSopenharmony_ci} 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_cistatic int load_buffer(AVCodecContext *avctx, 378cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 379cabdff1aSopenharmony_ci GetByteContext *gb, 380cabdff1aSopenharmony_ci int *nslices, int *off) 381cabdff1aSopenharmony_ci{ 382cabdff1aSopenharmony_ci bytestream2_init(gb, src, src_size); 383cabdff1aSopenharmony_ci *nslices = bytestream2_get_le16(gb); 384cabdff1aSopenharmony_ci *off = FFALIGN(*nslices * 4 + 2, 16); 385cabdff1aSopenharmony_ci if (src_size < *off) { 386cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "no slice data\n"); 387cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 388cabdff1aSopenharmony_ci } 389cabdff1aSopenharmony_ci 390cabdff1aSopenharmony_ci if (!*nslices) { 391cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "%d slices for %dx%d", *nslices, 392cabdff1aSopenharmony_ci avctx->width, avctx->height); 393cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 394cabdff1aSopenharmony_ci } 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci return 0; 397cabdff1aSopenharmony_ci} 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_cistatic inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8], 400cabdff1aSopenharmony_ci int bits) 401cabdff1aSopenharmony_ci{ 402cabdff1aSopenharmony_ci uint8_t c, val; 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci c = get_unary(gb, 0, bits); 405cabdff1aSopenharmony_ci if (!c) { 406cabdff1aSopenharmony_ci val = get_bits(gb, bits); 407cabdff1aSopenharmony_ci memmove(lru + 1, lru, sizeof(*lru) * (6 - 1)); 408cabdff1aSopenharmony_ci } else { 409cabdff1aSopenharmony_ci val = lru[c - 1]; 410cabdff1aSopenharmony_ci memmove(lru + 1, lru, sizeof(*lru) * (c - 1)); 411cabdff1aSopenharmony_ci } 412cabdff1aSopenharmony_ci lru[0] = val; 413cabdff1aSopenharmony_ci 414cabdff1aSopenharmony_ci return val; 415cabdff1aSopenharmony_ci} 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_citypedef int (*decode_slice_func)(GetBitContext *gb, AVFrame *frame, 418cabdff1aSopenharmony_ci int line, int height, uint8_t lru[3][8]); 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_citypedef void (*setup_lru_func)(uint8_t lru[3][8]); 421cabdff1aSopenharmony_ci 422cabdff1aSopenharmony_cistatic int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, 423cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 424cabdff1aSopenharmony_ci decode_slice_func decode_slice, 425cabdff1aSopenharmony_ci setup_lru_func setup_lru, 426cabdff1aSopenharmony_ci enum AVPixelFormat fmt, 427cabdff1aSopenharmony_ci uint32_t vflipped) 428cabdff1aSopenharmony_ci{ 429cabdff1aSopenharmony_ci GetByteContext gb, gb_check; 430cabdff1aSopenharmony_ci GetBitContext gb2; 431cabdff1aSopenharmony_ci int nslices, slice, line = 0; 432cabdff1aSopenharmony_ci uint32_t off, slice_size; 433cabdff1aSopenharmony_ci uint64_t off_check; 434cabdff1aSopenharmony_ci uint8_t lru[3][8]; 435cabdff1aSopenharmony_ci int ret; 436cabdff1aSopenharmony_ci 437cabdff1aSopenharmony_ci ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); 438cabdff1aSopenharmony_ci if (ret < 0) 439cabdff1aSopenharmony_ci return ret; 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ci off_check = off; 442cabdff1aSopenharmony_ci gb_check = gb; 443cabdff1aSopenharmony_ci for (slice = 0; slice < nslices; slice++) { 444cabdff1aSopenharmony_ci slice_size = bytestream2_get_le32(&gb_check); 445cabdff1aSopenharmony_ci 446cabdff1aSopenharmony_ci if (slice_size <= 16 + (avctx->height * avctx->width / (8 * nslices))) 447cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 448cabdff1aSopenharmony_ci off_check += slice_size; 449cabdff1aSopenharmony_ci } 450cabdff1aSopenharmony_ci 451cabdff1aSopenharmony_ci if (off_check - avctx->discard_damaged_percentage*off_check/100 > src_size) 452cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 453cabdff1aSopenharmony_ci 454cabdff1aSopenharmony_ci avctx->pix_fmt = fmt; 455cabdff1aSopenharmony_ci if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) 456cabdff1aSopenharmony_ci return ret; 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci for (slice = 0; slice < nslices; slice++) { 461cabdff1aSopenharmony_ci slice_size = bytestream2_get_le32(&gb); 462cabdff1aSopenharmony_ci 463cabdff1aSopenharmony_ci setup_lru(lru); 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_ci ret = check_slice_size(avctx, src, src_size, slice_size, off); 466cabdff1aSopenharmony_ci if (ret < 0) 467cabdff1aSopenharmony_ci return ret; 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) 470cabdff1aSopenharmony_ci return ret; 471cabdff1aSopenharmony_ci 472cabdff1aSopenharmony_ci line += decode_slice(&gb2, pic, line, avctx->height - line, lru); 473cabdff1aSopenharmony_ci 474cabdff1aSopenharmony_ci off += slice_size; 475cabdff1aSopenharmony_ci } 476cabdff1aSopenharmony_ci 477cabdff1aSopenharmony_ci if (avctx->height - line) { 478cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Not enough slice data available"); 479cabdff1aSopenharmony_ci } 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_ci do_vflip(avctx, pic, vflipped); 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci return 0; 484cabdff1aSopenharmony_ci} 485cabdff1aSopenharmony_ci 486cabdff1aSopenharmony_ciav_always_inline 487cabdff1aSopenharmony_cistatic int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame, 488cabdff1aSopenharmony_ci int line, int left, uint8_t lru[3][8], 489cabdff1aSopenharmony_ci int is_565) 490cabdff1aSopenharmony_ci{ 491cabdff1aSopenharmony_ci int x, y; 492cabdff1aSopenharmony_ci int r, g, b; 493cabdff1aSopenharmony_ci int width = frame->width; 494cabdff1aSopenharmony_ci int stride = frame->linesize[0]; 495cabdff1aSopenharmony_ci uint8_t *dst = frame->data[0] + stride * line; 496cabdff1aSopenharmony_ci 497cabdff1aSopenharmony_ci for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { 498cabdff1aSopenharmony_ci for (x = 0; x < width; x++) { 499cabdff1aSopenharmony_ci b = decode_sym_565(gb, lru[0], 5); 500cabdff1aSopenharmony_ci g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); 501cabdff1aSopenharmony_ci r = decode_sym_565(gb, lru[2], 5); 502cabdff1aSopenharmony_ci dst[x * 3 + 0] = (r << 3) | (r >> 2); 503cabdff1aSopenharmony_ci dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2); 504cabdff1aSopenharmony_ci dst[x * 3 + 2] = (b << 3) | (b >> 2); 505cabdff1aSopenharmony_ci } 506cabdff1aSopenharmony_ci 507cabdff1aSopenharmony_ci dst += stride; 508cabdff1aSopenharmony_ci } 509cabdff1aSopenharmony_ci 510cabdff1aSopenharmony_ci return y; 511cabdff1aSopenharmony_ci} 512cabdff1aSopenharmony_ci 513cabdff1aSopenharmony_cistatic void setup_lru_555(uint8_t lru[3][8]) 514cabdff1aSopenharmony_ci{ 515cabdff1aSopenharmony_ci memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); 516cabdff1aSopenharmony_ci memcpy(lru[1], def_lru_555, 8 * sizeof(*def_lru)); 517cabdff1aSopenharmony_ci memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); 518cabdff1aSopenharmony_ci} 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_cistatic void setup_lru_565(uint8_t lru[3][8]) 521cabdff1aSopenharmony_ci{ 522cabdff1aSopenharmony_ci memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); 523cabdff1aSopenharmony_ci memcpy(lru[1], def_lru_565, 8 * sizeof(*def_lru)); 524cabdff1aSopenharmony_ci memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); 525cabdff1aSopenharmony_ci} 526cabdff1aSopenharmony_ci 527cabdff1aSopenharmony_cistatic int dx2_decode_slice_555(GetBitContext *gb, AVFrame *frame, 528cabdff1aSopenharmony_ci int line, int left, uint8_t lru[3][8]) 529cabdff1aSopenharmony_ci{ 530cabdff1aSopenharmony_ci return dx2_decode_slice_5x5(gb, frame, line, left, lru, 0); 531cabdff1aSopenharmony_ci} 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_cistatic int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame, 534cabdff1aSopenharmony_ci int line, int left, uint8_t lru[3][8]) 535cabdff1aSopenharmony_ci{ 536cabdff1aSopenharmony_ci return dx2_decode_slice_5x5(gb, frame, line, left, lru, 1); 537cabdff1aSopenharmony_ci} 538cabdff1aSopenharmony_ci 539cabdff1aSopenharmony_cistatic int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, 540cabdff1aSopenharmony_ci const uint8_t *src, int src_size, int is_565, 541cabdff1aSopenharmony_ci uint32_t vflipped) 542cabdff1aSopenharmony_ci{ 543cabdff1aSopenharmony_ci enum AVPixelFormat fmt = AV_PIX_FMT_RGB24; 544cabdff1aSopenharmony_ci if (is_565) 545cabdff1aSopenharmony_ci return dxtory_decode_v2(avctx, pic, src, src_size, 546cabdff1aSopenharmony_ci dx2_decode_slice_565, 547cabdff1aSopenharmony_ci setup_lru_565, 548cabdff1aSopenharmony_ci fmt, vflipped); 549cabdff1aSopenharmony_ci else 550cabdff1aSopenharmony_ci return dxtory_decode_v2(avctx, pic, src, src_size, 551cabdff1aSopenharmony_ci dx2_decode_slice_555, 552cabdff1aSopenharmony_ci setup_lru_555, 553cabdff1aSopenharmony_ci fmt, vflipped); 554cabdff1aSopenharmony_ci} 555cabdff1aSopenharmony_ci 556cabdff1aSopenharmony_cistatic int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, 557cabdff1aSopenharmony_ci int line, int left, uint8_t lru[3][8]) 558cabdff1aSopenharmony_ci{ 559cabdff1aSopenharmony_ci int x, y; 560cabdff1aSopenharmony_ci int width = frame->width; 561cabdff1aSopenharmony_ci int stride = frame->linesize[0]; 562cabdff1aSopenharmony_ci uint8_t *dst = frame->data[0] + stride * line; 563cabdff1aSopenharmony_ci 564cabdff1aSopenharmony_ci for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { 565cabdff1aSopenharmony_ci for (x = 0; x < width; x++) { 566cabdff1aSopenharmony_ci dst[x * 3 + 0] = decode_sym(gb, lru[0]); 567cabdff1aSopenharmony_ci dst[x * 3 + 1] = decode_sym(gb, lru[1]); 568cabdff1aSopenharmony_ci dst[x * 3 + 2] = decode_sym(gb, lru[2]); 569cabdff1aSopenharmony_ci } 570cabdff1aSopenharmony_ci 571cabdff1aSopenharmony_ci dst += stride; 572cabdff1aSopenharmony_ci } 573cabdff1aSopenharmony_ci 574cabdff1aSopenharmony_ci return y; 575cabdff1aSopenharmony_ci} 576cabdff1aSopenharmony_ci 577cabdff1aSopenharmony_cistatic void default_setup_lru(uint8_t lru[3][8]) 578cabdff1aSopenharmony_ci{ 579cabdff1aSopenharmony_ci int i; 580cabdff1aSopenharmony_ci 581cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) 582cabdff1aSopenharmony_ci memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); 583cabdff1aSopenharmony_ci} 584cabdff1aSopenharmony_ci 585cabdff1aSopenharmony_cistatic int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, 586cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 587cabdff1aSopenharmony_ci uint32_t vflipped) 588cabdff1aSopenharmony_ci{ 589cabdff1aSopenharmony_ci return dxtory_decode_v2(avctx, pic, src, src_size, 590cabdff1aSopenharmony_ci dx2_decode_slice_rgb, 591cabdff1aSopenharmony_ci default_setup_lru, 592cabdff1aSopenharmony_ci AV_PIX_FMT_BGR24, vflipped); 593cabdff1aSopenharmony_ci} 594cabdff1aSopenharmony_ci 595cabdff1aSopenharmony_cistatic int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, 596cabdff1aSopenharmony_ci int line, int left, 597cabdff1aSopenharmony_ci uint8_t lru[3][8]) 598cabdff1aSopenharmony_ci{ 599cabdff1aSopenharmony_ci int x, y, i, j; 600cabdff1aSopenharmony_ci int width = frame->width; 601cabdff1aSopenharmony_ci 602cabdff1aSopenharmony_ci int ystride = frame->linesize[0]; 603cabdff1aSopenharmony_ci int ustride = frame->linesize[1]; 604cabdff1aSopenharmony_ci int vstride = frame->linesize[2]; 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_ci uint8_t *Y = frame->data[0] + ystride * line; 607cabdff1aSopenharmony_ci uint8_t *U = frame->data[1] + (ustride >> 2) * line; 608cabdff1aSopenharmony_ci uint8_t *V = frame->data[2] + (vstride >> 2) * line; 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci int h, w, hmargin, vmargin; 611cabdff1aSopenharmony_ci int huvborder; 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_ci h = frame->height & ~3; 614cabdff1aSopenharmony_ci w = frame->width & ~3; 615cabdff1aSopenharmony_ci hmargin = frame->width - w; 616cabdff1aSopenharmony_ci vmargin = frame->height - h; 617cabdff1aSopenharmony_ci huvborder = AV_CEIL_RSHIFT(frame->width, 2) - 1; 618cabdff1aSopenharmony_ci 619cabdff1aSopenharmony_ci for (y = 0; y < left - 3 && get_bits_left(gb) >= 18 * w / 4 + hmargin * 4 + (!!hmargin * 2); y += 4) { 620cabdff1aSopenharmony_ci for (x = 0; x < w; x += 4) { 621cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) 622cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 623cabdff1aSopenharmony_ci Y[x + i + j * ystride] = decode_sym(gb, lru[0]); 624cabdff1aSopenharmony_ci U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; 625cabdff1aSopenharmony_ci V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; 626cabdff1aSopenharmony_ci } 627cabdff1aSopenharmony_ci if (hmargin) { 628cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) 629cabdff1aSopenharmony_ci for (i = 0; i < hmargin; i++) 630cabdff1aSopenharmony_ci Y[x + i + j * ystride] = decode_sym(gb, lru[0]); 631cabdff1aSopenharmony_ci U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; 632cabdff1aSopenharmony_ci V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; 633cabdff1aSopenharmony_ci } 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci Y += ystride * 4; 636cabdff1aSopenharmony_ci U += ustride; 637cabdff1aSopenharmony_ci V += vstride; 638cabdff1aSopenharmony_ci } 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci if (vmargin && y + vmargin == left) { 641cabdff1aSopenharmony_ci for (x = 0; x < width; x += 4) { 642cabdff1aSopenharmony_ci for (j = 0; j < vmargin; j++) 643cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 644cabdff1aSopenharmony_ci Y[x + i + j * ystride] = decode_sym(gb, lru[0]); 645cabdff1aSopenharmony_ci U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; 646cabdff1aSopenharmony_ci V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; 647cabdff1aSopenharmony_ci } 648cabdff1aSopenharmony_ci if (hmargin) { 649cabdff1aSopenharmony_ci for (j = 0; j < vmargin; j++) { 650cabdff1aSopenharmony_ci for (i = 0; i < hmargin; i++) 651cabdff1aSopenharmony_ci Y[x + i + j * ystride] = decode_sym(gb, lru[0]); 652cabdff1aSopenharmony_ci } 653cabdff1aSopenharmony_ci U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; 654cabdff1aSopenharmony_ci V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; 655cabdff1aSopenharmony_ci } 656cabdff1aSopenharmony_ci 657cabdff1aSopenharmony_ci y += vmargin; 658cabdff1aSopenharmony_ci } 659cabdff1aSopenharmony_ci 660cabdff1aSopenharmony_ci return y; 661cabdff1aSopenharmony_ci} 662cabdff1aSopenharmony_ci 663cabdff1aSopenharmony_ci 664cabdff1aSopenharmony_cistatic int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, 665cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 666cabdff1aSopenharmony_ci uint32_t vflipped) 667cabdff1aSopenharmony_ci{ 668cabdff1aSopenharmony_ci return dxtory_decode_v2(avctx, pic, src, src_size, 669cabdff1aSopenharmony_ci dx2_decode_slice_410, 670cabdff1aSopenharmony_ci default_setup_lru, 671cabdff1aSopenharmony_ci AV_PIX_FMT_YUV410P, vflipped); 672cabdff1aSopenharmony_ci} 673cabdff1aSopenharmony_ci 674cabdff1aSopenharmony_cistatic int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, 675cabdff1aSopenharmony_ci int line, int left, 676cabdff1aSopenharmony_ci uint8_t lru[3][8]) 677cabdff1aSopenharmony_ci{ 678cabdff1aSopenharmony_ci int x, y; 679cabdff1aSopenharmony_ci 680cabdff1aSopenharmony_ci int width = frame->width; 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_ci int ystride = frame->linesize[0]; 683cabdff1aSopenharmony_ci int ustride = frame->linesize[1]; 684cabdff1aSopenharmony_ci int vstride = frame->linesize[2]; 685cabdff1aSopenharmony_ci 686cabdff1aSopenharmony_ci uint8_t *Y = frame->data[0] + ystride * line; 687cabdff1aSopenharmony_ci uint8_t *U = frame->data[1] + (ustride >> 1) * line; 688cabdff1aSopenharmony_ci uint8_t *V = frame->data[2] + (vstride >> 1) * line; 689cabdff1aSopenharmony_ci 690cabdff1aSopenharmony_ci int h, w, hmargin, vmargin; 691cabdff1aSopenharmony_ci int huvborder; 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci h = frame->height & ~1; 694cabdff1aSopenharmony_ci w = frame->width & ~1; 695cabdff1aSopenharmony_ci hmargin = frame->width - w; 696cabdff1aSopenharmony_ci vmargin = frame->height - h; 697cabdff1aSopenharmony_ci huvborder = AV_CEIL_RSHIFT(frame->width, 1) - 1; 698cabdff1aSopenharmony_ci 699cabdff1aSopenharmony_ci for (y = 0; y < left - 1 && get_bits_left(gb) >= 3 * w + hmargin * 4; y += 2) { 700cabdff1aSopenharmony_ci for (x = 0; x < w; x += 2) { 701cabdff1aSopenharmony_ci Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); 702cabdff1aSopenharmony_ci Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); 703cabdff1aSopenharmony_ci Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]); 704cabdff1aSopenharmony_ci Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]); 705cabdff1aSopenharmony_ci U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; 706cabdff1aSopenharmony_ci V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; 707cabdff1aSopenharmony_ci } 708cabdff1aSopenharmony_ci if (hmargin) { 709cabdff1aSopenharmony_ci Y[x + 0 * ystride] = decode_sym(gb, lru[0]); 710cabdff1aSopenharmony_ci Y[x + 1 * ystride] = decode_sym(gb, lru[0]); 711cabdff1aSopenharmony_ci U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; 712cabdff1aSopenharmony_ci V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; 713cabdff1aSopenharmony_ci } 714cabdff1aSopenharmony_ci 715cabdff1aSopenharmony_ci Y += ystride * 2; 716cabdff1aSopenharmony_ci U += ustride; 717cabdff1aSopenharmony_ci V += vstride; 718cabdff1aSopenharmony_ci } 719cabdff1aSopenharmony_ci 720cabdff1aSopenharmony_ci if (vmargin) { 721cabdff1aSopenharmony_ci for (x = 0; x < width; x += 2) { 722cabdff1aSopenharmony_ci Y[x + 0] = decode_sym(gb, lru[0]); 723cabdff1aSopenharmony_ci U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; 724cabdff1aSopenharmony_ci V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; 725cabdff1aSopenharmony_ci } 726cabdff1aSopenharmony_ci if (hmargin) { 727cabdff1aSopenharmony_ci Y[x] = decode_sym(gb, lru[0]); 728cabdff1aSopenharmony_ci U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; 729cabdff1aSopenharmony_ci V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; 730cabdff1aSopenharmony_ci } 731cabdff1aSopenharmony_ci } 732cabdff1aSopenharmony_ci 733cabdff1aSopenharmony_ci return y; 734cabdff1aSopenharmony_ci} 735cabdff1aSopenharmony_ci 736cabdff1aSopenharmony_cistatic int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, 737cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 738cabdff1aSopenharmony_ci uint32_t vflipped) 739cabdff1aSopenharmony_ci{ 740cabdff1aSopenharmony_ci return dxtory_decode_v2(avctx, pic, src, src_size, 741cabdff1aSopenharmony_ci dx2_decode_slice_420, 742cabdff1aSopenharmony_ci default_setup_lru, 743cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, vflipped); 744cabdff1aSopenharmony_ci} 745cabdff1aSopenharmony_ci 746cabdff1aSopenharmony_cistatic int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, 747cabdff1aSopenharmony_ci int line, int left, 748cabdff1aSopenharmony_ci uint8_t lru[3][8]) 749cabdff1aSopenharmony_ci{ 750cabdff1aSopenharmony_ci int x, y; 751cabdff1aSopenharmony_ci 752cabdff1aSopenharmony_ci int width = frame->width; 753cabdff1aSopenharmony_ci 754cabdff1aSopenharmony_ci int ystride = frame->linesize[0]; 755cabdff1aSopenharmony_ci int ustride = frame->linesize[1]; 756cabdff1aSopenharmony_ci int vstride = frame->linesize[2]; 757cabdff1aSopenharmony_ci 758cabdff1aSopenharmony_ci uint8_t *Y = frame->data[0] + ystride * line; 759cabdff1aSopenharmony_ci uint8_t *U = frame->data[1] + ustride * line; 760cabdff1aSopenharmony_ci uint8_t *V = frame->data[2] + vstride * line; 761cabdff1aSopenharmony_ci 762cabdff1aSopenharmony_ci for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { 763cabdff1aSopenharmony_ci for (x = 0; x < width; x++) { 764cabdff1aSopenharmony_ci Y[x] = decode_sym(gb, lru[0]); 765cabdff1aSopenharmony_ci U[x] = decode_sym(gb, lru[1]) ^ 0x80; 766cabdff1aSopenharmony_ci V[x] = decode_sym(gb, lru[2]) ^ 0x80; 767cabdff1aSopenharmony_ci } 768cabdff1aSopenharmony_ci 769cabdff1aSopenharmony_ci Y += ystride; 770cabdff1aSopenharmony_ci U += ustride; 771cabdff1aSopenharmony_ci V += vstride; 772cabdff1aSopenharmony_ci } 773cabdff1aSopenharmony_ci 774cabdff1aSopenharmony_ci return y; 775cabdff1aSopenharmony_ci} 776cabdff1aSopenharmony_ci 777cabdff1aSopenharmony_cistatic int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, 778cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 779cabdff1aSopenharmony_ci uint32_t vflipped) 780cabdff1aSopenharmony_ci{ 781cabdff1aSopenharmony_ci return dxtory_decode_v2(avctx, pic, src, src_size, 782cabdff1aSopenharmony_ci dx2_decode_slice_444, 783cabdff1aSopenharmony_ci default_setup_lru, 784cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, vflipped); 785cabdff1aSopenharmony_ci} 786cabdff1aSopenharmony_ci 787cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *pic, 788cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 789cabdff1aSopenharmony_ci{ 790cabdff1aSopenharmony_ci const uint8_t *src = avpkt->data; 791cabdff1aSopenharmony_ci uint32_t type; 792cabdff1aSopenharmony_ci int vflipped, ret; 793cabdff1aSopenharmony_ci 794cabdff1aSopenharmony_ci if (avpkt->size < 16) { 795cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "packet too small\n"); 796cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 797cabdff1aSopenharmony_ci } 798cabdff1aSopenharmony_ci 799cabdff1aSopenharmony_ci type = AV_RB32(src); 800cabdff1aSopenharmony_ci vflipped = !!(type & 0x20); 801cabdff1aSopenharmony_ci 802cabdff1aSopenharmony_ci switch (type) { 803cabdff1aSopenharmony_ci case 0x01000021: 804cabdff1aSopenharmony_ci case 0x01000001: 805cabdff1aSopenharmony_ci ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, 806cabdff1aSopenharmony_ci AV_PIX_FMT_BGR24, 3, vflipped); 807cabdff1aSopenharmony_ci break; 808cabdff1aSopenharmony_ci case 0x01000029: 809cabdff1aSopenharmony_ci case 0x01000009: 810cabdff1aSopenharmony_ci ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16, vflipped); 811cabdff1aSopenharmony_ci break; 812cabdff1aSopenharmony_ci case 0x02000021: 813cabdff1aSopenharmony_ci case 0x02000001: 814cabdff1aSopenharmony_ci ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16, vflipped); 815cabdff1aSopenharmony_ci break; 816cabdff1aSopenharmony_ci case 0x02000029: 817cabdff1aSopenharmony_ci case 0x02000009: 818cabdff1aSopenharmony_ci ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16, vflipped); 819cabdff1aSopenharmony_ci break; 820cabdff1aSopenharmony_ci case 0x03000021: 821cabdff1aSopenharmony_ci case 0x03000001: 822cabdff1aSopenharmony_ci ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16, vflipped); 823cabdff1aSopenharmony_ci break; 824cabdff1aSopenharmony_ci case 0x03000029: 825cabdff1aSopenharmony_ci case 0x03000009: 826cabdff1aSopenharmony_ci ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16, vflipped); 827cabdff1aSopenharmony_ci break; 828cabdff1aSopenharmony_ci case 0x04000021: 829cabdff1aSopenharmony_ci case 0x04000001: 830cabdff1aSopenharmony_ci ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16, vflipped); 831cabdff1aSopenharmony_ci break; 832cabdff1aSopenharmony_ci case 0x04000029: 833cabdff1aSopenharmony_ci case 0x04000009: 834cabdff1aSopenharmony_ci ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16, vflipped); 835cabdff1aSopenharmony_ci break; 836cabdff1aSopenharmony_ci case 0x17000021: 837cabdff1aSopenharmony_ci case 0x17000001: 838cabdff1aSopenharmony_ci ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, 839cabdff1aSopenharmony_ci AV_PIX_FMT_RGB565LE, 2, vflipped); 840cabdff1aSopenharmony_ci break; 841cabdff1aSopenharmony_ci case 0x17000029: 842cabdff1aSopenharmony_ci case 0x17000009: 843cabdff1aSopenharmony_ci ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1, vflipped); 844cabdff1aSopenharmony_ci break; 845cabdff1aSopenharmony_ci case 0x18000021: 846cabdff1aSopenharmony_ci case 0x19000021: 847cabdff1aSopenharmony_ci case 0x18000001: 848cabdff1aSopenharmony_ci case 0x19000001: 849cabdff1aSopenharmony_ci ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, 850cabdff1aSopenharmony_ci AV_PIX_FMT_RGB555LE, 2, vflipped); 851cabdff1aSopenharmony_ci break; 852cabdff1aSopenharmony_ci case 0x18000029: 853cabdff1aSopenharmony_ci case 0x19000029: 854cabdff1aSopenharmony_ci case 0x18000009: 855cabdff1aSopenharmony_ci case 0x19000009: 856cabdff1aSopenharmony_ci ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0, vflipped); 857cabdff1aSopenharmony_ci break; 858cabdff1aSopenharmony_ci default: 859cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Frame header %"PRIX32, type); 860cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 861cabdff1aSopenharmony_ci } 862cabdff1aSopenharmony_ci 863cabdff1aSopenharmony_ci if (ret) 864cabdff1aSopenharmony_ci return ret; 865cabdff1aSopenharmony_ci 866cabdff1aSopenharmony_ci pic->pict_type = AV_PICTURE_TYPE_I; 867cabdff1aSopenharmony_ci pic->key_frame = 1; 868cabdff1aSopenharmony_ci *got_frame = 1; 869cabdff1aSopenharmony_ci 870cabdff1aSopenharmony_ci return avpkt->size; 871cabdff1aSopenharmony_ci} 872cabdff1aSopenharmony_ci 873cabdff1aSopenharmony_ciconst FFCodec ff_dxtory_decoder = { 874cabdff1aSopenharmony_ci .p.name = "dxtory", 875cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Dxtory"), 876cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 877cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_DXTORY, 878cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 879cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, 880cabdff1aSopenharmony_ci}; 881