www.pudn.com > mediator15src.zip > ac3audio.cpp
/* * ac3audio.cpp * Copyright (C) 2001-2002 Arno Hornberger* * This file is part of MPEG Mediator, a free MPEG stream converter. * * MPEG Mediator is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPEG Mediator is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "ac3audio.h" #include "startcodes.h" AC3Audio::AC3Audio() { up = new Unpacketizer(); frame_buffer = new unsigned char[FRAMEBUFFERSIZE]; state = a52_init(0); } AC3Audio::~AC3Audio() { if (state) a52_free(state); if (frame_buffer) delete []frame_buffer; if (up) delete up; } void AC3Audio::SetInput(AsyncStream *as, int stream_id) { up->SetStream(as); this->stream_id = stream_id; payload_size = 0; payload_pos = 0; extrapolated_pts_valid = false; current_pts_used = true; audio_seek = true; } void AC3Audio::GetFrame(short *sample_buffer) { int framesize; float level; int flags; int bit_rate; int i, j; int *int_samples; up->Resync(); restart: GetBytes(frame_buffer, 7); while (1) { if ((frame_buffer[0] == 0x0b) && (frame_buffer[1] == 0x77)) { framesize = a52_syncinfo(frame_buffer, &bitstream_flags, &sample_rate, &bit_rate); if (framesize > 0) break; } for (i = 0; i < 6; i++) frame_buffer[i] = frame_buffer[i + 1]; frame_buffer[6] = GetByte(); } if (payload_pos < 7) { // frame started in previous packet?? if (!last_pts_used) { frame_pts = last_pts; last_pts_used = true; } else if (extrapolated_pts_valid) frame_pts = extrapolated_pts; else goto restart; // scan frames until we find a pts } else { // frame started in current packet.. if (!current_pts_used) { frame_pts = current_pts; current_pts_used = true; } else if (extrapolated_pts_valid) frame_pts = extrapolated_pts; else goto restart; // scan frames until we find a pts } GetBytes(&frame_buffer[7], framesize - 7); flags = A52_DOLBY; // A52_STEREO; // | A52_ADJUST_LEVEL; level = 1.0; a52_frame(state, frame_buffer, &flags, &level, 384.0); for (i = 0; i < 6; i++) { if (a52_block(state) == 0) { int_samples = (int *)a52_samples(state); for (j = 0; j < 256; j++) { // MMX would do that faster sample_buffer[j * 2] = Convert(int_samples[j]); sample_buffer[j * 2 + 1] = Convert(int_samples[j + 256]); } } else { for (j = 0; j < 512; j++) sample_buffer[j] = 0; } sample_buffer += 256 * 2; } frame_samples = 256 * 6; extrapolated_pts = frame_pts + (27000000 * (__int64)frame_samples) / (__int64)sample_rate; extrapolated_pts_valid = true; } void AC3Audio::SearchPacket() { last_pts = current_pts; last_pts_used = current_pts_used; int frame_offset; do { up->NextPacket(); } while ((up->GetStreamID() != PRIVATE_STREAM_1) || (up->GetSubstreamID() != (SUBSTREAM_AC3_0 + stream_id))); if (up->HasPTS()) { current_pts = up->GetPTS(); current_pts_used = false; } else current_pts_used = true; payload_size = up->GetPayloadSize(); if (audio_seek) { frame_offset = up->GetAudioFrameOffset() - 1; up->FlushPayloadBytes(frame_offset); payload_pos = frame_offset; audio_seek = false; } else payload_pos = 0; } unsigned char AC3Audio::GetByte() { unsigned char val; if (payload_pos >= payload_size) SearchPacket(); val = up->GetPayloadByte(); payload_pos++; return val; } void AC3Audio::GetBytes(unsigned char *dest, int count) { while (count > 0) { if (payload_pos >= payload_size) SearchPacket(); if (payload_size - payload_pos >= count) { up->GetPayloadBytes(dest, count); payload_pos += count; count = 0; } else { up->GetPayloadBytes(dest, payload_size - payload_pos); dest += payload_size - payload_pos; count -= payload_size - payload_pos; payload_pos = payload_size; } } } void AC3Audio::GetChannelDescriptor(char *desc) { static const int channels[] = { 2, 1, 2, 3, 3, 4, 4, 5, 1, 1, 3, 0, 0, 0, 0, 0 }; sprintf(desc, "%d.%d", channels[bitstream_flags & A52_CHANNEL_MASK], (bitstream_flags & A52_LFE) != 0 ? 1 : 0); }