00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029
00030 #include "libavutil/common.h"
00031 #include "libavutil/intreadwrite.h"
00032 #include "bytestream.h"
00033 #include "avcodec.h"
00034 #include "internal.h"
00035
00036 #include <zlib.h>
00037
00038
00039
00040
00041 typedef struct DxaDecContext {
00042 AVFrame pic, prev;
00043
00044 int dsize;
00045 uint8_t *decomp_buf;
00046 uint32_t pal[256];
00047 } DxaDecContext;
00048
00049 static const int shift1[6] = { 0, 8, 8, 8, 4, 4 };
00050 static const int shift2[6] = { 0, 0, 8, 4, 0, 4 };
00051
00052 static int decode_13(AVCodecContext *avctx, DxaDecContext *c, uint8_t* dst, uint8_t *src, uint8_t *ref)
00053 {
00054 uint8_t *code, *data, *mv, *msk, *tmp, *tmp2;
00055 int i, j, k;
00056 int type, x, y, d, d2;
00057 int stride = c->pic.linesize[0];
00058 uint32_t mask;
00059
00060 code = src + 12;
00061 data = code + ((avctx->width * avctx->height) >> 4);
00062 mv = data + AV_RB32(src + 0);
00063 msk = mv + AV_RB32(src + 4);
00064
00065 for(j = 0; j < avctx->height; j += 4){
00066 for(i = 0; i < avctx->width; i += 4){
00067 tmp = dst + i;
00068 tmp2 = ref + i;
00069 type = *code++;
00070 switch(type){
00071 case 4:
00072 x = (*mv) >> 4; if(x & 8) x = 8 - x;
00073 y = (*mv++) & 0xF; if(y & 8) y = 8 - y;
00074 tmp2 += x + y*stride;
00075 case 0:
00076 case 5:
00077 for(y = 0; y < 4; y++){
00078 memcpy(tmp, tmp2, 4);
00079 tmp += stride;
00080 tmp2 += stride;
00081 }
00082 break;
00083 case 1:
00084 case 10:
00085 case 11:
00086 case 12:
00087 case 13:
00088 case 14:
00089 case 15:
00090 if(type == 1){
00091 mask = AV_RB16(msk);
00092 msk += 2;
00093 }else{
00094 type -= 10;
00095 mask = ((msk[0] & 0xF0) << shift1[type]) | ((msk[0] & 0xF) << shift2[type]);
00096 msk++;
00097 }
00098 for(y = 0; y < 4; y++){
00099 for(x = 0; x < 4; x++){
00100 tmp[x] = (mask & 0x8000) ? *data++ : tmp2[x];
00101 mask <<= 1;
00102 }
00103 tmp += stride;
00104 tmp2 += stride;
00105 }
00106 break;
00107 case 2:
00108 for(y = 0; y < 4; y++){
00109 memset(tmp, data[0], 4);
00110 tmp += stride;
00111 }
00112 data++;
00113 break;
00114 case 3:
00115 for(y = 0; y < 4; y++){
00116 memcpy(tmp, data, 4);
00117 data += 4;
00118 tmp += stride;
00119 }
00120 break;
00121 case 8:
00122 mask = *msk++;
00123 for(k = 0; k < 4; k++){
00124 d = ((k & 1) << 1) + ((k & 2) * stride);
00125 d2 = ((k & 1) << 1) + ((k & 2) * stride);
00126 tmp2 = ref + i + d2;
00127 switch(mask & 0xC0){
00128 case 0x80:
00129 x = (*mv) >> 4; if(x & 8) x = 8 - x;
00130 y = (*mv++) & 0xF; if(y & 8) y = 8 - y;
00131 tmp2 += x + y*stride;
00132 case 0x00:
00133 tmp[d + 0 ] = tmp2[0];
00134 tmp[d + 1 ] = tmp2[1];
00135 tmp[d + 0 + stride] = tmp2[0 + stride];
00136 tmp[d + 1 + stride] = tmp2[1 + stride];
00137 break;
00138 case 0x40:
00139 tmp[d + 0 ] = data[0];
00140 tmp[d + 1 ] = data[0];
00141 tmp[d + 0 + stride] = data[0];
00142 tmp[d + 1 + stride] = data[0];
00143 data++;
00144 break;
00145 case 0xC0:
00146 tmp[d + 0 ] = *data++;
00147 tmp[d + 1 ] = *data++;
00148 tmp[d + 0 + stride] = *data++;
00149 tmp[d + 1 + stride] = *data++;
00150 break;
00151 }
00152 mask <<= 2;
00153 }
00154 break;
00155 case 32:
00156 mask = AV_RB16(msk);
00157 msk += 2;
00158 for(y = 0; y < 4; y++){
00159 for(x = 0; x < 4; x++){
00160 tmp[x] = data[mask & 1];
00161 mask >>= 1;
00162 }
00163 tmp += stride;
00164 tmp2 += stride;
00165 }
00166 data += 2;
00167 break;
00168 case 33:
00169 case 34:
00170 mask = AV_RB32(msk);
00171 msk += 4;
00172 for(y = 0; y < 4; y++){
00173 for(x = 0; x < 4; x++){
00174 tmp[x] = data[mask & 3];
00175 mask >>= 2;
00176 }
00177 tmp += stride;
00178 tmp2 += stride;
00179 }
00180 data += type - 30;
00181 break;
00182 default:
00183 av_log(avctx, AV_LOG_ERROR, "Unknown opcode %d\n", type);
00184 return AVERROR_INVALIDDATA;
00185 }
00186 }
00187 dst += stride * 4;
00188 ref += stride * 4;
00189 }
00190 return 0;
00191 }
00192
00193 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
00194 {
00195 DxaDecContext * const c = avctx->priv_data;
00196 uint8_t *outptr, *srcptr, *tmpptr;
00197 unsigned long dsize;
00198 int i, j, compr, ret;
00199 int stride;
00200 int pc = 0;
00201 GetByteContext gb;
00202
00203 bytestream2_init(&gb, avpkt->data, avpkt->size);
00204
00205
00206 if (bytestream2_peek_le32(&gb) == MKTAG('C','M','A','P')) {
00207 bytestream2_skip(&gb, 4);
00208 for(i = 0; i < 256; i++){
00209 c->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&gb);
00210 }
00211 pc = 1;
00212 }
00213
00214 if ((ret = ff_get_buffer(avctx, &c->pic)) < 0){
00215 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00216 return ret;
00217 }
00218 memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE);
00219 c->pic.palette_has_changed = pc;
00220
00221 outptr = c->pic.data[0];
00222 srcptr = c->decomp_buf;
00223 tmpptr = c->prev.data[0];
00224 stride = c->pic.linesize[0];
00225
00226 if (bytestream2_get_le32(&gb) == MKTAG('N','U','L','L'))
00227 compr = -1;
00228 else
00229 compr = bytestream2_get_byte(&gb);
00230
00231 dsize = c->dsize;
00232 if (compr != 4 && compr != -1) {
00233 bytestream2_skip(&gb, 4);
00234 if (uncompress(c->decomp_buf, &dsize, avpkt->data + bytestream2_tell(&gb),
00235 bytestream2_get_bytes_left(&gb)) != Z_OK) {
00236 av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n");
00237 return AVERROR_INVALIDDATA;
00238 }
00239 }
00240 switch(compr){
00241 case -1:
00242 c->pic.key_frame = 0;
00243 c->pic.pict_type = AV_PICTURE_TYPE_P;
00244 if(c->prev.data[0])
00245 memcpy(c->pic.data[0], c->prev.data[0], c->pic.linesize[0] * avctx->height);
00246 else{
00247 memset(c->pic.data[0], 0, c->pic.linesize[0] * avctx->height);
00248 c->pic.key_frame = 1;
00249 c->pic.pict_type = AV_PICTURE_TYPE_I;
00250 }
00251 break;
00252 case 2:
00253 case 3:
00254 case 4:
00255 case 5:
00256 c->pic.key_frame = !(compr & 1);
00257 c->pic.pict_type = (compr & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
00258 for(j = 0; j < avctx->height; j++){
00259 if((compr & 1) && tmpptr){
00260 for(i = 0; i < avctx->width; i++)
00261 outptr[i] = srcptr[i] ^ tmpptr[i];
00262 tmpptr += stride;
00263 }else
00264 memcpy(outptr, srcptr, avctx->width);
00265 outptr += stride;
00266 srcptr += avctx->width;
00267 }
00268 break;
00269 case 12:
00270 case 13:
00271 c->pic.key_frame = 0;
00272 c->pic.pict_type = AV_PICTURE_TYPE_P;
00273 if (!c->prev.data[0]) {
00274 av_log(avctx, AV_LOG_ERROR, "Missing reference frame\n");
00275 return AVERROR_INVALIDDATA;
00276 }
00277 decode_13(avctx, c, c->pic.data[0], srcptr, c->prev.data[0]);
00278 break;
00279 default:
00280 av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", compr);
00281 return AVERROR_INVALIDDATA;
00282 }
00283
00284 FFSWAP(AVFrame, c->pic, c->prev);
00285 if(c->pic.data[0])
00286 avctx->release_buffer(avctx, &c->pic);
00287
00288 *got_frame = 1;
00289 *(AVFrame*)data = c->prev;
00290
00291
00292 return avpkt->size;
00293 }
00294
00295 static av_cold int decode_init(AVCodecContext *avctx)
00296 {
00297 DxaDecContext * const c = avctx->priv_data;
00298
00299 avctx->pix_fmt = AV_PIX_FMT_PAL8;
00300
00301 avcodec_get_frame_defaults(&c->pic);
00302 avcodec_get_frame_defaults(&c->prev);
00303
00304 c->dsize = avctx->width * avctx->height * 2;
00305 c->decomp_buf = av_malloc(c->dsize);
00306 if (!c->decomp_buf) {
00307 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
00308 return AVERROR(ENOMEM);
00309 }
00310
00311 return 0;
00312 }
00313
00314 static av_cold int decode_end(AVCodecContext *avctx)
00315 {
00316 DxaDecContext * const c = avctx->priv_data;
00317
00318 av_freep(&c->decomp_buf);
00319 if(c->prev.data[0])
00320 avctx->release_buffer(avctx, &c->prev);
00321 if(c->pic.data[0])
00322 avctx->release_buffer(avctx, &c->pic);
00323
00324 return 0;
00325 }
00326
00327 AVCodec ff_dxa_decoder = {
00328 .name = "dxa",
00329 .type = AVMEDIA_TYPE_VIDEO,
00330 .id = AV_CODEC_ID_DXA,
00331 .priv_data_size = sizeof(DxaDecContext),
00332 .init = decode_init,
00333 .close = decode_end,
00334 .decode = decode_frame,
00335 .capabilities = CODEC_CAP_DR1,
00336 .long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"),
00337 };