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