Mercurial > libavcodec.hg
comparison vmdav.c @ 8634:33912b3ea952 libavcodec
VMD first chunk of audio is not coded as many separate chunks of block_align
size. Thus, make demuxer and decoder handle it as a whole.
author | kostya |
---|---|
date | Wed, 21 Jan 2009 13:24:35 +0000 |
parents | 2acf0ae7b041 |
children | 5b7d5a33a3e2 |
comparison
equal
deleted
inserted
replaced
8633:aa3670eccc16 | 8634:33912b3ea952 |
---|---|
454 | 454 |
455 return 0; | 455 return 0; |
456 } | 456 } |
457 | 457 |
458 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, | 458 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, |
459 const uint8_t *buf, int stereo) | 459 const uint8_t *buf, int buf_size, int stereo) |
460 { | 460 { |
461 int i; | 461 int i; |
462 int chan = 0; | 462 int chan = 0; |
463 int16_t *out = (int16_t*)data; | 463 int16_t *out = (int16_t*)data; |
464 | 464 |
465 for(i = 0; i < s->block_align; i++) { | 465 for(i = 0; i < buf_size; i++) { |
466 if(buf[i] & 0x80) | 466 if(buf[i] & 0x80) |
467 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; | 467 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; |
468 else | 468 else |
469 s->predictors[chan] += vmdaudio_table[buf[i]]; | 469 s->predictors[chan] += vmdaudio_table[buf[i]]; |
470 s->predictors[chan] = av_clip_int16(s->predictors[chan]); | 470 s->predictors[chan] = av_clip_int16(s->predictors[chan]); |
472 chan ^= stereo; | 472 chan ^= stereo; |
473 } | 473 } |
474 } | 474 } |
475 | 475 |
476 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, | 476 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, |
477 const uint8_t *buf, int silence) | 477 const uint8_t *buf, int silence, int data_size) |
478 { | 478 { |
479 int bytes_decoded = 0; | 479 int bytes_decoded = 0; |
480 int i; | 480 int i; |
481 | 481 |
482 // if (silence) | 482 // if (silence) |
483 // av_log(s->avctx, AV_LOG_INFO, "silent block!\n"); | 483 // av_log(s->avctx, AV_LOG_INFO, "silent block!\n"); |
484 if (s->channels == 2) { | 484 if (s->channels == 2) { |
485 | 485 |
486 /* stereo handling */ | 486 /* stereo handling */ |
487 if (silence) { | 487 if (silence) { |
488 memset(data, 0, s->block_align * 2); | 488 memset(data, 0, data_size * 2); |
489 } else { | 489 } else { |
490 if (s->bits == 16) | 490 if (s->bits == 16) |
491 vmdaudio_decode_audio(s, data, buf, 1); | 491 vmdaudio_decode_audio(s, data, buf, data_size, 1); |
492 else { | 492 else { |
493 /* copy the data but convert it to signed */ | 493 /* copy the data but convert it to signed */ |
494 for (i = 0; i < s->block_align; i++){ | 494 for (i = 0; i < data_size; i++){ |
495 *data++ = buf[i] + 0x80; | 495 *data++ = buf[i] + 0x80; |
496 *data++ = buf[i] + 0x80; | 496 *data++ = buf[i] + 0x80; |
497 } | 497 } |
498 } | 498 } |
499 } | 499 } |
500 } else { | 500 } else { |
501 bytes_decoded = s->block_align * 2; | 501 bytes_decoded = data_size * 2; |
502 | 502 |
503 /* mono handling */ | 503 /* mono handling */ |
504 if (silence) { | 504 if (silence) { |
505 memset(data, 0, s->block_align * 2); | 505 memset(data, 0, data_size * 2); |
506 } else { | 506 } else { |
507 if (s->bits == 16) { | 507 if (s->bits == 16) { |
508 vmdaudio_decode_audio(s, data, buf, 0); | 508 vmdaudio_decode_audio(s, data, buf, data_size, 0); |
509 } else { | 509 } else { |
510 /* copy the data but convert it to signed */ | 510 /* copy the data but convert it to signed */ |
511 for (i = 0; i < s->block_align; i++){ | 511 for (i = 0; i < data_size; i++){ |
512 *data++ = buf[i] + 0x80; | 512 *data++ = buf[i] + 0x80; |
513 *data++ = buf[i] + 0x80; | 513 *data++ = buf[i] + 0x80; |
514 } | 514 } |
515 } | 515 } |
516 } | 516 } |
517 } | 517 } |
518 | 518 |
519 return s->block_align * 2; | 519 return data_size * 2; |
520 } | 520 } |
521 | 521 |
522 static int vmdaudio_decode_frame(AVCodecContext *avctx, | 522 static int vmdaudio_decode_frame(AVCodecContext *avctx, |
523 void *data, int *data_size, | 523 void *data, int *data_size, |
524 const uint8_t *buf, int buf_size) | 524 const uint8_t *buf, int buf_size) |
532 if (buf_size < 16) | 532 if (buf_size < 16) |
533 return buf_size; | 533 return buf_size; |
534 | 534 |
535 if (buf[6] == 1) { | 535 if (buf[6] == 1) { |
536 /* the chunk contains audio */ | 536 /* the chunk contains audio */ |
537 *data_size = vmdaudio_loadsound(s, output_samples, p, 0); | 537 *data_size = vmdaudio_loadsound(s, output_samples, p, 0, buf_size - 16); |
538 } else if (buf[6] == 2) { | 538 } else if (buf[6] == 2) { |
539 /* the chunk may contain audio */ | 539 /* initial chunk, may contain audio and silence */ |
540 p += 4; | 540 uint32_t flags = AV_RB32(p); |
541 *data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16)); | 541 int raw_block_size = s->block_align * s->bits / 8; |
542 output_samples += (s->block_align * s->bits / 8); | 542 int silent_chunks; |
543 if(flags == 0xFFFFFFFF) | |
544 silent_chunks = 32; | |
545 else | |
546 silent_chunks = av_log2(flags + 1); | |
547 if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 2) | |
548 return -1; | |
549 *data_size = 0; | |
550 memset(output_samples, 0, raw_block_size * silent_chunks); | |
551 output_samples += raw_block_size * silent_chunks; | |
552 *data_size = raw_block_size * silent_chunks; | |
553 *data_size += vmdaudio_loadsound(s, output_samples, p + 4, 0, buf_size - 20); | |
543 } else if (buf[6] == 3) { | 554 } else if (buf[6] == 3) { |
544 /* silent chunk */ | 555 /* silent chunk */ |
545 *data_size = vmdaudio_loadsound(s, output_samples, p, 1); | 556 *data_size = vmdaudio_loadsound(s, output_samples, p, 1, 0); |
546 } | 557 } |
547 | 558 |
548 return buf_size; | 559 return buf_size; |
549 } | 560 } |
550 | 561 |