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