1 /*
2 * ac3strm_in.c: AC3 Audio strem class members handling scanning and
3 * buffering raw input stream.
4 *
5 * Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
6 * Copyright (C) 2000,2001 Brent Byeler for original header-structure
7 * parsing code.
8 *
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public License
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24 #include <config.h>
25 #include <math.h>
26 #include <stdlib.h>
27
28 #include "audiostrm.hpp"
29 #include "interact.hpp"
30 #include "multiplexor.hpp"
31
32 //#define DEBUG_AC3_HEADERS
33 #define AC3_SYNCWORD 0x0b77
34 #define AC3_PACKET_SAMPLES 1536
35
36 const unsigned int AC3Stream::default_buffer_size = 16*1024;
37
38 /// table for the available AC3 bitrates
39 static const unsigned int ac3_bitrate_index[32] =
40 { 32,40,48,56,64,80,96,112,128,160,192,
41 224,256,320,384,448,512,576,640,
42 0,0,0,0,0,0,0,0,0,0,0,0,0
43 };
44
45 static const unsigned int ac3_frame_size[3][32] =
46 {
47 { 64,80,96,112,128,160,192,224,256,320,384,
48 448,512,640,768,896,1024, 1152,1280,
49 0,0,0,0,0,0,0,0,0,0,0,0,0
50 },
51 { 69,87,104,121,139,174,208,243,278,348,417,
52 487,557,696,835,975,1114, 1253,1393,
53 0,0,0,0,0,0,0,0,0,0,0,0,0
54 },
55 { 96,120,144,168,192,240,288,336,384,480,576,
56 672,768,960,1152,1344, 1536,1728,1920,
57 0,0,0,0,0,0,0,0,0,0,0,0,0
58 }
59 };
60
61 /// table for the available AC3 frequencies
62 static const unsigned int ac3_frequency[4] =
63 { 48000, 44100, 32000, 0};
64
65
AC3Stream(IBitStream & ibs,Multiplexor & into)66 AC3Stream::AC3Stream(IBitStream &ibs, Multiplexor &into) :
67 AudioStream( ibs, into )
68 {
69 num_frames = 0;
70 }
71
Probe(IBitStream & bs)72 bool AC3Stream::Probe(IBitStream &bs )
73 {
74 return bs.GetBits(16) == AC3_SYNCWORD;
75 }
76
77
78 /*************************************************************************
79 *
80 * Reads initial stream parameters and displays feedback banner to users
81 * @param stream_num AC3 substream ID
82 *************************************************************************/
83
84
DisplayAc3HeaderInfo()85 void AC3Stream::DisplayAc3HeaderInfo()
86 {
87 /* Some stuff to generate frame-header information */
88 printf( "bsid = %d\n", bs.GetBits(5) );
89 printf( "bsmode = 0x%1x\n", bs.GetBits(3) );
90 int acmode = bs.GetBits(3);
91 int nfchans = 0;
92 switch( acmode )
93 {
94 case 0x0 :
95 nfchans = 2; break;
96 case 0x1 :
97 nfchans = 1; break;
98 case 0x2 :
99 nfchans = 2; break;
100 case 0x3 :
101 case 0x4 :
102 nfchans = 3; break;
103 case 0x5 :
104 case 0x6 :
105 nfchans = 4; break;
106 case 0x7 :
107 nfchans = 5; break;
108 }
109 printf( "acmode = 0x%1x (%d channels)\n", acmode, nfchans );
110 if( (acmode & 0x1) && (acmode != 1 ) )
111 printf( "cmixlev = %d\n", bs.GetBits(2) );
112 if( (acmode & 0x4) )
113 printf( "smixlev = %d\n", bs.GetBits(2) );
114 if( acmode == 2 )
115 printf( "dsurr = %d\n", bs.GetBits(2) );
116 printf( "lfeon = %d\n", bs.GetBits(1) );
117 printf( "dialnorm = %02d\n", bs.GetBits(5) );
118 int compre = bs.GetBits(1);
119 printf( "compre = %d\n", compre );
120 if( compre )
121 printf( "compr = %02d\n", bs.GetBits(8) );
122 int langcode = bs.GetBits(1);
123 printf( "langcode = %d\n", langcode );
124 if( langcode )
125 printf( "langcod = 0x%02x\n", bs.GetBits(8) );
126 int audprodie = bs.GetBits(1);
127 printf( "audprodie = %d\n", audprodie );
128 if( audprodie )
129 {
130 printf( "mixlevel = 0x%02x\n", bs.GetBits(5) );
131 printf( "roomtyp = 0x%02x\n", bs.GetBits(2) );
132 }
133 if( acmode == 0 )
134 {
135 printf( "Skipping 1+1 mode parameters\n" );
136 bs.GetBits(5+1+8+1+8);
137 if( bs.GetBits(1) )
138 bs.GetBits(7);
139 }
140 printf( "Copyright = %d\n", bs.GetBits(1) );
141 printf( "Original = %d\n", bs.GetBits(1) );
142 int timecod1e = bs.GetBits(1);
143 if( timecod1e )
144 {
145 printf( "timecod1 = 0x%03x\n", bs.GetBits(14) );
146 }
147 int timecod2e = bs.GetBits(1);
148 if( timecod2e )
149 {
150 printf( "timecod2 = 0x%03x\n", bs.GetBits(14) );
151 }
152 int addbsie = bs.GetBits(1);
153 if( addbsie )
154 {
155 printf( "addbsil = %02x\n", bs.GetBits(6) );
156 }
157
158
159 // FROM This point on we're actually right into the actual audio block
160 printf( "Audio block header...\n" );
161 printf( "blksw [ch] = %02x\n", bs.GetBits(nfchans) );
162 printf( "dithflg[ch] = %02x\n", bs.GetBits(nfchans) );
163 int dynrnge = bs.GetBits(1);
164 printf( "Dynrange = %d\n", bs.GetBits(1) );
165 if( dynrnge )
166 {
167 printf( "dynrng = %02x\n", bs.GetBits(8) );
168 }
169 if( acmode == 0 && bs.GetBits(1) )
170 {
171 printf( "dynrng2 = %02x\n", bs.GetBits(8) );
172 }
173 int cplstre = bs.GetBits(1);
174 printf( "cplstre = %d\n", cplstre );
175 int cplinu = 0;
176 if( cplstre )
177 {
178 cplinu = bs.GetBits(1);
179 printf( "cplinu = %d\n", cplinu );
180 if( cplinu )
181 {
182 printf( "Skipping cplinu=1 info...\n");
183 bs.GetBits(nfchans);
184 if( acmode == 2 )
185 bs.GetBits(1);
186 int cplbegf = bs.GetBits(4);
187 int cplendf = bs.GetBits(4);
188 bs.GetBits(3+cplbegf-cplendf);
189 }
190 }
191 if( cplinu )
192 {
193 printf( "Warning: no parser for coupling co-ordinates mess\n");
194 return;
195 }
196
197 if( acmode == 2 )
198 {
199 int rmatstr = bs.GetBits(1);
200 printf( "rmatstr = %d\n", rmatstr );
201 printf( "Warning: no parser for rematrixing...\n" );
202 }
203
204
205 }
206
Init(const int _stream_num)207 void AC3Stream::Init ( const int _stream_num)
208
209 {
210 unsigned int framesize_code;
211 stream_num = _stream_num;
212 MuxStream::Init( PRIVATE_STR_1,
213 1, // Buffer scale
214 default_buffer_size,
215 false,
216 muxinto.buffers_in_audio,
217 muxinto.always_buffers_in_audio
218 );
219 mjpeg_info ("Scanning for header info: AC3 Audio stream %02x (%s)",
220 stream_num,
221 bs.StreamName()
222 );
223
224 AU_start = bs.bitcount();
225 if (bs.GetBits(16)==AC3_SYNCWORD)
226 {
227 num_syncword++;
228 bs.GetBits(16); // CRC field
229 frequency = bs.GetBits(2); // Sample rate code
230 framesize_code = bs.GetBits(6); // Frame size code
231 framesize = ac3_frame_size[frequency][framesize_code>>1];
232 framesize =
233 (framesize_code&1) && frequency == 1 ?
234 (framesize + 1) << 1:
235 (framesize <<1);
236
237 header_skip = 5; // Initially skipped past 5 bytes of header
238
239 num_frames++;
240 access_unit.start = AU_start;
241 access_unit.length = framesize;
242 mjpeg_info( "AC3 frame size = %d", framesize );
243 bit_rate = ac3_bitrate_index[framesize_code>>1];
244 samples_per_second = ac3_frequency[frequency];
245
246 /* Presentation time-stamping */
247 access_unit.PTS = static_cast<clockticks>(decoding_order) *
248 static_cast<clockticks>(AC3_PACKET_SAMPLES) *
249 static_cast<clockticks>(CLOCKS) / samples_per_second;
250 access_unit.DTS = access_unit.PTS;
251 access_unit.dorder = decoding_order;
252 ++decoding_order;
253 aunits.Append( access_unit );
254
255 } else
256 {
257 mjpeg_error ( "Invalid AC3 Audio stream header.");
258 exit (1);
259 }
260
261
262 OutputHdrInfo();
263 }
264
265 /// @returns the current bitrate
NominalBitRate()266 unsigned int AC3Stream::NominalBitRate()
267 {
268 return bit_rate*1024;
269 }
270
271 /// Prefills the internal buffer for output multiplexing.
272 /// @param frames_to_buffer the number of audio frames to read ahead
FillAUbuffer(unsigned int frames_to_buffer)273 void AC3Stream::FillAUbuffer(unsigned int frames_to_buffer )
274 {
275 unsigned int framesize_code;
276
277 last_buffered_AU += frames_to_buffer;
278 mjpeg_debug( "Scanning %d AC3 audio frames to frame %d",
279 frames_to_buffer, last_buffered_AU );
280
281 int skip;
282 while( !bs.eos()
283 && decoding_order < last_buffered_AU
284 && !muxinto.AfterMaxPTS(access_unit.PTS)
285 )
286 {
287 skip=access_unit.length-header_skip;
288 bs.SeekFwdBits(skip);
289 prev_offset = AU_start;
290 AU_start = bs.bitcount();
291 if( AU_start - prev_offset != access_unit.length*8 )
292 {
293 mjpeg_warn( "Discarding incomplete final frame AC3 stream %d!",
294 stream_num);
295 aunits.DropLast();
296 --decoding_order;
297 break;
298 }
299
300 /* Check we have reached the end of have another catenated
301 stream to process before finishing ... */
302 if ( (syncword = bs.GetBits(16))!=AC3_SYNCWORD )
303 {
304 if( !bs.eos() )
305 {
306 mjpeg_error_exit1( "Can't find next AC3 frame: @ %lld we have %04x - broken bit-stream?", AU_start/8, syncword );
307 }
308 break;
309 }
310
311 bs.GetBits(16); // CRC field
312 bs.GetBits(2); // Sample rate code TOOD: check for change!
313 framesize_code = bs.GetBits(6);
314 framesize = ac3_frame_size[frequency][framesize_code>>1];
315 framesize =
316 (framesize_code&1) && frequency == 1 ?
317 (framesize + 1) << 1:
318 (framesize <<1);
319 access_unit.start = AU_start;
320 access_unit.length = framesize;
321 access_unit.PTS = static_cast<clockticks>(decoding_order) *
322 static_cast<clockticks>(AC3_PACKET_SAMPLES) *
323 static_cast<clockticks>(CLOCKS) / samples_per_second;;
324 access_unit.DTS = access_unit.PTS;
325 access_unit.dorder = decoding_order;
326 decoding_order++;
327 aunits.Append( access_unit );
328 num_frames++;
329
330 num_syncword++;
331
332 if (num_syncword >= old_frames+10 )
333 {
334 mjpeg_debug ("Got %d frame headers.", num_syncword);
335 old_frames=num_syncword;
336 }
337
338 }
339 last_buffered_AU = decoding_order;
340 eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);
341 }
342
343
344 /// Closes the AC3 stream and prints some statistics.
Close()345 void AC3Stream::Close()
346 {
347 stream_length = AU_start >> 3;
348 mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id);
349 mjpeg_info ("Audio stream length %lld bytes.", stream_length);
350 mjpeg_info ("Frames : %8u", num_frames);
351 }
352
353 /*************************************************************************
354 OutputAudioInfo
355 gibt gesammelte Informationen zu den Audio Access Units aus.
356
357 Prints information on audio access units
358 *************************************************************************/
359
OutputHdrInfo()360 void AC3Stream::OutputHdrInfo ()
361 {
362 mjpeg_info("AC3 AUDIO STREAM:");
363
364 mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)",
365 bit_rate*128, bit_rate);
366
367 if (frequency == 3)
368 mjpeg_info ("Frequency : reserved");
369 else
370 mjpeg_info ("Frequency : %d Hz",
371 ac3_frequency[frequency]);
372
373 }
374
375 /**
376 Reads the bytes neccessary to complete the current packet payload.
377 @param to_read number of bytes to read
378 @param dst byte buffer pointer to read to
379 @returns the number of bytes read
380 */
381 unsigned int
ReadPacketPayload(uint8_t * dst,unsigned int to_read)382 AC3Stream::ReadPacketPayload(uint8_t *dst, unsigned int to_read)
383 {
384 bitcount_t read_start = bs.GetBytePos();
385 // Remember to change StreamHeaderLen if you write a different
386 // length re-using this code...
387 unsigned int bytes_read = bs.GetBytes( dst+4, to_read-4 );
388 assert( bytes_read > 0 ); // Should never try to read nothing
389 bs.Flush( read_start );
390 clockticks decode_time;
391
392 unsigned int first_header =
393 (new_au_next_sec || au_unsent > bytes_read )
394 ? 0
395 : au_unsent;
396
397 // BUG BUG BUG: how do we set the 1st header pointer if we have
398 // the *middle* part of a large frame?
399 assert( first_header+2 <= to_read );
400
401 unsigned int syncwords = 0;
402 unsigned int bytes_muxed = bytes_read;
403
404 if (bytes_muxed == 0 || MuxCompleted() )
405 {
406 goto completion;
407 }
408
409
410 /* Work through what's left of the current AU and the following AU's
411 updating the info until we reach a point where an AU had to be
412 split between packets.
413 NOTE: It *is* possible for this loop to iterate.
414
415 The DTS/PTS field for the packet in this case would have been
416 given the that for the first AU to start in the packet.
417
418 */
419
420 decode_time = RequiredDTS();
421 while (au_unsent < bytes_muxed)
422 {
423 // BUG BUG BUG: if we ever had odd payload / packet size we might
424 // split an AC3 frame in the middle of the syncword!
425 assert( bytes_muxed > 1 );
426 bufmodel.Queued(au_unsent, decode_time);
427 bytes_muxed -= au_unsent;
428 if( new_au_next_sec )
429 ++syncwords;
430 if( !NextAU() )
431 {
432 goto completion;
433 }
434 new_au_next_sec = true;
435 decode_time = RequiredDTS();
436 };
437
438 // We've now reached a point where the current AU overran or
439 // fitted exactly. We need to distinguish the latter case
440 // so we can record whether the next packet starts with an
441 // existing AU or not - info we need to decide what PTS/DTS
442 // info to write at the start of the next packet.
443
444 if (au_unsent > bytes_muxed)
445 {
446 if( new_au_next_sec )
447 ++syncwords;
448 bufmodel.Queued( bytes_muxed, decode_time);
449 au_unsent -= bytes_muxed;
450 new_au_next_sec = false;
451 }
452 else // if (au_unsent == bytes_muxed)
453 {
454 bufmodel.Queued(bytes_muxed, decode_time);
455 if( new_au_next_sec )
456 ++syncwords;
457 new_au_next_sec = NextAU();
458 }
459 completion:
460 // Generate the AC3 header...
461 // Note the index counts from the low byte of the offset so
462 // the smallest value is 1!
463 dst[0] = AC3_SUB_STR_0 + stream_num;
464 dst[1] = syncwords;
465 dst[2] = (first_header+1)>>8;
466 dst[3] = (first_header+1)&0xff;
467 return bytes_read+4;
468 }
469
470
471
472 /*
473 * Local variables:
474 * c-file-style: "stroustrup"
475 * tab-width: 4
476 * indent-tabs-mode: nil
477 * End:
478 */
479