www.pudn.com > mediator15src.zip > lpcmaudio.cpp
/* * lpcmaudio.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 "lpcmaudio.h" #include "startcodes.h" LPCMAudio::LPCMAudio() { up = new Unpacketizer(); } LPCMAudio::~LPCMAudio() { if (up) delete up; } void LPCMAudio::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 LPCMAudio::GetFrame(short *sample_buffer) { unsigned char *sample_bytes, *sample_bytes_2; int i, frame_offset, frame_size; unsigned char tmp; up->Resync(); if (audio_seek) { frame_offset = SearchPacket(); up->FlushPayloadBytes(frame_offset); payload_pos = frame_offset; lpcm_identifier = up->GetLPCMType(); audio_seek = false; } restart: if (lpcm_identifier == 0x0180) { frame_size = 320; // 80 samples, 16 bit, stereo GetBytes((unsigned char *)sample_buffer, frame_size); // big-endian to little-endian conversion sample_bytes = (unsigned char *)sample_buffer; for (i = 0; i < 80 * 2; i++) { tmp = sample_bytes[0]; sample_bytes[0] = sample_bytes[1]; sample_bytes[1] = tmp; sample_bytes += 2; } } else if (lpcm_identifier == 0x9180) { frame_size = 960; // 160 samples, 24 bit, stereo GetBytes((unsigned char *)sample_buffer, frame_size); sample_bytes = sample_bytes_2 = (unsigned char *)sample_buffer; for (i = 0; i < 80; i++) { tmp = *sample_bytes_2++; *sample_bytes++ = *sample_bytes_2++; *sample_bytes++ = tmp; tmp = *sample_bytes_2++; *sample_bytes++ = *sample_bytes_2++; *sample_bytes++ = tmp; sample_bytes_2 += 8; // skip lsb's and "resample" to 48kHz } } else if (lpcm_identifier == 0x4180) { frame_size = 400; // 80 samples, 20 bit, stereo GetBytes((unsigned char *)sample_buffer, frame_size); sample_bytes = sample_bytes_2 = (unsigned char *)sample_buffer; for (i = 0; i < 40; i++) { tmp = *sample_bytes_2++; *sample_bytes++ = *sample_bytes_2++; *sample_bytes++ = tmp; tmp = *sample_bytes_2++; *sample_bytes++ = *sample_bytes_2++; *sample_bytes++ = tmp; tmp = *sample_bytes_2++; *sample_bytes++ = *sample_bytes_2++; *sample_bytes++ = tmp; tmp = *sample_bytes_2++; *sample_bytes++ = *sample_bytes_2++; *sample_bytes++ = tmp; sample_bytes_2 += 2; // skip lsb's } } if (payload_pos < frame_size) { // 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 } frame_samples = 80; sample_rate = 48000; extrapolated_pts = frame_pts + (27000000 * (__int64)frame_samples) / (__int64)sample_rate; extrapolated_pts_valid = true; } int LPCMAudio::SearchPacket() { last_pts = current_pts; last_pts_used = current_pts_used; do { up->NextPacket(); } while ((up->GetStreamID() != PRIVATE_STREAM_1) || (up->GetSubstreamID() != (SUBSTREAM_LPCM_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; return up->GetAudioFrameOffset() - 4; } void LPCMAudio::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; } } }