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;