2
* audiostrm_in.c: MPEG Audio strem class members handling scanning
3
* and buffering raw input stream.
5
* Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of version 2 of the GNU General Public License
10
* as published by the Free Software Foundation.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
#include "audiostrm.hpp"
27
#include "interact.hpp"
28
#include "multiplexor.hpp"
30
#define mjpeg_info mjpeg_warn
32
static const char *mpa_audio_version[4] =
40
static const unsigned int mpa_bitrates_kbps [4][3][16] =
42
{ /* MPEG audio V2.5 */
43
{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
44
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
45
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}
48
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
49
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
50
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
53
{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
54
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
55
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}
58
{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
59
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
60
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}
66
static const int mpa_freq_table [4][4] =
73
{22050,24000, 16000,0},
75
{44100, 48000, 32000, 0}
78
static const char mpa_stereo_mode [4][15] =
79
{ "stereo", "joint stereo", "dual channel", "single channel" };
80
static const char mpa_copyright_status [2][20] =
81
{ "no copyright","copyright protected" };
82
static const char mpa_original_bit [2][10] =
83
{ "copy","original" };
84
static const char mpa_emphasis_mode [4][20] =
85
{ "none", "50/15 microseconds", "reserved", "CCITT J.17" };
86
static const unsigned int mpa_slots [4] = {12, 144, 144, 0};
87
static const unsigned int mpa_samples [4] = {384, 1152, 1152, 0};
91
MPAStream::MPAStream(IBitStream &ibs, Multiplexor &into) :
92
AudioStream( ibs, into )
94
for( int i = 0; i <2 ; ++i )
95
num_frames[i] = size_frames[i] = 0;
98
bool MPAStream::Probe(IBitStream &bs )
100
return bs.GetBits(11) == AUDIO_SYNCWORD;
104
/*************************************************************************
106
* Reads initial stream parameters and displays feedback banner to users
108
*************************************************************************/
111
void MPAStream::Init ( const int stream_num )
116
MuxStream::Init( AUDIO_STR_0 + stream_num,
118
muxinto.audio_buffer_size,
119
muxinto.vcd_zero_stuffing,
120
muxinto.buffers_in_audio,
121
muxinto.always_buffers_in_audio
123
mjpeg_info ("Scanning for header info: Audio stream %02x (%s)",
124
AUDIO_STR_0 + stream_num,
130
/* A.Stevens 2000 - update to be compatible up to MPEG2.5
132
AU_start = bs.bitcount();
133
if (bs.GetBits(11)==AUDIO_SYNCWORD)
136
version_id = bs.GetBits( 2);
137
layer = 3-bs.GetBits( 2); /* 0..2 not 1..3!! */
138
protection = bs.Get1Bit();
139
bit_rate_code = bs.GetBits( 4);
140
frequency = bs.GetBits( 2);
141
padding_bit = bs.Get1Bit();
143
mode = bs.GetBits( 2);
144
mode_extension = bs.GetBits( 2);
145
copyright = bs.Get1Bit();
146
original_copy = bs.Get1Bit ();
147
emphasis = bs.GetBits( 2);
150
mpa_bitrates_kbps[version_id][layer][bit_rate_code] *
151
mpa_slots[layer] *1000 /
152
mpa_freq_table[version_id][frequency];
154
size_frames[0] = framesize;
155
size_frames[1] = framesize+( layer == 0 ? 4 : 1);
156
num_frames[padding_bit]++;
157
access_unit.start = AU_start;
158
access_unit.length = size_frames[padding_bit];
160
samples_per_second = mpa_freq_table[version_id][frequency];
162
/* Presentation time-stamping */
163
access_unit.PTS = static_cast<clockticks>(decoding_order) *
164
static_cast<clockticks>(mpa_samples [layer]) *
165
static_cast<clockticks>(CLOCKS) / samples_per_second;
166
access_unit.DTS = access_unit.PTS;
167
access_unit.dorder = decoding_order;
169
aunits.append( access_unit );
173
mjpeg_error ( "Invalid MPEG Audio stream header.");
181
unsigned int MPAStream::NominalBitRate()
183
return mpa_bitrates_kbps[version_id][layer][bit_rate_code]*1024;
187
unsigned int MPAStream::SizeFrame( int rate_code, int padding )
189
return mpa_bitrates_kbps[version_id][layer][rate_code] *
190
mpa_slots [layer] *1000 /
191
mpa_freq_table[version_id][frequency] + padding;
194
void MPAStream::FillAUbuffer(unsigned int frames_to_buffer )
196
unsigned int padding_bit;
197
last_buffered_AU += frames_to_buffer;
202
mjpeg_debug( "Scanning %d MPA frames to frame %d",
206
&& decoding_order < last_buffered_AU
207
&& !muxinto.AfterMaxPTS(access_unit.PTS) )
210
int skip=access_unit.length-4;
211
bs.SeekFwdBits( skip );
212
prev_offset = AU_start;
213
AU_start = bs.bitcount();
214
if( AU_start - prev_offset != access_unit.length*8 )
216
mjpeg_warn("Discarding incomplete final frame MPEG audio stream %02x!",
223
/* Check we have reached the end of have another catenated
224
stream to process before finishing ... */
225
if ( (syncword = bs.GetBits( 11))!=AUDIO_SYNCWORD )
228
// Handle a broken last frame...
231
mjpeg_warn( "Data follows end of last recogniseable MPEG audio frame - bad stream?");
237
// Skip version_id:2, layer:2, protection:1
238
(void) bs.GetBits( 5);
239
int rate_code = bs.GetBits( 4);
241
(void) bs.GetBits( 2);
243
padding_bit=bs.Get1Bit();
244
access_unit.start = AU_start;
245
access_unit.length = SizeFrame( rate_code, padding_bit );
246
access_unit.PTS = static_cast<clockticks>(decoding_order) * static_cast<clockticks>(mpa_samples[layer]) * static_cast<clockticks>(CLOCKS)
247
/ samples_per_second;
248
access_unit.DTS = access_unit.PTS;
249
access_unit.dorder = decoding_order;
251
aunits.append( access_unit );
252
num_frames[padding_bit]++;
258
if (num_syncword >= old_frames+10 )
260
mjpeg_debug ("Got %d frame headers.", num_syncword);
261
old_frames=num_syncword;
268
last_buffered_AU = decoding_order;
269
eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);
274
void MPAStream::Close()
276
stream_length = AU_start >> 3;
277
mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id);
278
mjpeg_info ("Audio stream length %lld bytes.", stream_length);
279
mjpeg_info ("Syncwords : %8u",num_syncword);
280
mjpeg_info ("Frames : %8u padded", num_frames[0]);
281
mjpeg_info ("Frames : %8u unpadded", num_frames[1]);
285
/*************************************************************************
287
gibt gesammelte Informationen zu den Audio Access Units aus.
289
Prints information on audio access units
290
*************************************************************************/
292
void MPAStream::OutputHdrInfo ()
294
unsigned int bitrate;
295
bitrate = mpa_bitrates_kbps[version_id][layer][bit_rate_code];
298
mjpeg_info("MPEG AUDIO STREAM: %02x", stream_id);
299
mjpeg_info("Audio version : %s", mpa_audio_version[version_id]);
300
mjpeg_info("Layer : %8u",layer+1);
302
if (protection == 0) mjpeg_info ("CRC checksums : yes");
303
else mjpeg_info ("CRC checksums : no");
305
if (bit_rate_code == 0)
306
mjpeg_info ("Bit rate : free");
307
else if (bit_rate_code == 0xf)
308
mjpeg_info ("Bit rate : reserved");
310
mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)",
311
bitrate*128, bitrate);
314
mjpeg_info ("Frequency : reserved");
316
mjpeg_info ("Frequency : %d Hz",
317
mpa_freq_table[version_id][frequency]);
319
mjpeg_info ("Mode : %8u %s",
320
mode,mpa_stereo_mode[mode]);
321
mjpeg_info ("Mode extension : %8u",mode_extension);
322
mjpeg_info ("Copyright bit : %8u %s",
323
copyright,mpa_copyright_status[copyright]);
324
mjpeg_info ("Original/Copy : %8u %s",
325
original_copy,mpa_original_bit[original_copy]);
326
mjpeg_info ("Emphasis : %8u %s",
327
emphasis,mpa_emphasis_mode[emphasis]);
334
* c-file-style: "stroustrup"
336
* indent-tabs-mode: nil