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