#include #include #include "a52.h" #include "mpeg3private.h" #include "mpeg3protos.h" #include mpeg3_ac3_t* mpeg3_new_ac3() { mpeg3_ac3_t *result = calloc(1, sizeof(mpeg3_ac3_t)); result->stream = mpeg3bits_new_stream(0, 0); result->state = a52_init(0); result->output = a52_samples(result->state); return result; } void mpeg3_delete_ac3(mpeg3_ac3_t *audio) { mpeg3bits_delete_stream(audio->stream); a52_free(audio->state); free(audio); } /* Return 1 if it isn't an AC3 header */ int mpeg3_ac3_check(unsigned char *header) { int flags, samplerate, bitrate; return !a52_syncinfo(header, &flags, &samplerate, &bitrate); } /* Decode AC3 header */ int mpeg3_ac3_header(mpeg3_ac3_t *audio, unsigned char *header) { int result = 0; audio->flags = 0; //printf("mpeg3_ac3_header %02x%02x%02x%02x%02x%02x%02x%02x\n", header[0], header[1], header[2], header[3], header[4], header[5], header[6], header[7]); result = a52_syncinfo(header, &audio->flags, &audio->samplerate, &audio->bitrate); if(result) { //printf("%d\n", result); audio->framesize = result; audio->channels = 0; if(audio->flags & A52_LFE) audio->channels++; /* * printf("mpeg3_ac3_header %08x %08x\n", * audio->flags & A52_LFE, * audio->flags & A52_CHANNEL_MASK); */ switch(audio->flags & A52_CHANNEL_MASK) { case A52_CHANNEL: audio->channels++; break; case A52_MONO: audio->channels++; break; case A52_STEREO: audio->channels += 2; break; case A52_3F: audio->channels += 3; break; case A52_2F1R: audio->channels += 3; break; case A52_3F1R: audio->channels += 4; break; case A52_2F2R: audio->channels += 4; break; case A52_3F2R: audio->channels += 5; break; case A52_DOLBY: audio->channels += 2; break; default: printf("mpeg3_ac3_header: unknown channel code: %p\n", audio->flags & A52_CHANNEL_MASK); break; } } //printf("mpeg3_ac3_header 1 %d\n", audio->channels); return result; } int mpeg3audio_doac3(mpeg3_ac3_t *audio, char *frame, int frame_size, float **output, int render) { int output_position = 0; sample_t level = 1; int i, j, k, l; //printf("mpeg3audio_doac3 1\n"); a52_frame(audio->state, frame, &audio->flags, &level, 0); //printf("mpeg3audio_doac3 2\n"); a52_dynrng(audio->state, NULL, NULL); //printf("mpeg3audio_doac3 3\n"); for(i = 0; i < 6; i++) { if(!a52_block(audio->state)) { l = 0; if(render) { // Remap the channels to conform to encoders. for(j = 0; j < audio->channels; j++) { int dst_channel = j; // Make LFE last channel. // Shift all other channels down 1. if((audio->flags & A52_LFE)) { if(j == 0) dst_channel = audio->channels - 1; else dst_channel--; } // Swap front left and center for certain configurations switch(audio->flags & A52_CHANNEL_MASK) { case A52_3F: case A52_3F1R: case A52_3F2R: if(dst_channel == 0) dst_channel = 1; else if(dst_channel == 1) dst_channel = 0; break; } for(k = 0; k < 256; k++) { output[dst_channel][output_position + k] = ((sample_t*)audio->output)[l]; l++; } } } output_position += 256; } } return output_position; }