Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 272 lines (241 sloc) 9.698 kb
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
1 /* $Id: declpcm.c,v 1.8 2005/11/04 14:44:01 titer Exp $
2
3 This file is part of the HandBrake source code.
2151f887 » jbrjake
2008-04-15 Saearch & Replace domain names to move from .m0k.org to handbrake.fr.…
4 Homepage: <http://handbrake.fr/>.
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
5 It may be used under the terms of the GNU General Public License. */
6
65d8c6e6 » prigaux
2007-03-06 Merge the 5.1 branch into the trunk.
7 #include "hb.h"
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
8
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
9 struct hb_work_private_s
10 {
11 hb_job_t *job;
12 uint32_t size; /* frame size in bytes */
13 uint32_t count; /* frame size in samples */
14 uint32_t pos; /* buffer offset for next input data */
15
16 int64_t next_pts; /* pts for next output frame */
17 int64_t sequence;
18
19 /* the following is frame info for the frame we're currently accumulating */
20 uint64_t duration; /* frame duratin (in 90KHz ticks) */
21 uint32_t offset; /* where in buf frame starts */
22 uint32_t samplerate; /* sample rate in bits/sec */
23 uint8_t nchannels;
24 uint8_t sample_size; /* bits per sample */
25
26 uint8_t frame[HB_DVD_READ_BUFFER_SIZE*2];
27 };
28
29 static hb_buffer_t * Decode( hb_work_object_t * w );
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
30 static int declpcmInit( hb_work_object_t *, hb_job_t * );
31 static int declpcmWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
32 static void declpcmClose( hb_work_object_t * );
33 static int declpcmBSInfo( hb_work_object_t *, const hb_buffer_t *,
34 hb_work_info_t * );
bc3615d5 » titer
2006-03-16 Structural changes, in order to eventually be able to compile HB
35
36 hb_work_object_t hb_declpcm =
73404b3a » saintdev
2008-02-21 Formatting: Remove a lot of trailing whitespace.
37 {
bc3615d5 » titer
2006-03-16 Structural changes, in order to eventually be able to compile HB
38 WORK_DECLPCM,
39 "LPCM decoder",
40 declpcmInit,
41 declpcmWork,
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
42 declpcmClose,
43 0,
44 declpcmBSInfo
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
45 };
46
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
47 static const int hdr2samplerate[] = { 48000, 96000, 44100, 32000 };
48 static const int hdr2samplesize[] = { 16, 20, 24, 16 };
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
49 static const int hdr2layout[] = {
50 HB_INPUT_CH_LAYOUT_MONO, HB_INPUT_CH_LAYOUT_STEREO,
51 HB_INPUT_CH_LAYOUT_2F1R, HB_INPUT_CH_LAYOUT_2F2R,
52 HB_INPUT_CH_LAYOUT_3F2R, HB_INPUT_CH_LAYOUT_4F2R,
53 HB_INPUT_CH_LAYOUT_STEREO, HB_INPUT_CH_LAYOUT_STEREO,
54 };
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
55
56 static void lpcmInfo( hb_work_object_t *w, hb_buffer_t *in )
57 {
58 hb_work_private_t * pv = w->private_data;
59
60 /*
61 * LPCM packets have a 7 byte header (the substream id is stripped off
62 * before we get here so it's numbered -1 below)::
63 * byte -1 Substream id
64 * byte 0 Number of frames that begin in this packet
65 * (last frame may finish in next packet)
66 * byte 1,2 offset to first frame that begins in this packet (not including hdr)
67 * byte 3:
68 * bits 0-4 continuity counter (increments modulo 20)
69 * bit 5 reserved
70 * bit 6 audio mute on/off
71 * bit 7 audio emphasis on/off
72 * byte 4:
73 * bits 0-2 #channels - 1 (e.g., stereo = 1)
74 * bit 3 reserved
75 * bits 4-5 sample rate (0=48K,1=96K,2=44.1K,3=32K)
76 * bits 6-7 bits per sample (0=16 bit, 1=20 bit, 2=24 bit)
77 * byte 5 Dynamic range control (0x80 = off)
78 *
79 * The audio is viewed as "frames" of 150 90KHz ticks each (80 samples @ 48KHz).
80 * The frames are laid down continuously without regard to MPEG packet
81 * boundaries. E.g., for 48KHz stereo, the first packet will contain 6
82 * frames plus the start of the 7th, the second packet will contain the
83 * end of the 7th, 8-13 & the start of 14, etc. The frame structure is
84 * important because the PTS on the packet gives the time of the first
85 * frame that starts in the packet *NOT* the time of the first sample
86 * in the packet. Also samples get split across packet boundaries
87 * so we can't assume that we can consume all the data in one packet
88 * on every call to the work routine.
89 */
90 pv->offset = ( ( in->data[1] << 8 ) | in->data[2] ) + 2;
91 if ( pv->offset >= HB_DVD_READ_BUFFER_SIZE )
92 {
93 hb_log( "declpcm: illegal frame offset %d", pv->offset );
94 pv->offset = 2; /*XXX*/
95 }
96 pv->samplerate = hdr2samplerate[ ( in->data[4] >> 4 ) & 0x3 ];
97 pv->nchannels = ( in->data[4] & 7 ) + 1;
98 pv->sample_size = hdr2samplesize[in->data[4] >> 6];
99
100 /*
101 * PCM frames have a constant duration (150 90KHz ticks).
102 * We need to convert that to the amount of data expected. It's the
103 * duration divided by the sample rate (to get #samples) times the number
104 * of channels times the bits per sample divided by 8 to get bytes.
105 * (we have to compute in bits because 20 bit samples are not an integral
106 * number of bytes). We do all the multiplies first then the divides to
107 * avoid truncation errors.
108 */
109 pv->duration = in->data[0] * 150;
110 pv->count = ( pv->duration * pv->nchannels * pv->samplerate ) / 90000;
111 pv->size = ( pv->count * pv->sample_size ) / 8;
112
113 pv->next_pts = in->start;
114 }
115
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
116 static int declpcmInit( hb_work_object_t * w, hb_job_t * job )
bc3615d5 » titer
2006-03-16 Structural changes, in order to eventually be able to compile HB
117 {
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
118 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
119 w->private_data = pv;
120 pv->job = job;
bc3615d5 » titer
2006-03-16 Structural changes, in order to eventually be able to compile HB
121 return 0;
122 }
123
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
124 /*
125 * Convert DVD encapsulated LPCM to floating point PCM audio buffers.
126 * The amount of audio in a PCM frame is always <= the amount that will fit
127 * in a DVD block (2048 bytes) but the standard doesn't require that the audio
128 * frames line up with the DVD frames. Since audio frame boundaries are unrelated
129 * to DVD PES boundaries, this routine has to reconstruct then extract the audio
130 * frames. Because of the arbitrary alignment, it can output zero, one or two buf's.
131 */
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
132 static int declpcmWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
133 hb_buffer_t ** buf_out )
134 {
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
135 hb_work_private_t * pv = w->private_data;
ed9d3071 » van
2008-07-26 - in encx264, if an video frame is larger than init_delay split it i…
136 hb_buffer_t *in = *buf_in;
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
137 hb_buffer_t *buf = NULL;
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
138
ed9d3071 » van
2008-07-26 - in encx264, if an video frame is larger than init_delay split it i…
139 if ( in->size <= 0 )
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
140 {
ed9d3071 » van
2008-07-26 - in encx264, if an video frame is larger than init_delay split it i…
141 /* EOF on input stream - send it downstream & say that we're done */
142 *buf_out = in;
143 *buf_in = NULL;
144 return HB_WORK_DONE;
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
145 }
146
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
147 pv->sequence = in->sequence;
148
149 /* if we have a frame to finish, add enough data from this buf to finish it */
150 if ( pv->size )
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
151 {
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
152 memcpy( pv->frame + pv->pos, in->data + 6, pv->size - pv->pos );
153 buf = Decode( w );
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
154 }
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
155 *buf_out = buf;
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
156
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
157 /* save the (rest of) data from this buf in our frame buffer */
158 lpcmInfo( w, in );
159 int off = pv->offset;
160 int amt = in->size - off;
161 pv->pos = amt;
162 memcpy( pv->frame, in->data + off, amt );
163 if ( amt >= pv->size )
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
164 {
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
165 if ( buf )
166 {
167 buf->next = Decode( w );
168 }
169 else
170 {
171 *buf_out = Decode( w );
172 }
173 pv->size = 0;
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
174 }
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
175 return HB_WORK_OK;
176 }
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
177
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
178 static hb_buffer_t *Decode( hb_work_object_t *w )
179 {
180 hb_work_private_t *pv = w->private_data;
ee517f19 » jstebbins
2010-10-19 fix zero duration lpcm frame handling
181 hb_buffer_t *out;
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
182
ee517f19 » jstebbins
2010-10-19 fix zero duration lpcm frame handling
183 if (pv->count == 0)
184 return NULL;
185
186 out = hb_buffer_init( pv->count * sizeof( float ) );
187
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
188 out->start = pv->next_pts;
189 pv->next_pts += pv->duration;
190 out->stop = pv->next_pts;
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
191
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
192 uint8_t *frm = pv->frame;
193 float *odat = (float *)out->data;
194 int count = pv->count;
195
196 switch( pv->sample_size )
197 {
198 case 16: // 2 byte, big endian, signed (the right shift sign extends)
199 while ( --count >= 0 )
200 {
201 *odat++ = ( (int)( frm[0] << 24 ) >> 16 ) | frm[1];
202 frm += 2;
203 }
204 break;
205 case 20:
206 // 20 bit big endian signed (5 bytes for 2 samples = 2.5 bytes/sample
207 // so we do two samples per iteration).
208 count /= 2;
209 while ( --count >= 0 )
210 {
211 *odat++ = (float)( ( (int)( frm[0] << 24 ) >> 12 ) |
212 ( frm[1] << 4 ) | ( frm[2] >> 4 ) ) / 16.;
213 *odat++ = (float)( ( (int)( frm[2] << 28 ) >> 16 ) |
214 ( frm[3] << 8 ) | frm[4] ) / 16.;
215 frm += 5;
216 }
217 break;
218 case 24:
219 // This format is bizarre. It's 24 bit samples but some confused
220 // individual apparently thought they would be easier to interpret
221 // as 16 bits if they were scrambled in the following way:
222 // Things are stored in 4 sample (12 byte) chunks. Each chunk has
223 // 4 samples containing the two top bytes of the actual samples in
224 // 16 bit big-endian order followed by the four least significant bytes
225 // of each sample.
226 count /= 4; // the loop has to work in 4 sample chunks
227 while ( --count >= 0 )
228 {
229 *odat++ = (float)( ( (int)( frm[0] << 24 ) >> 8 ) |
230 ( frm[1] << 8 ) | frm[8] ) / 256.;
231 *odat++ = (float)( ( (int)( frm[2] << 24 ) >> 8 ) |
232 ( frm[3] << 8 ) | frm[9] ) / 256.;
233 *odat++ = (float)( ( (int)( frm[4] << 24 ) >> 8 ) |
234 ( frm[5] << 8 ) | frm[10] ) / 256.;
235 *odat++ = (float)( ( (int)( frm[6] << 24 ) >> 8 ) |
236 ( frm[7] << 8 ) | frm[11] ) / 256.;
237 frm += 12;
238 }
239 break;
240 }
241 return out;
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
242 }
243
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
244 static void declpcmClose( hb_work_object_t * w )
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
245 {
66ecdb71 » van
2008-04-02 scan and pcm audio fixes.
246 if ( w->private_data )
247 {
248 free( w->private_data );
249 w->private_data = 0;
250 }
0ac3b7e3 » root
2006-01-14 HandBrake 0.7.0
251 }
983ea454 » van
2008-05-31 - support blu-ray, avchd & dvb x264
252
253 static int declpcmBSInfo( hb_work_object_t *w, const hb_buffer_t *b,
254 hb_work_info_t *info )
255 {
256 int nchannels = ( b->data[4] & 7 ) + 1;
257 int sample_size = hdr2samplesize[b->data[4] >> 6];
258
259 int rate = hdr2samplerate[ ( b->data[4] >> 4 ) & 0x3 ];
260 int bitrate = rate * sample_size * nchannels;
261
262 memset( info, 0, sizeof(*info) );
263
264 info->name = "LPCM";
265 info->rate = rate;
266 info->rate_base = 1;
267 info->bitrate = bitrate;
268 info->flags = ( b->data[3] << 16 ) | ( b->data[4] << 8 ) | b->data[5];
269 info->channel_layout = hdr2layout[nchannels - 1];
270
271 return 1;
272 }
Something went wrong with that request. Please try again.