www.pudn.com > mediator15src.zip > audiosync.cpp
/* * audiosync.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 "audiosync.h" #include "string.h" static const int num_denom[][2] = { { 24000, 1001 }, { 24, 1 }, { 25, 1 }, { 30000, 1001 }, { 30, 1 }, { 50, 1 }, { 60000, 1001 }, { 60, 1 } }; AudioSync::AudioSync() { ass_buffer = 0; frm_buffer = 0; max_delta = 27000000 / 20; } AudioSync::~AudioSync() { if (ass_buffer) delete[] ass_buffer; if (frm_buffer) delete[] frm_buffer; } void AudioSync::SetInput(MPEGStream *stream) { int frameratecode; int max_bytes_per_frame; this->stream = stream; frameratecode = stream->GetFinalFramerateCode(); if ((frameratecode < 1) || (frameratecode > 8)) frameratecode = 3; // default: 25fps rate_numerator = num_denom[frameratecode - 1][0]; rate_denominator = num_denom[frameratecode - 1][1]; total_frames = 0; total_samples = 0; start_pts = stream->GetStartPTS(); samplerate = stream->GetSampleRate(); channels = stream->IsStereo() ? 2 : 1; samples_per_frame = (rate_denominator * samplerate) / rate_numerator; frame_duration = (27000000 * (__int64)rate_denominator) / rate_numerator; if (samples_per_frame * rate_numerator != samplerate * rate_denominator) samples_per_frame++; max_bytes_per_frame = 2 * samples_per_frame * channels + 2 * 2 * channels; ass_buffer = new short[max_bytes_per_frame / 2]; frm_buffer = new short[FRM_BUFFER_SIZE * channels]; frm_samplesi = 0; frm_samples = 0; mute_samples = 0; last_frame_size = 0; finished = false; } void AudioSync::Mute(short *samples, int samplecount) { for (int i = 0; i < samplecount * channels; i++) *samples++ = 0; } void AudioSync::GetSameFrame(short ***dest, int *framesize, bool has_alloc) { if (!has_alloc) { out_buffer = ass_buffer; *dest = &out_buffer; } *framesize = last_frame_size; } bool AudioSync::GetFrame(short ***dest, int *framesize, bool has_alloc) { __int64 samples_cont; __int64 pts_slot; int out_samples; int out_samplesi; __int64 frm_pts; __int64 frm_pts_upper; if (has_alloc) out_buffer = **dest; else { out_buffer = ass_buffer; *dest = &out_buffer; } if (finished) { *framesize = samples_per_frame * channels * 2; return false; } pts_slot = ((__int64)total_frames * rate_denominator * 27000000) / rate_numerator; samples_cont = (total_samples * 27000000) / samplerate; out_samplesi = 0; out_samples = (int) (((pts_slot + frame_duration - samples_cont) * samplerate) / 27000000); while (out_samplesi != out_samples) { if (mute_samples > 0) { if (mute_samples <= (out_samples - out_samplesi)) { Mute(&out_buffer[out_samplesi * channels], mute_samples); out_samplesi += mute_samples; total_samples += mute_samples; mute_samples = 0; } else { Mute(&out_buffer[out_samplesi * channels], out_samples - out_samplesi); mute_samples -= out_samples - out_samplesi; total_samples += out_samples - out_samplesi; out_samplesi = out_samples; } } else { if (frm_samplesi >= frm_samples) { try { stream->GetAudioFrame(frm_buffer); } catch (...) { finished = true; *framesize = last_frame_size = out_samplesi * 2 * channels; if (out_samplesi != 0) return true; else return false; } frm_pts = stream->GetAudioFramePTS(); frm_samples = stream->GetSampleCount(); pts_slot = start_pts + (total_samples * 27000000) / samplerate; frm_samplesi = 0; if (frm_pts > (pts_slot + max_delta)) mute_samples = (int)(((frm_pts - pts_slot) * samplerate) / 27000000); else if (frm_pts < (pts_slot - max_delta)) { frm_pts_upper = frm_pts + ((frm_samples - 1) * 27000000) / samplerate; while (pts_slot > frm_pts_upper) { try { stream->GetAudioFrame(frm_buffer); } catch (...) { finished = true; *framesize = last_frame_size = out_samplesi * 2 * channels; if (out_samplesi != 0) return true; else return false; } frm_pts = stream->GetAudioFramePTS(); frm_samples = stream->GetSampleCount(); frm_pts_upper = frm_pts + ((frm_samples - 1) * 27000000) / samplerate; } if (frm_pts > pts_slot) mute_samples = (int)(((frm_pts - pts_slot) * samplerate) / 27000000); else frm_samplesi = (int)(((pts_slot - frm_pts) * samplerate) / 27000000); } } else { if ((frm_samples - frm_samplesi) <= (out_samples - out_samplesi)) { memcpy(&out_buffer[out_samplesi * channels], &frm_buffer[frm_samplesi * channels], (frm_samples - frm_samplesi) * 2 * channels); out_samplesi += frm_samples - frm_samplesi; total_samples += frm_samples - frm_samplesi; frm_samplesi = frm_samples; } else { memcpy(&out_buffer[out_samplesi * channels], &frm_buffer[frm_samplesi * channels], (out_samples - out_samplesi) * 2 * channels); frm_samplesi += out_samples - out_samplesi; total_samples += out_samples - out_samplesi; out_samplesi = out_samples; } } } } total_frames++; *framesize = last_frame_size = out_samplesi * 2 * channels; return true; }