Source code: org/esau/ptarmigan/impl/MPEGFrameHeader.java
1 /* $Header: /cvsroot/ptarmigan/ptarmigan/src/java/org/esau/ptarmigan/impl/MPEGFrameHeader.java,v 1.2 2002/10/02 05:27:03 reedesau Exp $ */
2
3 package org.esau.ptarmigan.impl;
4
5 import org.apache.commons.logging.Log;
6 import org.apache.commons.logging.LogFactory;
7
8 /**
9 * MPEG Frame Header
10 * <p>
11 * Parse and validate a 4-byte MPEG Header
12 * <p>
13 * @author Reed Esau
14 * @version $Revision: 1.2 $ $Date: 2002/10/02 05:27:03 $
15 */
16 public final class MPEGFrameHeader {
17
18 /** ctor */
19 public MPEGFrameHeader() {
20 resetData();
21 }
22
23 /** copy ctor */
24 public MPEGFrameHeader(MPEGFrameHeader other) {
25 m_audio_ver = other.m_audio_ver ;
26 m_layer_code = other.m_layer_code ;
27 m_protection = other.m_protection ;
28 m_bitrate_index = other.m_bitrate_index;
29 m_sample_index = other.m_sample_index ;
30 m_padding = other.m_padding ;
31 m_private_bit = other.m_private_bit ;
32 m_channel_mode = other.m_channel_mode ;
33 m_mode_ext = other.m_mode_ext ;
34 m_copyright = other.m_copyright ;
35 m_original = other.m_original ;
36 m_emphasis = other.m_emphasis ;
37
38 m_bit_rate = other.m_bit_rate ;
39 m_sample_rate = other.m_sample_rate ;
40 m_frame_length = other.m_frame_length ;
41 }
42
43 /**
44 * Try to identify a frame header in the specified buffer at the
45 * specified offset.
46 *
47 * Note that it's not definitive. You have to look for repeating MPEG
48 * frames and check CRCs to make sure.
49 *
50 * AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
51 *
52 * @return false if not a valid frame header; true if it may be (but not definitive)
53 */
54 public boolean initHeader(byte[] buf, int offset) {
55
56 resetData();
57
58 int dw = ((buf[offset+0] & 0xFF) << 24) +
59 ((buf[offset+1] & 0xFF) << 16) +
60 ((buf[offset+2] & 0xFF) << 8) +
61 (buf[offset+3] & 0xFF);
62
63 if ((dw & FRAME_SYNC_MASK) != FRAME_SYNC_MASK)
64 return false;
65
66 m_audio_ver = (dw & AUDIO_VER_MASK) >> AUDIO_VER_SHIFT;
67 // 00 - MPEG Version 2.5 (may not be official)
68 // 01 - reserved
69 // 10 - MPEG Version 2 (ISO/IEC 13818-3)
70 // 11 - MPEG Version 1 (ISO/IEC 11172-3)
71
72 m_layer_code = (dw & LAYER_MASK) >> LAYER_SHIFT;
73 // 00 - reserved
74 // 01 - Layer III
75 // 10 - Layer II
76 // 11 - Layer I
77
78 m_protection = ((dw & PROTECTION_MASK) == PROTECTION_MASK);
79 // 0 - Protected by CRC (16bit crc follows header)
80 // 1 - Not protected
81
82 m_bitrate_index = (dw & BITRATE_MASK) >> BITRATE_SHIFT;
83 // used in a table lookup
84
85 m_sample_index = (dw & SAMPLE_MASK) >> SAMPLE_SHIFT;
86 // used in a table lookup
87
88 m_padding = ((dw & PADDING_MASK) == PADDING_MASK);
89 // 0 - frame is not padded
90 // 1 - frame is padded with one extra slot
91 // Padding is used to fit the bit rates exactly. For an example: 128k
92 // 44.1kHz layer II uses a lot of 418 bytes and some of 417 bytes long frames
93 // to get the exact 128k bitrate. For Layer I slot is 32 bits long, for
94 // Layer II and Layer III slot is 8 bits long.
95
96 m_private_bit = ((dw & PRIVATE_MASK) == PRIVATE_MASK);
97 // used by application
98
99 m_channel_mode = (dw & CHANNEL_MASK) >> CHANNEL_SHIFT;
100 // 00 - Stereo
101 // 01 - Joint stereo (Stereo)
102 // 10 - Dual channel (Stereo)
103 // 11 - Single channel (Mono)
104
105 m_mode_ext = (dw & MODE_EXT_MASK) >> MODE_EXT_SHIFT;
106 // LAYER I AND II LAYER III
107 // INTENSITY MS
108 // VALUE STEREO STEREO
109 // 00 bands 4 to 31 off off
110 // 01 bands 8 to 31 on off
111 // 10 bands 12 to 31 off on
112 // 11 bands 16 to 31 on on
113
114 m_copyright = ((dw & COPYRIGHT_MASK) == COPYRIGHT_MASK);
115 // 0 - Audio is not copyrighted
116 // 1 - Audio is copyrighted
117
118 m_original = ((dw & ORIGINAL_MASK) == ORIGINAL_MASK);
119 // 0 - Copy of original media
120 // 1 - Original media
121
122 m_emphasis = (dw & EMPHASIS_MASK); // no shift necessary
123 // 00 - none
124 // 01 - 50/15 ms
125 // 10 - reserved
126 // 11 - CCIT J.17
127
128 return validate();
129 }
130
131
132 //
133 // gettors and settors
134 //
135
136 public String getAudioVersion() {
137 if (0 <= m_audio_ver && m_audio_ver < S_AUDIO_VER.length)
138 return S_AUDIO_VER[m_audio_ver];
139 else
140 return null;
141 }
142 public int getLayer() {
143 if (0 <= m_layer_code && m_layer_code < S_LAYER.length)
144 return S_LAYER[m_layer_code];
145 else
146 return -1;
147 }
148 public boolean getProtection() {
149 return m_protection;
150 }
151 public boolean getPadding() {
152 return m_padding;
153 }
154 public boolean getPrivateBit() {
155 return m_private_bit;
156 }
157 public int getChannelMode() {
158 return m_channel_mode;
159 }
160 public int getModeExt() {
161 return m_mode_ext;
162 }
163
164 public int getChannels() {
165 return m_channel_mode==CHANNEL_SINGLE ? 1 : 2;
166 }
167
168 public String getChannelDesc() {
169 StringBuffer buf = new StringBuffer();
170
171 buf.append(S_CHANNEL_MODE[m_channel_mode]);
172
173 if (m_channel_mode == CHANNEL_JOINT_STEREO) {
174 switch (m_layer_code) {
175 case LAYER_I:
176 case LAYER_II:
177 buf.append("-intensity-").append(S_MODE_EXT_LAYER_I_II[m_mode_ext]);
178 break;
179 case LAYER_III:
180 buf.append(S_MODE_EXT_LAYER_III[m_mode_ext]);
181 break;
182 default:
183 }
184 }
185 return buf.toString();
186 }
187
188 public boolean getCopyright() {
189 return m_copyright;
190 }
191 public boolean getOriginal() {
192 return m_original;
193 }
194 public int getEmphasis() {
195 return m_emphasis;
196 }
197
198 //
199 // calculated fields
200 //
201
202 public int getBitRate() {
203 return m_bit_rate;
204 }
205 public int getSampleRate() {
206 return m_sample_rate;
207 }
208 public int getFrameLength() {
209 return m_frame_length;
210 }
211
212 //
213 // internal
214 //
215
216 /**
217 * A number of tests to validate a single frame. The results are
218 * not definitive.
219 *
220 * For best results, check consecutive frames and the CRC, if present.
221 */
222 boolean validate() {
223
224 if (m_audio_ver == AUDIO_VER_RESERVED) {
225 log.debug("validate: audio version reserved found");
226 return false;
227 }
228
229 if (m_layer_code == LAYER_RESERVED) {
230 log.debug("validate: layer reserved found");
231 return false;
232 }
233
234 if (lookupBitRate() == false) {
235 log.debug("validate: invalid bit rate");
236 return false;
237 }
238
239 //bitrate allowed modes
240 if (m_layer_code == LAYER_II) {
241 switch (m_bit_rate) {
242 case 32 :
243 case 48 :
244 case 56 :
245 case 80 :
246 if (m_channel_mode != CHANNEL_SINGLE) {
247 log.debug("validate: failure (bad channel mode for bitrate)");
248 return false;
249 }
250 break;
251 case 224:
252 case 256:
253 case 320:
254 case 384:
255 if (m_channel_mode != CHANNEL_STEREO
256 && m_channel_mode != CHANNEL_JOINT_STEREO
257 && m_channel_mode != CHANNEL_DUAL) {
258 log.debug("validate: failure (bad channel mode for bitrate)");
259 return false;
260 }
261 break;
262 default:
263 }
264 }
265
266 if (lookupSampleRate() == false) {
267 log.debug("validate: invalid sample rate");
268 return false;
269 }
270
271 if (calculateFrameLength() == false) {
272 log.debug("validate: failure (bad frame length)");
273 return false;
274 }
275
276 return true;
277 }
278
279
280 //
281 // lookups and calculations
282 //
283
284 /** bit rate in bits per second */
285 boolean lookupBitRate() {
286 if (m_bit_rate > 0)
287 return true; // already done
288
289 //if (log.isDebugEnabled())
290 // log.debug("lookupBitRate: m_audio_ver=" + m_audio_ver + " m_layer_code=" + m_layer_code);
291
292 int index = -1;
293
294 switch (m_audio_ver) {
295 case AUDIO_VER_VERSION_1:
296 switch (m_layer_code) {
297 case LAYER_I:
298 index = 0;
299 break;
300 case LAYER_II:
301 index = 1;
302 break;
303 case LAYER_III:
304 index = 2;
305 break;
306 default:
307 }
308 break;
309 case AUDIO_VER_VERSION_2:
310 case AUDIO_VER_VERSION_2_5:
311 switch (m_layer_code) {
312 case LAYER_I:
313 index = 3;
314 break;
315 case LAYER_II:
316 case LAYER_III:
317 index = 4;
318 break;
319 default:
320 }
321 break;
322 }
323
324 //if (log.isDebugEnabled())
325 // log.debug("lookupBitRate: m_bitrate_index=" + m_bitrate_index + " index=" + index);
326
327 int lookup = (index != -1
328 ? BIT_RATES[m_bitrate_index][index]
329 : LOOKUP_FAILURE);
330
331 // store the bitrate in bps, not kbps
332 m_bit_rate = lookup > 0 ? lookup*1000 : BAD; // RESOLVE: should be 1024?
333
334 if (log.isDebugEnabled())
335 log.debug("lookupBitRate: m_bit_rate=" + m_bit_rate);
336
337 return m_bit_rate == FREE || m_bit_rate > 0;
338 }
339
340 /** sample rate */
341 boolean lookupSampleRate() {
342 if (m_sample_rate >= 0)
343 return true; // already done
344
345 //if (log.isDebugEnabled())
346 // log.debug("lookupSampleRate: m_audio_ver=" + m_audio_ver
347 // + " m_sample_index=" + m_sample_index);
348
349 int index = -1;
350
351 switch (m_audio_ver) {
352 case AUDIO_VER_VERSION_1:
353 index = 0;
354 break;
355 case AUDIO_VER_VERSION_2:
356 index = 1;
357 break;
358 case AUDIO_VER_VERSION_2_5:
359 index = 2;
360 break;
361 default:
362 }
363
364 m_sample_rate = (index != -1
365 ? SAMPLE_RATES[m_sample_index][index]
366 : LOOKUP_FAILURE);
367
368 if (log.isDebugEnabled())
369 log.debug("lookupSampleRate: m_sample_rate=" + m_sample_rate);
370
371 return m_sample_rate >= 0;
372 }
373
374 /** frame length in bytes */
375 boolean calculateFrameLength() {
376 if (m_frame_length >= 0)
377 return true;
378
379 if (lookupBitRate() == false)
380 return false;
381 if (lookupSampleRate() == false)
382 return false;
383
384 if (log.isDebugEnabled())
385 log.debug("calculateFrameLength: m_layer_code=" + m_layer_code
386 + " m_bit_rate=" + m_bit_rate
387 + " m_sample_rate=" + m_sample_rate
388 + " m_padding=" + m_padding);
389
390 switch (m_layer_code) {
391 case LAYER_I:
392 m_frame_length = (4 * ( (12 * m_bit_rate / m_sample_rate)
393 + (m_padding ? SLOT_LAYER_I : 0)
394 )
395 );
396 break;
397 case LAYER_II:
398 case LAYER_III:
399 m_frame_length = (144 * m_bit_rate) / m_sample_rate
400 + (m_padding ? SLOT_LAYER_II_III : 0);
401 break;
402 default:
403 return false;
404 }
405
406 if (log.isDebugEnabled())
407 log.debug("calculateFrameLength: m_frame_length=" + m_frame_length);
408
409 return true;
410 }
411
412 //
413 // resetter
414 //
415
416 public void resetData() {
417 m_audio_ver = -1;
418 m_layer_code = -1;
419 m_protection = false;
420 m_bitrate_index = -1;
421 m_sample_index = -1;
422 m_padding = false;
423 m_private_bit = false;
424 m_channel_mode = -1;
425 m_mode_ext = -1;
426 m_copyright = false;
427 m_original = false;
428 m_emphasis = -1;
429
430 m_bit_rate = -1;
431 m_sample_rate = -1;
432 m_frame_length = -1;
433 }
434
435 //
436 // data members
437 //
438
439 int m_audio_ver;
440 int m_layer_code;
441 boolean m_protection;
442 int m_bitrate_index;
443 int m_sample_index;
444 boolean m_padding;
445 boolean m_private_bit;
446 int m_channel_mode;
447 int m_mode_ext;
448 boolean m_copyright;
449 boolean m_original;
450 int m_emphasis;
451
452 int m_bit_rate;
453 int m_sample_rate;
454 int m_frame_length;
455
456 //
457 // header mask constants
458 //
459 // AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
460 //
461
462 // header masks
463 static final int FRAME_SYNC_MASK = 0xFFE00000; // A 11-bits (31-21) - Frame sync (all bits set)
464 static final int AUDIO_VER_MASK = 0x00180000; // B 2-bits (20,19) - MPEG Audio version ID
465 static final int AUDIO_VER_SHIFT = 19;
466 static final int LAYER_MASK = 0x00060000; // C 2-bits (18,17) - Layer description
467 static final int LAYER_SHIFT = 17;
468 static final int PROTECTION_MASK = 0x00010000; // D 1-bit (16) - Protection bit
469 static final int BITRATE_MASK = 0x0000F000; // E 4-bits (15,12) - Bitrate index
470 static final int BITRATE_SHIFT = 12;
471 static final int SAMPLE_MASK = 0x00000C00; // F 2-bits (11,10) - Sampling rate frequency index (values are in Hz)
472 static final int SAMPLE_SHIFT = 10;
473 static final int PADDING_MASK = 0x00000200; // G 1-bit (9) - Padding bit
474 static final int PRIVATE_MASK = 0x00000100; // H 1-bit (8) - private bit
475 static final int CHANNEL_MASK = 0x000000C0; // I 2-bits (7,6) - Channel Mode
476 static final int CHANNEL_SHIFT = 6;
477 static final int MODE_EXT_MASK = 0x00000030; // J 2-bits (5,4) - Mode extension (Only if Joint stereo)
478 static final int MODE_EXT_SHIFT = 4;
479 static final int COPYRIGHT_MASK = 0x00000008; // K 1-bit (3) - copyright bit
480 static final int ORIGINAL_MASK = 0x00000004; // L 1-bit (2) - Original
481 static final int EMPHASIS_MASK = 0x00000003; // M 2-bits (1,0) - Emphasis
482 static final int EMPHASIS_SHIFT = 0;
483
484
485 //
486 // lookup tables
487 //
488
489 static final int LOOKUP_FAILURE = -777;
490 static final int FREE = -1;
491 static final int BAD = -666;
492 static final int[][] BIT_RATES = {
493 //V1L1 V1L2 V1L3 V2L1 V2L2&3
494 { FREE,FREE,FREE,FREE,FREE} // 0000 (all 'free')
495 ,{ 32 ,32 ,32 ,32 ,8} // 0001
496 ,{ 64 ,48 ,40 ,48 ,16} // 0010
497 ,{ 96 ,56 ,48 ,56 ,24} // 0011
498 ,{ 128 ,64 ,56 ,64 ,32} // 0100
499 ,{ 160 ,80 ,64 ,80 ,40} // 0101
500 ,{ 192 ,96 ,80 ,96 ,48} // 0110
501 ,{ 224 ,112 ,96 ,112 ,56} // 0111
502 ,{ 256 ,128 ,112 ,128 ,64} // 1000
503 ,{ 288 ,160 ,128 ,144 ,80} // 1001
504 ,{ 320 ,192 ,160 ,160 ,96} // 1010
505 ,{ 352 ,224 ,192 ,176 ,112} // 1011
506 ,{ 384 ,256 ,224 ,192 ,128} // 1100
507 ,{ 416 ,320 ,256 ,224 ,144} // 1101
508 ,{ 448 ,384 ,320 ,256 ,160} // 1110
509 ,{ BAD ,BAD ,BAD ,BAD ,BAD} // 1111 (all 'bad')
510 };
511
512 static final int[][] SAMPLE_RATES = {
513 { 44100 ,22050 ,11025}
514 ,{ 48000 ,24000 ,12000}
515 ,{ 32000 ,16000 ,8000}
516 ,{ -1 ,-1 ,-1}
517 };
518
519 //
520 // string constants (for writing into SAX events)
521 //
522
523 static final String[] S_AUDIO_VER = {
524 "2.5", "reserved", "2.0", "1.0"
525 };
526
527 static final int[] S_LAYER = {
528 0, 3, 2, 1
529 };
530
531 static final String[] S_CHANNEL_MODE = {
532 "stereo", "joint-stereo", "dual-mono", "single-mono"
533 };
534
535 static final String[] S_MODE_EXT_LAYER_I_II = {
536 "4-31", "8-31", "12-31", "16-31"
537 };
538
539 static final String[] S_MODE_EXT_LAYER_III = {
540 "", "-intensity", "-m/s", "-intensity-m/s"
541 };
542
543 //
544 // header constants
545 //
546
547 static final int HEADER_SIZE = 4; // bytes
548
549 static final int AUDIO_VER_VERSION_2_5 = 0; //00 - MPEG Version 2.5
550 static final int AUDIO_VER_RESERVED = 1; //01 - reserved
551 static final int AUDIO_VER_VERSION_2 = 2; //10 - MPEG Version 2 (ISO/IEC 13818-3)
552 static final int AUDIO_VER_VERSION_1 = 3; //11 - MPEG Version 1 (ISO/IEC 11172-3)
553
554 static final int LAYER_RESERVED = 0; // 00 - reserved
555 static final int LAYER_III = 1; // 01 - Layer III
556 static final int LAYER_II = 2; // 10 - Layer II
557 static final int LAYER_I = 3; // 11 - Layer I
558
559 static final int CHANNEL_STEREO = 0; // 00 - Stereo
560 static final int CHANNEL_JOINT_STEREO = 1; // 01 - Joint stereo (Stereo)
561 static final int CHANNEL_DUAL = 2; // 10 - Dual channel (Stereo)
562 static final int CHANNEL_SINGLE = 3; // 11 - Single channel (Mono)
563
564 static final int SLOT_LAYER_I = 4; // bytes
565 static final int SLOT_LAYER_II_III = 1; // byte
566
567 /**
568 * logging object
569 */
570 static Log log = LogFactory.getLog(MPEGFrameHeader.class);
571 }
572
573 /*
574 PTARMIGAN MODIFIED BSD LICENSE
575
576 Copyright (c) 2002, Reed Esau (reed.esau@pobox.com) All rights reserved.
577
578 Redistribution and use in source and binary forms, with or without
579 modification, are permitted provided that the following conditions are
580 met:
581
582 Redistributions of source code must retain the above copyright notice,
583 this list of conditions and the following disclaimer.
584
585 Redistributions in binary form must reproduce the above copyright notice,
586 this list of conditions and the following disclaimer in the documentation
587 and/or other materials provided with the distribution.
588
589 Neither the name of the Ptarmigan Project
590 (http://ptarmigan.sourceforge.net) nor the names of its contributors may
591 be used to endorse or promote products derived from this software without
592 specific prior written permission.
593
594 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
595 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
596 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
597 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
598 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
599 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
600 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
601 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
602 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
603 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
604 POSSIBILITY OF SUCH DAMAGE.
605 */