1 /*
2 * dtsstrm_in.c: dts Audio stream class members handling scanning and
3 * buffering raw input stream.
4 *
5 * Copyright (C) 2003 Markus Plail <plail@web.de>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public License
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include <config.h>
22 #include <math.h>
23 #include <stdlib.h>
24
25 #include "audiostrm.hpp"
26 #include "interact.hpp"
27 #include "multiplexor.hpp"
28
29 #define DTS_SYNCWORD 0x7ffe8001
30 #define DTS_PACKET_SAMPLES 1536
31
32 const unsigned int DTSStream::default_buffer_size = 16*1024;
33
34 /// table for the available dts bitrates
35 static const unsigned int dts_bitrate_index[32] =
36 { 32,56,64,96,112,128,192,224,
37 256,320,384,448,512,576,640,768,
38 960,1024,1152,1280,1344,1408,1411,1472,
39 1536,1920,2048,3072,3840,0,0,0
40 };
41
42 /// table for the available dts frequencies
43 static const unsigned int dts_frequency[17] =
44 { 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0 };
45
46 /// samples per frame
47 static const unsigned int dts_packet_samples[4] =
48 { 256, 512, 1024, 2048 };
49
50
DTSStream(IBitStream & ibs,Multiplexor & into)51 DTSStream::DTSStream(IBitStream &ibs, Multiplexor &into) :
52 AudioStream( ibs, into )
53 {
54 num_frames = 0;
55 }
56
Probe(IBitStream & bs)57 bool DTSStream::Probe(IBitStream &bs )
58 {
59 return bs.GetBits(32) == DTS_SYNCWORD;
60 }
61
62 #ifdef DEBUG_DTS
63
binString(int value,int length)64 static char *binString(int value, int length)
65 {
66 char *bin = (char *) malloc((length + 1) * sizeof(char));
67 int index;
68 int dummy = 1 << (length - 1);
69
70 for(index = 0; index < length; index++)
71 {
72 if(value & dummy)
73 bin[index] = '1';
74 else
75 bin[index] = '0';
76
77 dummy >>= 1;
78 }
79 bin[index] = '\0';
80
81 return(bin);
82 }
83
84
85 /*************************************************************************
86 *
87 * Reads initial stream parameters and displays feedback banner to users
88 * @param stream_num dts substream ID
89 *************************************************************************/
90
91
DisplayDtsHeaderInfo()92 void DTSStream::DisplayDtsHeaderInfo()
93 {
94 /* Some stuff to generate frame-header information */
95 printf( "normal/termination? = %i\n", bs.GetBits(1) );
96 printf( "deficit sample count = %i\n", bs.GetBits(5) );
97 int crc = bs.GetBits(1);
98 printf( "CRC present? = %i\n", crc );
99 printf( "PCM samples = %i\n", bs.GetBits(7) );
100 printf( "frame byte size = %i\n", bs.GetBits(14) );
101 int acmode = bs.GetBits(6);
102 printf( "audio channel = %s\n", binString(acmode, 6) );
103 printf( "audio sampling freqency = %s\n", binString(bs.GetBits(4), 4) );
104 printf( "bit rate = %s\n", binString(bs.GetBits(5), 5) );
105 printf( "downmix enabled = %i\n", bs.GetBits(1) );
106 printf( "dynamic range flag = %i\n", bs.GetBits(1) );
107 printf( "time stamp = %i\n", bs.GetBits(1) );
108 printf( "auxiliary data = %i\n", bs.GetBits(1) );
109 printf( "HDCD = %i\n", bs.GetBits(1) );
110 printf( "extended coding flag = %i\n", bs.GetBits(1) );
111 printf( "audio sync word insert = %i\n", bs.GetBits(1) );
112 printf( "low frequency effects = %i\n", bs.GetBits(1) );
113 printf( "predictor history = %i\n", bs.GetBits(1) );
114 if (crc) printf( "CRC = %i\n", bs.GetBits(16) );
115 printf( "multirate interpolator = %i\n", bs.GetBits(1) );
116 printf( "encoder software revision = %i\n", bs.GetBits(4) );
117 printf( "copy history = %i\n", bs.GetBits(2) );
118 printf( "PCM resolution = %s\n", binString(bs.GetBits(3), 3) );
119 printf( "front sums difference flags = %i\n", bs.GetBits(1) );
120 printf( "surround sums difference flags = %i\n", bs.GetBits(1) );
121 printf( "dialog normalization parameter = %i\n", bs.GetBits(4) );
122 }
123 #endif
Init(const int _stream_num)124 void DTSStream::Init ( const int _stream_num)
125
126 {
127 stream_num = _stream_num;
128 MuxStream::Init( PRIVATE_STR_1,
129 1, // Buffer scale
130 default_buffer_size,
131 false,
132 muxinto.buffers_in_audio,
133 muxinto.always_buffers_in_audio
134 );
135 mjpeg_info ("Scanning for header info: dts Audio stream %02x (%s)",
136 stream_num,
137 bs.StreamName()
138 );
139
140 AU_start = bs.bitcount();
141 if (bs.GetBits(32)==DTS_SYNCWORD)
142 {
143 num_syncword++;
144 bs.GetBits(6); // additional sync
145 bs.GetBits(1); // CRC
146 bs.GetBits(7); // pcm samples
147 framesize = bs.GetBits(14) + 1; // frame size
148
149 bs.GetBits(6); // audio channels
150 frequency = bs.GetBits(4); // sample rate code
151 bit_rate = dts_bitrate_index[bs.GetBits(5)];
152 bs.GetBits(5); // misc.
153
154 header_skip = 10; // Initially skipped past 10 bytes of header
155
156 num_frames++;
157 access_unit.start = AU_start;
158 access_unit.length = framesize;
159 mjpeg_info( "dts frame size = %d", framesize );
160 samples_per_second = dts_frequency[frequency];
161
162 /* Presentation time-stamping */
163 access_unit.PTS = static_cast<clockticks>(decoding_order) *
164 static_cast<clockticks>(DTS_PACKET_SAMPLES) *
165 static_cast<clockticks>(CLOCKS) / samples_per_second;
166 access_unit.DTS = access_unit.PTS;
167 access_unit.dorder = decoding_order;
168 ++decoding_order;
169 aunits.Append( access_unit );
170
171 } else
172 {
173 mjpeg_error ( "Invalid dts Audio stream header.");
174 exit (1);
175 }
176 OutputHdrInfo();
177 }
178
179 /// @returns the current bitrate
NominalBitRate()180 unsigned int DTSStream::NominalBitRate()
181 {
182 return bit_rate*1024;
183 }
184
185 /// Prefills the internal buffer for output multiplexing.
186 /// @param frames_to_buffer the number of audio frames to read ahead
FillAUbuffer(unsigned int frames_to_buffer)187 void DTSStream::FillAUbuffer(unsigned int frames_to_buffer )
188 {
189 unsigned int packet_samples;
190
191 last_buffered_AU += frames_to_buffer;
192 mjpeg_debug( "Scanning %d dts audio frames to frame %d",
193 frames_to_buffer, last_buffered_AU );
194
195 while( !bs.eos() && decoding_order < last_buffered_AU
196 && !muxinto.AfterMaxPTS(access_unit.PTS) )
197 {
198 int skip = access_unit.length - header_skip;
199 bs.SeekFwdBits(skip);
200 prev_offset = AU_start;
201 AU_start = bs.bitcount();
202
203 if( AU_start - prev_offset != access_unit.length*8 )
204 {
205 mjpeg_warn( "Discarding incomplete final frame dts stream %d!",
206 stream_num);
207 aunits.DropLast();
208 decoding_order--;
209 break;
210 }
211
212 /* Check if we have reached the end or have another catenated
213 stream to process before finishing ... */
214 if ( (syncword = bs.GetBits(32))!=DTS_SYNCWORD )
215 {
216 if( !bs.eos() )
217 {
218 mjpeg_error_exit1( "Can't find next dts frame: @ %lld we have %04x - broken bit-stream?", AU_start/8, syncword );
219 }
220 break;
221 }
222
223 bs.GetBits(6); // additional sync
224 bs.GetBits(1); // CRC
225 packet_samples = (bs.GetBits(7) + 1) * 32; // pcm samples
226 framesize = bs.GetBits(14) + 1; // frame size
227
228 bs.GetBits(6); // audio channels
229 bs.GetBits(4); // sample rate code
230 bs.GetBits(5); // bitrate
231 bs.GetBits(5); // misc.
232
233 access_unit.start = AU_start;
234 access_unit.length = framesize;
235 access_unit.PTS = static_cast<clockticks>(decoding_order) *
236 static_cast<clockticks>(packet_samples) *
237 static_cast<clockticks>(CLOCKS) / samples_per_second;
238 access_unit.DTS = access_unit.PTS;
239 access_unit.dorder = decoding_order;
240 decoding_order++;
241 aunits.Append( access_unit );
242 num_frames++;
243
244 num_syncword++;
245
246 if (num_syncword >= old_frames+10 )
247 {
248 mjpeg_debug ("Got %d frame headers.", num_syncword);
249 old_frames=num_syncword;
250 }
251
252 }
253 last_buffered_AU = decoding_order;
254 eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);
255 }
256
257
258 /// Closes the dts stream and prints some statistics.
Close()259 void DTSStream::Close()
260 {
261 stream_length = AU_start >> 3;
262 mjpeg_info ("DTS STATISTICS: %02x", stream_id);
263 mjpeg_info ("Audio stream length %lld bytes.", stream_length);
264 mjpeg_info ("Frames : %8u", num_frames);
265 }
266
267 /*************************************************************************
268 OutputAudioInfo
269 gibt gesammelte Informationen zu den Audio Access Units aus.
270
271 Prints information on audio access units
272 *************************************************************************/
273
OutputHdrInfo()274 void DTSStream::OutputHdrInfo ()
275 {
276 mjpeg_info("dts AUDIO STREAM:");
277
278 mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)",
279 bit_rate*128, bit_rate);
280
281 if (frequency == 3)
282 mjpeg_info ("Frequency : reserved");
283 else
284 mjpeg_info ("Frequency : %d Hz",
285 dts_frequency[frequency]);
286
287 }
288
289 /**
290 Reads the bytes neccessary to complete the current packet payload.
291 @param to_read number of bytes to read
292 @param dst byte buffer pointer to read to
293 @returns the number of bytes read
294 */
295 unsigned int
ReadPacketPayload(uint8_t * dst,unsigned int to_read)296 DTSStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read)
297 {
298 clockticks decode_time;
299 // TODO: BUG BUG BUG: if there is a change in format in the stream
300 // this framesize will be invalid! It only *looks* like it works...
301 // really each AU should store its own framesize...
302 unsigned int frames = to_read / framesize;
303 bitcount_t read_start = bs.GetBytePos();
304 unsigned int bytes_read = bs.GetBytes( dst + 4, framesize * frames);
305 unsigned int bytes_muxed = bytes_read;
306
307 assert( bytes_read > 0 ); // Should never try to read nothing
308
309 bs.Flush( read_start );
310
311 unsigned int first_header =
312 (new_au_next_sec || au_unsent > bytes_read )
313 ? 0
314 : au_unsent;
315
316 // BUG BUG BUG: how do we set the 1st header pointer if we have
317 // the *middle* part of a large frame?
318 assert( first_header+2 <= to_read );
319
320 unsigned int syncwords = 0;
321
322 if (bytes_muxed == 0 || MuxCompleted() )
323 {
324 goto completion;
325 }
326
327
328 /* Work through what's left of the current AU and the following AU's
329 updating the info until we reach a point where an AU had to be
330 split between packets.
331 NOTE: It *is* possible for this loop to iterate.
332
333 The DTS/PTS field for the packet in this case would have been
334 given the that for the first AU to start in the packet.
335
336 */
337
338 decode_time = RequiredDTS();
339 while (au_unsent < bytes_muxed)
340 {
341 // BUG BUG BUG: if we ever had odd payload / packet size we might
342 // split a DTS frame in the middle of the syncword!
343 assert( bytes_muxed > 1 );
344 bufmodel.Queued(au_unsent, decode_time);
345 bytes_muxed -= au_unsent;
346 if( new_au_next_sec )
347 ++syncwords;
348 if( !NextAU() )
349 {
350 goto completion;
351 }
352 new_au_next_sec = true;
353 decode_time = RequiredDTS();
354 };
355
356 // We've now reached a point where the current AU overran or
357 // fitted exactly. We need to distinguish the latter case
358 // so we can record whether the next packet starts with an
359 // existing AU or not - info we need to decide what PTS/DTS
360 // info to write at the start of the next packet.
361
362 if (au_unsent > bytes_muxed)
363 {
364 if( new_au_next_sec )
365 ++syncwords;
366 bufmodel.Queued( bytes_muxed, decode_time);
367 au_unsent -= bytes_muxed;
368 new_au_next_sec = false;
369 }
370 else // if (au_unsent == bytes_muxed)
371 {
372 bufmodel.Queued(bytes_muxed, decode_time);
373 if( new_au_next_sec )
374 ++syncwords;
375 new_au_next_sec = NextAU();
376 }
377
378 completion:
379 // Generate the dts header...
380 // Note the index counts from the low byte of the offset so
381 // the smallest value is 1!
382 dst[0] = DTS_SUB_STR_0 + stream_num;
383 dst[1] = frames;
384 dst[2] = (first_header+1)>>8;
385 dst[3] = (first_header+1)&0xff;
386
387 return bytes_read + 4;
388 }
389
390
391
392 /*
393 * Local variables:
394 * c-file-style: "stroustrup"
395 * tab-width: 4
396 * indent-tabs-mode: nil
397 * End:
398 */
399