1 /*
2  *  lpcmstrm_in.c: LPCM Audio strem class members handling scanning and
3  *  buffering raw input stream.
4  *
5  * Takes a *RAW* LPCM stream as input.
6  * This is *signed* linear 16, 20, or 24-bit sample PCM.
7  * Samples are stored msb first.
8  * How  20-bit samples are allocated to bytes? I just don't know, but
9  * believe 4 bits are appended after the lsb (samples are msb-byte aligned).
10  *
11  *  Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
12  *  Copyright (C) 2000,2001 Brent Byeler for original header-structure
13  *                          parsing code.
14  *
15  *
16  *  This program is free software; you can redistribute it and/or
17  *  modify it under the terms of version 2 of the GNU General Public License
18  *  as published by the Free Software Foundation.
19  *
20  *  This program is distributed in the hope that it will be useful,
21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *  GNU General Public License for more details.
24  *
25  *  You should have received a copy of the GNU General Public License
26  *  along with this program; if not, write to the Free Software
27  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29 
30 #include <config.h>
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "audiostrm.hpp"
36 #include "interact.hpp"
37 #include "multiplexor.hpp"
38 
39 
40 const unsigned int LPCMStream::default_buffer_size = 58*1024;
41 const unsigned int LPCMStream::ticks_per_frame_90kHz = 150;
42 
43 
LPCMStream(IBitStream & ibs,LpcmParams * parms,Multiplexor & into)44 LPCMStream::LPCMStream(IBitStream &ibs, LpcmParams *parms, Multiplexor &into) :
45 	AudioStream( ibs, into ),
46     parms(parms)
47 {
48 	num_frames = 0;
49 }
50 
51 
52 
53 
Probe(IBitStream & bs)54 bool LPCMStream::Probe(IBitStream &bs )
55 {
56     const char *last_dot = strrchr( bs.StreamName(), '.' );
57     return
58         last_dot != NULL
59         && strcmp( last_dot+1, "lpcm") == 0;
60 
61 }
62 
63 
64 /*************************************************************************
65  *
66  * Reads initial stream parameters and displays feedback banner to users
67  *
68  *************************************************************************/
69 
70 
Init(const int _stream_num)71 void LPCMStream::Init ( const int _stream_num)
72 
73 {
74     stream_num = _stream_num;
75     header_skip = 0;
76 	MuxStream::Init( PRIVATE_STR_1,
77 					 1,  // Buffer scale
78 					 default_buffer_size,
79 					 false,
80 					 muxinto.buffers_in_audio,
81 					 muxinto.always_buffers_in_audio
82 		);
83 
84     // This seems to be necessary not only for some software players but
85     // for some standalone players too.   Yuck... shades of the VCD audio
86     // sectors.
87     min_pes_header_len = 10;
88     mjpeg_info ("Scanning for header info: LPCM Audio stream %02x (%s)",
89                 stream_num,
90                 bs.StreamName()
91                 );
92 
93 
94 	AU_start = bs.bitcount();
95 
96     // This is a dummy debug version that simply assumes 48kHz
97     // two channel 16 bit sample LPCM
98 
99     samples_per_second = parms->SamplesPerSec();
100     channels = parms->Channels();
101     bits_per_sample = parms->BitsPerSample();
102     bytes_per_frame =
103         samples_per_second * channels * bits_per_sample / 8
104         * ticks_per_frame_90kHz
105         / 90000;
106     frame_index = 0;
107     dynamic_range_code = 0x80;
108 
109     /* Presentation/decoding time-stamping  */
110     access_unit.start = AU_start;
111     access_unit.length = bytes_per_frame;
112     access_unit.PTS = static_cast<clockticks>(decoding_order) *
113         (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz);
114     access_unit.DTS = access_unit.PTS;
115     access_unit.dorder = decoding_order;
116     decoding_order++;
117     aunits.Append( access_unit );
118 
119 	OutputHdrInfo();
120 }
121 
NominalBitRate()122 unsigned int LPCMStream::NominalBitRate()
123 {
124 	return samples_per_second * channels * bits_per_sample;
125 }
126 
127 
128 
FillAUbuffer(unsigned int frames_to_buffer)129 void LPCMStream::FillAUbuffer(unsigned int frames_to_buffer )
130 {
131 	last_buffered_AU += frames_to_buffer;
132 	mjpeg_debug( "Scanning %d MPEG LPCM audio frames to frame %d",
133 				 frames_to_buffer, last_buffered_AU );
134 
135 	while ( !bs.eos()
136             && decoding_order < last_buffered_AU
137             && !muxinto.AfterMaxPTS(access_unit.PTS) )
138 	{
139 		int skip=access_unit.length;
140         bs.SeekFwdBits( skip );
141 		prev_offset = AU_start;
142 		AU_start = bs.bitcount();
143         if( AU_start - prev_offset != access_unit.length*8 )
144         {
145             mjpeg_warn("Discarding incomplete final frame LPCM  stream %d",
146                        stream_num);
147             aunits.DropLast();
148             --decoding_order;
149             break;
150         }
151 
152         // Here we would check for header data but LPCM has no headers...
153         if( bs.eos()   )
154             break;
155 
156 		access_unit.start = AU_start;
157 		access_unit.length = bytes_per_frame;
158 		access_unit.PTS = static_cast<clockticks>(decoding_order) *
159             (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz);
160 		access_unit.DTS = access_unit.PTS;
161 		access_unit.dorder = decoding_order;
162 		decoding_order++;
163 		aunits.Append( access_unit );
164 		num_frames++;
165 
166 		num_syncword++;
167 
168 		if (num_syncword >= old_frames+10 )
169 		{
170 			mjpeg_debug ("Got %d frame headers.", num_syncword);
171 			old_frames=num_syncword;
172 		}
173         mjpeg_debug( "Got frame %d\n", decoding_order );
174 
175     }
176 	last_buffered_AU = decoding_order;
177 	eoscan =  bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);
178 }
179 
180 
181 
Close()182 void LPCMStream::Close()
183 {
184     stream_length = AU_start / 8;
185 	mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id);
186     mjpeg_info ("Audio stream length %lld bytes.", stream_length);
187     mjpeg_info   ("Frames         : %8u ",  num_frames);
188 }
189 
190 /*************************************************************************
191 	OutputAudioInfo
192 	gibt gesammelte Informationen zu den Audio Access Units aus.
193 
194 	Prints information on audio access units
195 *************************************************************************/
196 
OutputHdrInfo()197 void LPCMStream::OutputHdrInfo ()
198 {
199 	mjpeg_info("LPCM AUDIO STREAM:");
200 
201     mjpeg_info ("Bit rate       : %8u bytes/sec (%u) bit/sec)",
202                 NominalBitRate()/8, NominalBitRate() );
203     mjpeg_info ("Channels       :     %d", channels);
204     mjpeg_info ("Bits per sample:     %d", bits_per_sample );
205     mjpeg_info ("Frequency      :     %d Hz", samples_per_second );
206 
207 }
208 
209 
210 unsigned int
ReadPacketPayload(uint8_t * dst,unsigned int to_read)211 LPCMStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read)
212 {
213     unsigned int header_size = LPCMStream::StreamHeaderSize();
214     bitcount_t read_start = bs.GetBytePos();
215     unsigned int bytes_read = bs.GetBytes( dst+header_size,
216                                            to_read-header_size );
217     bs.Flush( read_start );
218 
219 	clockticks   decode_time;
220     bool starting_frame_found = false;
221     uint8_t starting_frame_index = 0;
222 
223     int starting_frame_offset =
224         (new_au_next_sec || au_unsent > bytes_read )
225         ? 0
226         : au_unsent;
227 
228     unsigned int frames = 0;
229     unsigned int bytes_muxed = bytes_read;
230 
231 	if (bytes_muxed == 0 || MuxCompleted() )
232     {
233 		goto completion;
234     }
235 
236 
237 	/* Work through what's left of the current frames and the
238 	   following frames's updating the info until we reach a point where
239 	   an frame had to be split between packets.
240 
241 	   The DTS/PTS field for the packet in this case would have been
242 	   given the that for the first AU to start in the packet.
243 
244 	*/
245 
246 	decode_time = RequiredDTS();
247 	while (au_unsent < bytes_muxed)
248 	{
249         assert( bytes_muxed > 1 );
250 		bufmodel.Queued(au_unsent, decode_time);
251 		bytes_muxed -= au_unsent;
252         if( new_au_next_sec )
253         {
254             ++frames;
255             if( ! starting_frame_found )
256             {
257                 starting_frame_index = static_cast<uint8_t>(au->dorder % 20);
258                 starting_frame_found = true;
259             }
260         }
261 		if( !NextAU() )
262         {
263             goto completion;
264         }
265 		new_au_next_sec = true;
266 		decode_time = RequiredDTS();
267 	};
268 
269 	// We've now reached a point where the current AU overran or
270 	// fitted exactly.  We need to distinguish the latter case so we
271 	// can record whether the next packet starts with the tail end of
272 	// // an already started frame or a new one. We need this info to
273 	// decide what PTS/DTS info to write at the start of the next
274 	// packet.
275 
276 	if (au_unsent > bytes_muxed)
277 	{
278         if( new_au_next_sec )
279             ++frames;
280 		bufmodel.Queued( bytes_muxed, decode_time);
281 		au_unsent -= bytes_muxed;
282 		new_au_next_sec = false;
283 	}
284 	else //  if (au_unsent == bytes_muxed)
285 	{
286 		bufmodel.Queued(bytes_muxed, decode_time);
287         if( new_au_next_sec )
288             ++frames;
289         new_au_next_sec = NextAU();
290 	}
291 completion:
292     // Generate the LPCM header...
293     // Note the index counts from the low byte of the offset so
294     // the smallest value is 1!
295     dst[0] = LPCM_SUB_STR_0 + stream_num;
296     dst[1] = frames;
297     dst[2] = (starting_frame_offset+4)>>8;
298     dst[3] = (starting_frame_offset+4)&0xff;
299     unsigned int bps_code;
300     switch( bits_per_sample )
301     {
302     case 16 : bps_code = 0; break;
303     case 20 : bps_code = 1; break;
304     case 24 : bps_code = 2; break;
305     default : bps_code = 3; break;
306     }
307     dst[4] = starting_frame_index;
308     unsigned int bsf_code = (samples_per_second == 48000) ? 0 : 1;
309     unsigned int channels_code = channels - 1;
310     dst[5] = (bps_code << 6) | (bsf_code << 4) | channels_code;
311     dst[6] = dynamic_range_code;
312 	return bytes_read+header_size;
313 }
314 
315 
316 
317 /*
318  * Local variables:
319  *  c-file-style: "stroustrup"
320  *  tab-width: 4
321  *  indent-tabs-mode: nil
322  * End:
323  */
324