00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "avcodec.h"
00024 #include "internal.h"
00025 #include "bytestream.h"
00026
00027 #include "libavutil/imgutils.h"
00028 #include "libavutil/lzo.h"
00029
00030 typedef struct DfaContext {
00031 AVFrame pic;
00032
00033 uint32_t pal[256];
00034 uint8_t *frame_buf;
00035 } DfaContext;
00036
00037 static av_cold int dfa_decode_init(AVCodecContext *avctx)
00038 {
00039 DfaContext *s = avctx->priv_data;
00040 int ret;
00041
00042 avctx->pix_fmt = PIX_FMT_PAL8;
00043
00044 if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
00045 return ret;
00046
00047 s->frame_buf = av_mallocz(avctx->width * avctx->height + AV_LZO_OUTPUT_PADDING);
00048 if (!s->frame_buf)
00049 return AVERROR(ENOMEM);
00050
00051 return 0;
00052 }
00053
00054 static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
00055 {
00056 const int size = width * height;
00057
00058 if (bytestream2_get_buffer(gb, frame, size) != size)
00059 return AVERROR_INVALIDDATA;
00060 return 0;
00061 }
00062
00063 static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
00064 {
00065 const uint8_t *frame_start = frame;
00066 const uint8_t *frame_end = frame + width * height;
00067 int mask = 0x10000, bitbuf = 0;
00068 int v, count, segments;
00069 unsigned offset;
00070
00071 segments = bytestream2_get_le32(gb);
00072 offset = bytestream2_get_le32(gb);
00073 if (frame_end - frame <= offset)
00074 return AVERROR_INVALIDDATA;
00075 frame += offset;
00076 while (segments--) {
00077 if (bytestream2_get_bytes_left(gb) < 2)
00078 return AVERROR_INVALIDDATA;
00079 if (mask == 0x10000) {
00080 bitbuf = bytestream2_get_le16u(gb);
00081 mask = 1;
00082 }
00083 if (frame_end - frame < 2)
00084 return AVERROR_INVALIDDATA;
00085 if (bitbuf & mask) {
00086 v = bytestream2_get_le16(gb);
00087 offset = (v & 0x1FFF) << 1;
00088 count = ((v >> 13) + 2) << 1;
00089 if (frame - frame_start < offset || frame_end - frame < count)
00090 return AVERROR_INVALIDDATA;
00091 av_memcpy_backptr(frame, offset, count);
00092 frame += count;
00093 } else {
00094 *frame++ = bytestream2_get_byte(gb);
00095 *frame++ = bytestream2_get_byte(gb);
00096 }
00097 mask <<= 1;
00098 }
00099
00100 return 0;
00101 }
00102
00103 static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
00104 {
00105 const uint8_t *frame_start = frame;
00106 const uint8_t *frame_end = frame + width * height;
00107 int mask = 0x10000, bitbuf = 0;
00108 int v, offset, count, segments;
00109
00110 segments = bytestream2_get_le16(gb);
00111 while (segments--) {
00112 if (bytestream2_get_bytes_left(gb) < 2)
00113 return AVERROR_INVALIDDATA;
00114 if (mask == 0x10000) {
00115 bitbuf = bytestream2_get_le16u(gb);
00116 mask = 1;
00117 }
00118 if (frame_end - frame < 2)
00119 return AVERROR_INVALIDDATA;
00120 if (bitbuf & mask) {
00121 v = bytestream2_get_le16(gb);
00122 offset = (v & 0x1FFF) << 1;
00123 count = ((v >> 13) + 2) << 1;
00124 if (frame - frame_start < offset || frame_end - frame < count)
00125 return AVERROR_INVALIDDATA;
00126
00127 for (v = 0; v < count; v++)
00128 frame[v] = frame[v - offset];
00129 frame += count;
00130 } else if (bitbuf & (mask << 1)) {
00131 frame += bytestream2_get_le16(gb);
00132 } else {
00133 *frame++ = bytestream2_get_byte(gb);
00134 *frame++ = bytestream2_get_byte(gb);
00135 }
00136 mask <<= 2;
00137 }
00138
00139 return 0;
00140 }
00141
00142 static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
00143 {
00144 const uint8_t *frame_start = frame;
00145 const uint8_t *frame_end = frame + width * height;
00146 int mask = 0x10000, bitbuf = 0;
00147 int i, v, offset, count, segments;
00148
00149 segments = bytestream2_get_le16(gb);
00150 while (segments--) {
00151 if (bytestream2_get_bytes_left(gb) < 2)
00152 return AVERROR_INVALIDDATA;
00153 if (mask == 0x10000) {
00154 bitbuf = bytestream2_get_le16u(gb);
00155 mask = 1;
00156 }
00157
00158 if (bitbuf & mask) {
00159 v = bytestream2_get_le16(gb);
00160 offset = (v & 0x1FFF) << 2;
00161 count = ((v >> 13) + 2) << 1;
00162 if (frame - frame_start < offset || frame_end - frame < count*2 + width)
00163 return AVERROR_INVALIDDATA;
00164 for (i = 0; i < count; i++) {
00165 frame[0] = frame[1] =
00166 frame[width] = frame[width + 1] = frame[-offset];
00167
00168 frame += 2;
00169 }
00170 } else if (bitbuf & (mask << 1)) {
00171 v = bytestream2_get_le16(gb)*2;
00172 if (frame - frame_end < v)
00173 return AVERROR_INVALIDDATA;
00174 frame += v;
00175 } else {
00176 if (frame_end - frame < width + 3)
00177 return AVERROR_INVALIDDATA;
00178 frame[0] = frame[1] =
00179 frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
00180 frame += 2;
00181 frame[0] = frame[1] =
00182 frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
00183 frame += 2;
00184 }
00185 mask <<= 2;
00186 }
00187
00188 return 0;
00189 }
00190
00191 static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
00192 {
00193 uint8_t *line_ptr;
00194 int count, lines, segments;
00195
00196 count = bytestream2_get_le16(gb);
00197 if (count >= height)
00198 return AVERROR_INVALIDDATA;
00199 frame += width * count;
00200 lines = bytestream2_get_le16(gb);
00201 if (count + lines > height)
00202 return AVERROR_INVALIDDATA;
00203
00204 while (lines--) {
00205 if (bytestream2_get_bytes_left(gb) < 1)
00206 return AVERROR_INVALIDDATA;
00207 line_ptr = frame;
00208 frame += width;
00209 segments = bytestream2_get_byteu(gb);
00210 while (segments--) {
00211 if (frame - line_ptr <= bytestream2_peek_byte(gb))
00212 return AVERROR_INVALIDDATA;
00213 line_ptr += bytestream2_get_byte(gb);
00214 count = (int8_t)bytestream2_get_byte(gb);
00215 if (count >= 0) {
00216 if (frame - line_ptr < count)
00217 return AVERROR_INVALIDDATA;
00218 if (bytestream2_get_buffer(gb, line_ptr, count) != count)
00219 return AVERROR_INVALIDDATA;
00220 } else {
00221 count = -count;
00222 if (frame - line_ptr < count)
00223 return AVERROR_INVALIDDATA;
00224 memset(line_ptr, bytestream2_get_byte(gb), count);
00225 }
00226 line_ptr += count;
00227 }
00228 }
00229
00230 return 0;
00231 }
00232
00233 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
00234 {
00235 const uint8_t *frame_end = frame + width * height;
00236 uint8_t *line_ptr;
00237 int count, i, v, lines, segments;
00238 int y = 0;
00239
00240 lines = bytestream2_get_le16(gb);
00241 if (lines > height)
00242 return AVERROR_INVALIDDATA;
00243
00244 while (lines--) {
00245 if (bytestream2_get_bytes_left(gb) < 2)
00246 return AVERROR_INVALIDDATA;
00247 segments = bytestream2_get_le16u(gb);
00248 while ((segments & 0xC000) == 0xC000) {
00249 unsigned skip_lines = -(int16_t)segments;
00250 unsigned delta = -((int16_t)segments * width);
00251 if (frame_end - frame <= delta || y + lines + skip_lines > height)
00252 return AVERROR_INVALIDDATA;
00253 frame += delta;
00254 y += skip_lines;
00255 segments = bytestream2_get_le16(gb);
00256 }
00257 if (segments & 0x8000) {
00258 frame[width - 1] = segments & 0xFF;
00259 segments = bytestream2_get_le16(gb);
00260 }
00261 line_ptr = frame;
00262 if (frame_end - frame < width)
00263 return AVERROR_INVALIDDATA;
00264 frame += width;
00265 y++;
00266 while (segments--) {
00267 if (frame - line_ptr <= bytestream2_peek_byte(gb))
00268 return AVERROR_INVALIDDATA;
00269 line_ptr += bytestream2_get_byte(gb);
00270 count = (int8_t)bytestream2_get_byte(gb);
00271 if (count >= 0) {
00272 if (frame - line_ptr < count * 2)
00273 return AVERROR_INVALIDDATA;
00274 if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
00275 return AVERROR_INVALIDDATA;
00276 line_ptr += count * 2;
00277 } else {
00278 count = -count;
00279 if (frame - line_ptr < count * 2)
00280 return AVERROR_INVALIDDATA;
00281 v = bytestream2_get_le16(gb);
00282 for (i = 0; i < count; i++)
00283 bytestream_put_le16(&line_ptr, v);
00284 }
00285 }
00286 }
00287
00288 return 0;
00289 }
00290
00291 static int decode_unk6(GetByteContext *gb, uint8_t *frame, int width, int height)
00292 {
00293 return AVERROR_PATCHWELCOME;
00294 }
00295
00296 static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
00297 {
00298 memset(frame, 0, width * height);
00299 return 0;
00300 }
00301
00302
00303 typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height);
00304
00305 static const chunk_decoder decoder[8] = {
00306 decode_copy, decode_tsw1, decode_bdlt, decode_wdlt,
00307 decode_unk6, decode_dsw1, decode_blck, decode_dds1,
00308 };
00309
00310 static const char* chunk_name[8] = {
00311 "COPY", "TSW1", "BDLT", "WDLT", "????", "DSW1", "BLCK", "DDS1"
00312 };
00313
00314 static int dfa_decode_frame(AVCodecContext *avctx,
00315 void *data, int *data_size,
00316 AVPacket *avpkt)
00317 {
00318 DfaContext *s = avctx->priv_data;
00319 GetByteContext gb;
00320 const uint8_t *buf = avpkt->data;
00321 uint32_t chunk_type, chunk_size;
00322 uint8_t *dst;
00323 int ret;
00324 int i, pal_elems;
00325
00326 if (s->pic.data[0])
00327 avctx->release_buffer(avctx, &s->pic);
00328
00329 if ((ret = ff_get_buffer(avctx, &s->pic))) {
00330 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00331 return ret;
00332 }
00333
00334 bytestream2_init(&gb, avpkt->data, avpkt->size);
00335 while (bytestream2_get_bytes_left(&gb) > 0) {
00336 bytestream2_skip(&gb, 4);
00337 chunk_size = bytestream2_get_le32(&gb);
00338 chunk_type = bytestream2_get_le32(&gb);
00339 if (!chunk_type)
00340 break;
00341 if (chunk_type == 1) {
00342 pal_elems = FFMIN(chunk_size / 3, 256);
00343 for (i = 0; i < pal_elems; i++) {
00344 s->pal[i] = bytestream2_get_be24(&gb) << 2;
00345 s->pal[i] |= (s->pal[i] >> 6) & 0x333;
00346 }
00347 s->pic.palette_has_changed = 1;
00348 } else if (chunk_type <= 9) {
00349 if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
00350 av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
00351 chunk_name[chunk_type - 2]);
00352 return AVERROR_INVALIDDATA;
00353 }
00354 } else {
00355 av_log(avctx, AV_LOG_WARNING, "Ignoring unknown chunk type %d\n",
00356 chunk_type);
00357 }
00358 buf += chunk_size;
00359 }
00360
00361 buf = s->frame_buf;
00362 dst = s->pic.data[0];
00363 for (i = 0; i < avctx->height; i++) {
00364 memcpy(dst, buf, avctx->width);
00365 dst += s->pic.linesize[0];
00366 buf += avctx->width;
00367 }
00368 memcpy(s->pic.data[1], s->pal, sizeof(s->pal));
00369
00370 *data_size = sizeof(AVFrame);
00371 *(AVFrame*)data = s->pic;
00372
00373 return avpkt->size;
00374 }
00375
00376 static av_cold int dfa_decode_end(AVCodecContext *avctx)
00377 {
00378 DfaContext *s = avctx->priv_data;
00379
00380 if (s->pic.data[0])
00381 avctx->release_buffer(avctx, &s->pic);
00382
00383 av_freep(&s->frame_buf);
00384
00385 return 0;
00386 }
00387
00388 AVCodec ff_dfa_decoder = {
00389 .name = "dfa",
00390 .type = AVMEDIA_TYPE_VIDEO,
00391 .id = CODEC_ID_DFA,
00392 .priv_data_size = sizeof(DfaContext),
00393 .init = dfa_decode_init,
00394 .close = dfa_decode_end,
00395 .decode = dfa_decode_frame,
00396 .capabilities = CODEC_CAP_DR1,
00397 .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"),
00398 };