Mercurial > libavcodec.hg
comparison cinepak.c @ 4262:cdcfabd40101 libavcodec
Another hack to allow the Cinepak decoder to detect both types of deviant Cinepak
data. Tested against both known FILM files, several CPK files, and normal
CVID-encoded files.
author | melanson |
---|---|
date | Sat, 02 Dec 2006 22:27:18 +0000 |
parents | c8c591fe26f8 |
children | 05e932ddaaa9 |
comparison
equal
deleted
inserted
replaced
4261:ca322819f0cc | 4262:cdcfabd40101 |
---|---|
24 * @file cinepak.c | 24 * @file cinepak.c |
25 * Cinepak video decoder | 25 * Cinepak video decoder |
26 * by Ewald Snel <ewald@rambo.its.tudelft.nl> | 26 * by Ewald Snel <ewald@rambo.its.tudelft.nl> |
27 * For more information on the Cinepak algorithm, visit: | 27 * For more information on the Cinepak algorithm, visit: |
28 * http://www.csse.monash.edu.au/~timf/ | 28 * http://www.csse.monash.edu.au/~timf/ |
29 * For more information on the quirky data inside Sega FILM/CPK files, visit: | |
30 * http://wiki.multimedia.cx/index.php?title=Sega_FILM | |
29 */ | 31 */ |
30 | 32 |
31 #include <stdio.h> | 33 #include <stdio.h> |
32 #include <stdlib.h> | 34 #include <stdlib.h> |
33 #include <string.h> | 35 #include <string.h> |
64 | 66 |
65 int width, height; | 67 int width, height; |
66 | 68 |
67 int palette_video; | 69 int palette_video; |
68 cvid_strip_t strips[MAX_STRIPS]; | 70 cvid_strip_t strips[MAX_STRIPS]; |
71 | |
72 int sega_film_skip_bytes; | |
69 | 73 |
70 } CinepakContext; | 74 } CinepakContext; |
71 | 75 |
72 static void cinepak_decode_codebook (cvid_codebook_t *codebook, | 76 static void cinepak_decode_codebook (cvid_codebook_t *codebook, |
73 int chunk_id, int size, uint8_t *data) | 77 int chunk_id, int size, uint8_t *data) |
317 { | 321 { |
318 uint8_t *eod = (s->data + s->size); | 322 uint8_t *eod = (s->data + s->size); |
319 int i, result, strip_size, frame_flags, num_strips; | 323 int i, result, strip_size, frame_flags, num_strips; |
320 int y0 = 0; | 324 int y0 = 0; |
321 int encoded_buf_size; | 325 int encoded_buf_size; |
322 /* if true, Cinepak data is from a Sega FILM/CPK file */ | |
323 int sega_film_data = 0; | |
324 | 326 |
325 if (s->size < 10) | 327 if (s->size < 10) |
326 return -1; | 328 return -1; |
327 | 329 |
328 frame_flags = s->data[0]; | 330 frame_flags = s->data[0]; |
329 num_strips = BE_16 (&s->data[8]); | 331 num_strips = BE_16 (&s->data[8]); |
330 encoded_buf_size = ((s->data[1] << 16) | BE_16 (&s->data[2])); | 332 encoded_buf_size = ((s->data[1] << 16) | BE_16 (&s->data[2])); |
331 if (encoded_buf_size != s->size) | 333 |
332 sega_film_data = 1; | 334 /* if this is the first frame, check for deviant Sega FILM data */ |
333 if (sega_film_data) | 335 if (s->sega_film_skip_bytes == -1) { |
334 s->data += 12; | 336 if (encoded_buf_size != s->size) { |
335 else | 337 /* If the encoded frame size differs from the frame size as indicated |
336 s->data += 10; | 338 * by the container file, this data likely comes from a Sega FILM/CPK file. |
339 * If the frame header is followed by the bytes FE 00 00 06 00 00 then | |
340 * this is probably one of the two known files that have 6 extra bytes | |
341 * after the frame header. Else, assume 2 extra bytes. */ | |
342 if ((s->data[10] == 0xFE) && | |
343 (s->data[11] == 0x00) && | |
344 (s->data[12] == 0x00) && | |
345 (s->data[13] == 0x06) && | |
346 (s->data[14] == 0x00) && | |
347 (s->data[15] == 0x00)) | |
348 s->sega_film_skip_bytes = 6; | |
349 else | |
350 s->sega_film_skip_bytes = 2; | |
351 } else | |
352 s->sega_film_skip_bytes = 0; | |
353 } | |
354 | |
355 s->data += 10 + s->sega_film_skip_bytes; | |
337 | 356 |
338 if (num_strips > MAX_STRIPS) | 357 if (num_strips > MAX_STRIPS) |
339 num_strips = MAX_STRIPS; | 358 num_strips = MAX_STRIPS; |
340 | 359 |
341 for (i=0; i < num_strips; i++) { | 360 for (i=0; i < num_strips; i++) { |
375 CinepakContext *s = (CinepakContext *)avctx->priv_data; | 394 CinepakContext *s = (CinepakContext *)avctx->priv_data; |
376 | 395 |
377 s->avctx = avctx; | 396 s->avctx = avctx; |
378 s->width = (avctx->width + 3) & ~3; | 397 s->width = (avctx->width + 3) & ~3; |
379 s->height = (avctx->height + 3) & ~3; | 398 s->height = (avctx->height + 3) & ~3; |
399 s->sega_film_skip_bytes = -1; /* uninitialized state */ | |
380 | 400 |
381 // check for paletted data | 401 // check for paletted data |
382 if ((avctx->palctrl == NULL) || (avctx->bits_per_sample == 40)) { | 402 if ((avctx->palctrl == NULL) || (avctx->bits_per_sample == 40)) { |
383 s->palette_video = 0; | 403 s->palette_video = 0; |
384 avctx->pix_fmt = PIX_FMT_YUV420P; | 404 avctx->pix_fmt = PIX_FMT_YUV420P; |