1 /*
2 * audiostrm_in.c: MPEG Audio strem class members handling scanning
3 * and buffering raw input stream.
4 *
5 * Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
6 *
7 *
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.
11 *
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.
16 *
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.
20 */
21
22 #include <config.h>
23 #include <math.h>
24 #include <stdlib.h>
25
26 #include "audiostrm.hpp"
27 #include "interact.hpp"
28 #include "multiplexor.hpp"
29
30
31 static const char *mpa_audio_version[4] =
32 {
33 "2.5",
34 "2.0",
35 "reserved",
36 "1.0"
37 };
38
39 static const unsigned int mpa_bitrates_kbps [4][3][16] =
40 {
41 { /* MPEG audio V2.5 */
42 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
43 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
44 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}
45 },
46 { /*RESERVED*/
47 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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 },
51 { /* MPEG audio V2 */
52 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
53 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
54 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}
55 },
56 { /* MPEG audio V1 */
57 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
58 {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
59 {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}
60 }
61
62 };
63
64
65 static const int mpa_freq_table [4][4] =
66 {
67 /* MPEG audio V2.5 */
68 {11025,12000,8000,0},
69 /* RESERVED */
70 { 0, 0, 0, 0 },
71 /* MPEG audio V2 */
72 {22050,24000, 16000,0},
73 /* MPEG audio V1 */
74 {44100, 48000, 32000, 0}
75 };
76
77 static const char mpa_stereo_mode [4][15] =
78 { "stereo", "joint stereo", "dual channel", "single channel" };
79 static const char mpa_copyright_status [2][20] =
80 { "no copyright","copyright protected" };
81 static const char mpa_original_bit [2][10] =
82 { "copy","original" };
83 static const char mpa_emphasis_mode [4][20] =
84 { "none", "50/15 microseconds", "reserved", "CCITT J.17" };
85 static const unsigned int mpa_slots [4] = {12, 144, 144, 0};
86 static const unsigned int mpa_samples [4] = {384, 1152, 1152, 0};
87
88
89
MPAStream(IBitStream & ibs,Multiplexor & into)90 MPAStream::MPAStream(IBitStream &ibs, Multiplexor &into) :
91 AudioStream( ibs, into )
92 {
93 for( int i = 0; i <2 ; ++i )
94 num_frames[i] = size_frames[i] = 0;
95 }
96
Probe(IBitStream & bs)97 bool MPAStream::Probe(IBitStream &bs )
98 {
99 return bs.GetBits(11) == AUDIO_SYNCWORD;
100 }
101
102
103 /*************************************************************************
104 *
105 * Reads initial stream parameters and displays feedback banner to users
106 *
107 *************************************************************************/
108
109
Init(const int stream_num)110 void MPAStream::Init ( const int stream_num )
111
112 {
113 int padding_bit;
114
115 MuxStream::Init( AUDIO_STR_0 + stream_num,
116 0, // Buffer scale
117 muxinto.audio_buffer_size,
118 muxinto.vcd_zero_stuffing,
119 muxinto.buffers_in_audio,
120 muxinto.always_buffers_in_audio
121 );
122 mjpeg_info ("Scanning for header info: Audio stream %02x (%s)",
123 AUDIO_STR_0 + stream_num,
124 bs.StreamName()
125 );
126
127 /* A.Stevens 2000 - update to be compatible up to MPEG2.5
128 */
129 AU_start = bs.bitcount();
130 if (bs.GetBits(11)==AUDIO_SYNCWORD)
131 {
132 num_syncword++;
133 version_id = bs.GetBits( 2);
134 layer = 3-bs.GetBits( 2); /* 0..2 not 1..3!! */
135 protection = bs.Get1Bit();
136 bit_rate_code = bs.GetBits( 4);
137 frequency = bs.GetBits( 2);
138 padding_bit = bs.Get1Bit();
139 bs.Get1Bit();
140 mode = bs.GetBits( 2);
141 mode_extension = bs.GetBits( 2);
142 copyright = bs.Get1Bit();
143 original_copy = bs.Get1Bit ();
144 emphasis = bs.GetBits( 2);
145
146 framesize =
147 mpa_bitrates_kbps[version_id][layer][bit_rate_code] *
148 mpa_slots[layer] *1000 /
149 mpa_freq_table[version_id][frequency];
150
151 size_frames[0] = framesize * ( layer == 0 ? 4 : 1);
152 size_frames[1] = (framesize+1) * ( layer == 0 ? 4 : 1);
153 num_frames[padding_bit]++;
154 access_unit.start = AU_start;
155 access_unit.length = size_frames[padding_bit];
156
157 samples_per_second = mpa_freq_table[version_id][frequency];
158 if (!samples_per_second) {
159 mjpeg_error ( "Invalid frequency in MPEG Audio stream header.");
160 exit(1);
161 }
162
163 /* Presentation time-stamping */
164 access_unit.PTS = static_cast<clockticks>(decoding_order) *
165 static_cast<clockticks>(mpa_samples [layer]) *
166 static_cast<clockticks>(CLOCKS) / samples_per_second;
167 access_unit.DTS = access_unit.PTS;
168 access_unit.dorder = decoding_order;
169 ++decoding_order;
170 aunits.Append( access_unit );
171
172 } else
173 {
174 mjpeg_error ( "Invalid MPEG Audio stream header.");
175 exit (1);
176 }
177
178
179 OutputHdrInfo();
180 }
181
NominalBitRate()182 unsigned int MPAStream::NominalBitRate()
183 {
184 return mpa_bitrates_kbps[version_id][layer][bit_rate_code]*1024;
185 }
186
187
SizeFrame(int rate_code,int padding)188 unsigned int MPAStream::SizeFrame( int rate_code, int padding )
189 {
190 return ( mpa_bitrates_kbps[version_id][layer][rate_code] *
191 mpa_slots [layer] *1000 /
192 mpa_freq_table[version_id][frequency] + padding ) * ( layer == 0 ? 4 : 1);
193 }
194
FillAUbuffer(unsigned int frames_to_buffer)195 void MPAStream::FillAUbuffer(unsigned int frames_to_buffer )
196 {
197 unsigned int padding_bit;
198 last_buffered_AU += frames_to_buffer;
199
200 if( eoscan )
201 return;
202
203 mjpeg_debug( "Scanning %d MPA frames to frame %d",
204 frames_to_buffer,
205 last_buffered_AU );
206 while( !bs.eos()
207 && decoding_order < last_buffered_AU
208 && !muxinto.AfterMaxPTS(access_unit.PTS) )
209 {
210
211 int skip=access_unit.length-4;
212 bs.SeekFwdBits( skip );
213 prev_offset = AU_start;
214 AU_start = bs.bitcount();
215 if( AU_start - prev_offset != access_unit.length*8 )
216 {
217 mjpeg_warn("Discarding incomplete final frame MPEG audio stream %02x!",
218 stream_id
219 );
220 aunits.DropLast();
221 --decoding_order;
222 break;
223 }
224 /* Check we have reached the end of have another catenated
225 stream to process before finishing ... */
226 if ( (syncword = bs.GetBits( 11))!=AUDIO_SYNCWORD )
227 {
228 //
229 // Handle a broken last frame...
230 if( !bs.eos() )
231 {
232 mjpeg_warn( "Data follows end of last recogniseable MPEG audio frame - bad stream?");
233 eoscan = true;
234 return;
235 }
236 break;
237 }
238 // Skip version_id:2, layer:2, protection:1
239 (void) bs.GetBits( 5);
240 int rate_code = bs.GetBits( 4);
241 // Skip frequency
242 (void) bs.GetBits( 2);
243
244 padding_bit=bs.Get1Bit();
245 access_unit.start = AU_start;
246 access_unit.length = SizeFrame( rate_code, padding_bit );
247 access_unit.PTS = static_cast<clockticks>(decoding_order) * static_cast<clockticks>(mpa_samples[layer]) * static_cast<clockticks>(CLOCKS)
248 / samples_per_second;
249 access_unit.DTS = access_unit.PTS;
250 access_unit.dorder = decoding_order;
251 decoding_order++;
252 aunits.Append( access_unit );
253 num_frames[padding_bit]++;
254
255 bs.GetBits( 9);
256
257 num_syncword++;
258
259 if (num_syncword >= old_frames+10 )
260 {
261 mjpeg_debug ("Got %d frame headers.", num_syncword);
262 old_frames=num_syncword;
263
264 }
265
266
267
268 }
269 last_buffered_AU = decoding_order;
270 eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);
271 }
272
273
274
Close()275 void MPAStream::Close()
276 {
277 stream_length = AU_start >> 3;
278 mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id);
279 mjpeg_info ("Audio stream length %lld bytes.", stream_length);
280 mjpeg_info ("Syncwords : %8u",num_syncword);
281 mjpeg_info ("Frames : %8u padded", num_frames[0]);
282 mjpeg_info ("Frames : %8u unpadded", num_frames[1]);
283
284 }
285
286 /*************************************************************************
287 OutputAudioInfo
288 gibt gesammelte Informationen zu den Audio Access Units aus.
289
290 Prints information on audio access units
291 *************************************************************************/
292
OutputHdrInfo()293 void MPAStream::OutputHdrInfo ()
294 {
295 unsigned int bitrate;
296 bitrate = mpa_bitrates_kbps[version_id][layer][bit_rate_code];
297
298
299 mjpeg_info("MPEG AUDIO STREAM: %02x", stream_id);
300 mjpeg_info("Audio version : %s", mpa_audio_version[version_id]);
301 mjpeg_info("Layer : %8u",layer+1);
302
303 if (protection == 0) mjpeg_info ("CRC checksums : yes");
304 else mjpeg_info ("CRC checksums : no");
305
306 if (bit_rate_code == 0)
307 mjpeg_info ("Bit rate : free");
308 else if (bit_rate_code == 0xf)
309 mjpeg_info ("Bit rate : reserved");
310 else
311 mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)",
312 bitrate*128, bitrate);
313
314 if (frequency == 3)
315 mjpeg_info ("Frequency : reserved");
316 else
317 mjpeg_info ("Frequency : %d Hz",
318 mpa_freq_table[version_id][frequency]);
319
320 mjpeg_info ("Mode : %8u %s",
321 mode,mpa_stereo_mode[mode]);
322 mjpeg_info ("Mode extension : %8u",mode_extension);
323 mjpeg_info ("Copyright bit : %8u %s",
324 copyright,mpa_copyright_status[copyright]);
325 mjpeg_info ("Original/Copy : %8u %s",
326 original_copy,mpa_original_bit[original_copy]);
327 mjpeg_info ("Emphasis : %8u %s",
328 emphasis,mpa_emphasis_mode[emphasis]);
329 }
330
331
332
333 /*
334 * Local variables:
335 * c-file-style: "stroustrup"
336 * tab-width: 4
337 * indent-tabs-mode: nil
338 * End:
339 */
340