www.pudn.com > mediator15src.zip > mpegaudio.cpp
/* * mpegaudio.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 "mpegaudio.h" #include "startcodes.h" MPEGAudio::MPEGAudio() { up = new Unpacketizer(); frame_buffer = new unsigned char[FRAMEBUFFERSIZE]; make_decode_tables(32768); // initialize mpg123 init_layer2(); } MPEGAudio::~MPEGAudio() { if (frame_buffer) delete []frame_buffer; if (up) delete up; } void MPEGAudio::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; } void MPEGAudio::GetFrame(short *sample_buffer) { unsigned long header; bool sync_found; int framesize; int sample_bytes; up->Resync(); restart: header = 0; sync_found = false; do { header <<= 8; header |= GetByte(); if ((header & 0xfff00000) == 0xfff00000) { framesize = decode_header(&fr, header); if (framesize > 0) sync_found = true; } } while (!sync_found); if (payload_pos < 4) { // 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 } if (fr.error_protection) { GetByte(); // skip crc-sum GetByte(); framesize -= 2; } GetBytes(frame_buffer, framesize); switch (fr.lay) { case 1: sample_bytes = do_layer1(&fr, frame_buffer, sample_buffer); break; case 2: sample_bytes = do_layer2(&fr, frame_buffer, sample_buffer); break; default: throw MPAExcept(MPAExcept::AUDIO_LAYER_NOT_SUPPORTED); } if (fr.stereo == 2) frame_samples = sample_bytes / 4; // 2 bytes per sample, 2 channels else frame_samples = sample_bytes / 2; // 2 bytes per sample, 1 channel extrapolated_pts = frame_pts + (27000000 * (__int64)frame_samples) / (__int64)fr.sample_rate; extrapolated_pts_valid = true; } void MPEGAudio::SearchPacket() { last_pts = current_pts; last_pts_used = current_pts_used; do { up->NextPacket(); } while (up->GetStreamID() != (AUDIO_STREAM_0 + stream_id)); if (up->HasPTS()) { current_pts = up->GetPTS(); current_pts_used = false; } else current_pts_used = true; payload_size = up->GetPayloadSize(); payload_pos = 0; } unsigned char MPEGAudio::GetByte() { unsigned char val; if (payload_pos >= payload_size) SearchPacket(); val = up->GetPayloadByte(); payload_pos++; return val; } void MPEGAudio::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; } } }