|
1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 /************************************************************************** |
|
21 mpif.cpp - MPEG-1, MPEG-2 LSF and MPEG-2.5 file format implementations. |
|
22 |
|
23 Author(s): Juha Ojanpera |
|
24 Copyright (c) 1999-2004 by Nokia Research Center, Speech and Audio Systems. |
|
25 *************************************************************************/ |
|
26 |
|
27 /*-- project headers --*/ |
|
28 #include "mpif.h" |
|
29 //#include "auddef.h" |
|
30 #include "mpheader.h" |
|
31 #include "nok_bits.h" |
|
32 #include "mstream.h" |
|
33 |
|
34 |
|
35 /************************************************************************** |
|
36 Internal Objects |
|
37 *************************************************************************/ |
|
38 |
|
39 /* |
|
40 Purpose: Sync lost after 16384 bytes. |
|
41 Explanation: - */ |
|
42 #define SYNC_THRESHOLD (16384 << 3) |
|
43 |
|
44 /************************************************************************** |
|
45 Title : main_data_slots |
|
46 |
|
47 Purpose : Computes the number of bytes for the layer III payload. The |
|
48 payload consists of the scalefactors and quantized data of |
|
49 the channel(s). |
|
50 |
|
51 Usage : y = main_data_slots(mp) |
|
52 |
|
53 Input : mp - mp3 file format parameters |
|
54 |
|
55 Output : y - # of payload bytes for this frame |
|
56 |
|
57 Author(s) : Juha Ojanpera |
|
58 *************************************************************************/ |
|
59 |
|
60 INLINE int32 |
|
61 main_data_slots(TMpTransportHandle *tHandle) |
|
62 { |
|
63 int16 nSlots; |
|
64 |
|
65 if(bit_rate(&tHandle->header)) |
|
66 { |
|
67 nSlots = tHandle->SlotTable[bit_rate_idx(&tHandle->header)]; |
|
68 |
|
69 if(padding(&tHandle->header)) |
|
70 nSlots++; |
|
71 if(error_protection(&tHandle->header)) |
|
72 nSlots -= 2; |
|
73 } |
|
74 else |
|
75 { |
|
76 nSlots = tHandle->FreeFormatSlots; |
|
77 |
|
78 if(padding(&tHandle->header)) |
|
79 nSlots++; |
|
80 } |
|
81 |
|
82 return(nSlots); |
|
83 } |
|
84 |
|
85 /* |
|
86 * Maximum # of bits needed for the header. Note that only |
|
87 * 20 bits are read since 12 bits were read already when |
|
88 * locating the start of frame. 16 bits are needed for |
|
89 * the optional CRC codeword. |
|
90 */ |
|
91 #define MAX_MP_HEADER_SIZE (20 + 16) |
|
92 |
|
93 /************************************************************************** |
|
94 Title : decode_header |
|
95 |
|
96 Purpose : Reads header information (excluding syncword) from the bitstream. |
|
97 |
|
98 Usage : decode_header(tHandle, bs) |
|
99 |
|
100 Input : tHandle - file format parser |
|
101 bs - input bitstream |
|
102 |
|
103 Explanation : Header information is commmon to all layers. Note also that |
|
104 this function doesn't interprete the fields of the header. |
|
105 |
|
106 Author(s) : Juha Ojanpera |
|
107 *************************************************************************/ |
|
108 |
|
109 INLINE SEEK_STATUS |
|
110 decode_header(TMpTransportHandle *tHandle, TBitStream *bs) |
|
111 { |
|
112 uint32 header, bitsLeft; |
|
113 |
|
114 bitsLeft = (BsGetBufSize(bs) << 3) - BsGetBitsRead(bs); |
|
115 if(bitsLeft < MAX_MP_HEADER_SIZE) |
|
116 return (SYNC_BITS_OUT); |
|
117 |
|
118 /*-- Read rest of the header bits. --*/ |
|
119 tHandle->headerOld.header = tHandle->header.header; |
|
120 header = (!tHandle->mpeg25) << HEADER_BITS; |
|
121 header |= BsGetBits(bs, HEADER_BITS); |
|
122 tHandle->header.header = header; |
|
123 |
|
124 /*-- Read CRC codeword. --*/ |
|
125 if(error_protection(&tHandle->header)) |
|
126 tHandle->crc.crc = (int16) BsGetBits(bs, 16); |
|
127 |
|
128 return (SYNC_FOUND); |
|
129 } |
|
130 |
|
131 /************************************************************************** |
|
132 Title : GetSideInfoSlots |
|
133 |
|
134 Purpose : Retrieves the amount of side info for layer III stream. |
|
135 |
|
136 Usage : y = GetSideInfoSlots(tHandle) |
|
137 |
|
138 Input : tHandle - file format parser |
|
139 |
|
140 Output : y - # of side info bytes |
|
141 |
|
142 Author(s) : Juha Ojanpera |
|
143 *************************************************************************/ |
|
144 |
|
145 int16 |
|
146 GetSideInfoSlots(TMpTransportHandle *tHandle) |
|
147 { |
|
148 int16 nSlots = 0; |
|
149 |
|
150 if(version(&tHandle->header) != MPEG_PHASE2_LSF) |
|
151 nSlots = (channels(&tHandle->header) == 1) ? (int16) 17 : (int16) 32; |
|
152 else |
|
153 nSlots = (channels(&tHandle->header) == 1) ? (int16) 9 : (int16) 17; |
|
154 |
|
155 return (nSlots); |
|
156 } |
|
157 |
|
158 int16 |
|
159 GetSideInfoSlots(TMPEG_Header *header) |
|
160 { |
|
161 int16 nSlots = 0; |
|
162 |
|
163 if(version(header) != MPEG_PHASE2_LSF) |
|
164 nSlots = (channels(header) == 1) ? 17 : 32; |
|
165 else |
|
166 nSlots = (channels(header) == 1) ? 9 : 17; |
|
167 |
|
168 return (nSlots); |
|
169 } |
|
170 |
|
171 /************************************************************************** |
|
172 Title : GetSlotSize |
|
173 |
|
174 Purpose : Retrieves the amount of frame data for layer III stream. |
|
175 |
|
176 Usage : y = GetSlotSize(tHandle) |
|
177 |
|
178 Input : tHandle - file format parser |
|
179 |
|
180 Output : y - # of frame data bytes |
|
181 |
|
182 Author(s) : Juha Ojanpera |
|
183 *************************************************************************/ |
|
184 |
|
185 static INLINE int16 |
|
186 GetSlotSize(TMpTransportHandle *tHandle) |
|
187 { |
|
188 int16 ave_slots; |
|
189 |
|
190 if(bit_rate(&tHandle->header)) |
|
191 ave_slots = (int16) tHandle->aveFrameLen; |
|
192 else |
|
193 { |
|
194 ave_slots = (int16) (tHandle->FreeFormatSlots + GetSideInfoSlots(tHandle)); |
|
195 if(error_protection(&tHandle->header)) |
|
196 ave_slots += 2; |
|
197 ave_slots += 4; |
|
198 } |
|
199 |
|
200 return (ave_slots); |
|
201 } |
|
202 |
|
203 INLINE int32 * |
|
204 GetSeekOffset(TMpTransportHandle *tHandle, int32 *seekValues) |
|
205 { |
|
206 int16 main_data; |
|
207 int32 frameOffset, byte_offset; |
|
208 |
|
209 /* |
|
210 * Some reinitialization need to be performed after file pointer has been |
|
211 * moved to the new postion. For this reason, the total number of frames |
|
212 * to be skipped does not correspond exactly to the given time offset. |
|
213 * However, after reinitialization the playback position should be the correct. |
|
214 */ |
|
215 byte_offset = GetSlotSize(tHandle); |
|
216 main_data = (int16) ((version(&tHandle->header) == MPEG_PHASE2_LSF) ? 256 : 512); |
|
217 frameOffset = (byte_offset) ? main_data / byte_offset : 0; |
|
218 |
|
219 if(byte_offset) |
|
220 if(main_data % byte_offset) |
|
221 frameOffset++; |
|
222 |
|
223 seekValues[0] = frameOffset; |
|
224 seekValues[1] = byte_offset; |
|
225 |
|
226 return (seekValues); |
|
227 } |
|
228 |
|
229 /* |
|
230 * Estimates the bitrate of the mp3 stream from the size of the |
|
231 * payload + side info + header. The accuracy of the computed |
|
232 * bitrate depends very much on the accuracy of the average frame |
|
233 * size. |
|
234 */ |
|
235 int16 |
|
236 MP_EstimateBitrate(TMpTransportHandle *tHandle, uint8 isVbr) |
|
237 { |
|
238 int16 bitRate; |
|
239 |
|
240 if(!bit_rate(&tHandle->header) || isVbr) |
|
241 { |
|
242 FLOAT div; |
|
243 |
|
244 div = (FLOAT) ((version(&tHandle->header) == MPEG_PHASE2_LSF) ? 72 : 144); |
|
245 bitRate = (int16) (((frequency(&tHandle->header) / 1000.0f) * GetSlotSize(tHandle) / div) + 0.5f); |
|
246 } |
|
247 else |
|
248 bitRate = bit_rate(&tHandle->header); |
|
249 |
|
250 return (bitRate); |
|
251 } |
|
252 |
|
253 /* |
|
254 * Returns the length of the track in milliseconds. |
|
255 */ |
|
256 uint32 |
|
257 MP_FileLengthInMs(TMpTransportHandle *tHandle, int32 fileSize) |
|
258 { |
|
259 FLOAT frames = fileSize / (FLOAT) GetSlotSize(tHandle); |
|
260 |
|
261 return (uint32) (frames * GetFrameTime(&tHandle->header) + 0.5f); |
|
262 } |
|
263 |
|
264 /* |
|
265 * Returns the byte offset corresponding to the specified seeking position. |
|
266 */ |
|
267 int32 |
|
268 MP_GetSeekOffset(TMpTransportHandle *tHandle, int32 seekPos) |
|
269 { |
|
270 FLOAT numFrames; |
|
271 int32 seekValues[2], frameOffset, byte_offset; |
|
272 |
|
273 GetSeekOffset(tHandle, seekValues); |
|
274 |
|
275 frameOffset = seekValues[0]; |
|
276 byte_offset = seekValues[1]; |
|
277 |
|
278 numFrames = seekPos / (FLOAT) GetFrameTime(&tHandle->header); |
|
279 if(numFrames < frameOffset) |
|
280 frameOffset = 0; |
|
281 |
|
282 /*-- Total offset. --*/ |
|
283 byte_offset = (int32) ((byte_offset * (numFrames - frameOffset)) + 0.5f); |
|
284 |
|
285 return (byte_offset); |
|
286 } |
|
287 |
|
288 /* |
|
289 * Returns the duration of each frame in milliseconds. |
|
290 */ |
|
291 int32 |
|
292 MP_GetFrameTime(TMpTransportHandle *tHandle) |
|
293 { |
|
294 return (GetFrameTime(&tHandle->header)); |
|
295 } |
|
296 |
|
297 /* |
|
298 * Checks if the specified mp3 stream is using free format |
|
299 * i.e., bitrate is not specified in the header part |
|
300 * of the frame. |
|
301 * |
|
302 * Return TRUE if bitrate not specified, FALSE otherwise |
|
303 */ |
|
304 BOOL |
|
305 IsMP3FreeFormat(TMpTransportHandle *tHandle) |
|
306 { |
|
307 return (bit_rate(&tHandle->header) == 0); |
|
308 } |
|
309 |
|
310 /************************************************************************** |
|
311 Title : FillDataSlotTable |
|
312 |
|
313 Purpose : Pre-computes (to avoid division operation during decoding) |
|
314 the payload size of layer III for all bitrates. This function |
|
315 should be called once the start of 1st frame has been located. |
|
316 |
|
317 Usage : y = FillDataSlotTable(tHandle) |
|
318 |
|
319 Input : tHandle - file format parser |
|
320 |
|
321 Author(s) : Juha Ojanpera |
|
322 *************************************************************************/ |
|
323 |
|
324 INLINE void |
|
325 FillDataSlotTable(TMpTransportHandle *tHandle) |
|
326 { |
|
327 int16 nSlots; |
|
328 const int16 *brTbl; |
|
329 |
|
330 brTbl = GetBitRateTable(&tHandle->header); |
|
331 |
|
332 /* |
|
333 * index 0 is free format and index 14 illegal bitrate. |
|
334 */ |
|
335 for(int16 i = 1; i < 15; i++) |
|
336 { |
|
337 nSlots = (int16)((144 * brTbl[i]) / (frequency(&tHandle->header) / 1000.0f)); |
|
338 |
|
339 if(version(&tHandle->header) == MPEG_PHASE2_LSF) |
|
340 nSlots >>= 1; |
|
341 |
|
342 nSlots = (int16) (nSlots - GetSideInfoSlots(tHandle) - 4); |
|
343 tHandle->SlotTable[i] = nSlots; |
|
344 } |
|
345 } |
|
346 |
|
347 /************************************************************************** |
|
348 Title : SeekSync |
|
349 |
|
350 Purpose : Seeks for a byte aligned sync word in the bitstream and |
|
351 places the bitstream pointer right after the sync word. |
|
352 |
|
353 Usage : y = SeekSync(mp, bs_mcu, bufMapper, execState) |
|
354 |
|
355 Input : mp - mp3 stream parameters |
|
356 bs_mcu - bitstream parameters |
|
357 execState - exec status of this function |
|
358 |
|
359 Output : y : |
|
360 SYNC_BITS_OUT - bit buffer need to be updated |
|
361 SYNC_LOST - start of next frame was not found |
|
362 SYNC_FOUND - OK to decode next frame |
|
363 |
|
364 Author(s) : Juha Ojanpera |
|
365 *************************************************************************/ |
|
366 |
|
367 INLINE SEEK_STATUS |
|
368 SeekSync(TMpTransportHandle *tHandle, TBitStream *bs_mcu, ExecState *execState) |
|
369 { |
|
370 #define PRESYNCBITS (MP_SYNC_WORD_LENGTH + 8) |
|
371 #define POSTSYNCBITS (MAX_MP_HEADER_SIZE + 1) |
|
372 |
|
373 uint32 hdr, bits_left; |
|
374 BOOL exitCheck = TRUE; |
|
375 int32 sync_cand, bits_read; |
|
376 |
|
377 bits_left = (BsSlotsLeft(bs_mcu) - 1) << 3; |
|
378 |
|
379 if(execState->execMode == GLITCH_FREE && bits_left > PRESYNCBITS) |
|
380 { |
|
381 bits_left -= (BsByteAlign(bs_mcu) + (bits_read = tHandle->syncInfo.sync_length)); |
|
382 sync_cand = BsGetBits(bs_mcu, tHandle->syncInfo.sync_length); |
|
383 } |
|
384 else if(execState->execMode == GLITCH_FREE) |
|
385 { |
|
386 execState->execMode = GLITCH_FREE; |
|
387 |
|
388 return (SYNC_BITS_OUT); |
|
389 } |
|
390 else |
|
391 { |
|
392 sync_cand = (int32)execState->a0_u32[0]; |
|
393 bits_read = (int32)execState->a0_u32[1]; |
|
394 } |
|
395 |
|
396 while(exitCheck) |
|
397 { |
|
398 while(sync_cand != tHandle->syncInfo.sync_word && |
|
399 bits_read < SYNC_THRESHOLD && bits_left) |
|
400 { |
|
401 bits_read++; |
|
402 bits_left--; |
|
403 sync_cand = (sync_cand << 1) & tHandle->syncInfo.sync_mask; |
|
404 sync_cand |= (int16) BsGetBits(bs_mcu, 1); |
|
405 } |
|
406 |
|
407 if(bits_read > SYNC_THRESHOLD) |
|
408 return (SYNC_LOST); |
|
409 else if(bits_left < POSTSYNCBITS) |
|
410 { |
|
411 execState->execMode = GLITCH0; |
|
412 execState->a0_u32[0] = sync_cand; |
|
413 execState->a0_u32[1] = bits_read; |
|
414 |
|
415 return (SYNC_BITS_OUT); |
|
416 } |
|
417 else |
|
418 { |
|
419 bits_read++; |
|
420 bits_left--; |
|
421 sync_cand = (sync_cand << 1) & tHandle->syncInfo.sync_mask; |
|
422 sync_cand |= (int16) BsGetBits(bs_mcu, 1); |
|
423 |
|
424 tHandle->mpeg25 = !(sync_cand & 0x1); |
|
425 |
|
426 /* Check the next frame header. */ |
|
427 hdr = (!tHandle->mpeg25) << HEADER_BITS; |
|
428 tHandle->header.header = hdr | BsLookAhead(bs_mcu, HEADER_BITS); |
|
429 |
|
430 /* Detect false frame boundaries. */ |
|
431 switch(tHandle->syncInfo.sync_status) |
|
432 { |
|
433 case LAYER3_STREAM: |
|
434 if(HEADER_MASK(tHandle->header.header) == HEADER_MASK(tHandle->headerOld.header) && |
|
435 sfreq(&tHandle->header) != 3 && LAYER_MASK(tHandle->header.header) == 0x1) |
|
436 { |
|
437 if(tHandle->FreeFormatSlots == 0) |
|
438 { |
|
439 if(bit_rate(&tHandle->header)) |
|
440 exitCheck = FALSE; |
|
441 } |
|
442 else exitCheck = FALSE; |
|
443 } |
|
444 break; |
|
445 |
|
446 case INIT_LAYER3_STREAM: |
|
447 if(!(version(&tHandle->header) && mp25version(&tHandle->header))) |
|
448 { |
|
449 if(sfreq(&tHandle->header) != 3 && LAYER_MASK(tHandle->header.header) == 0x1 && bit_rate_idx(&tHandle->header) != 15) |
|
450 { |
|
451 tHandle->headerOld.header = tHandle->header.header; |
|
452 tHandle->syncInfo.sync_status = LAYER3_STREAM; |
|
453 exitCheck = FALSE; |
|
454 } |
|
455 } |
|
456 break; |
|
457 |
|
458 default: |
|
459 break; |
|
460 } |
|
461 } |
|
462 } |
|
463 |
|
464 execState->execMode = GLITCH_FREE; |
|
465 |
|
466 return (SYNC_FOUND); |
|
467 } |
|
468 |
|
469 /************************************************************************** |
|
470 Title : FindFreeFormatSlotCount |
|
471 |
|
472 Purpose : Determines the size of the payload of a free format stream. |
|
473 |
|
474 Usage : y = FindFreeFormatSlotCount(mpDec, bs_mcu, execState) |
|
475 |
|
476 Input : mpDec - mp3 stream parameters |
|
477 bs_mcu - bitstream parameters |
|
478 execState - exec status of this function |
|
479 |
|
480 Output : y : |
|
481 SYNC_BITS_OUT - bit buffer need to be updated |
|
482 SYNC_LOST - stream is undecodable |
|
483 SYNC_FOUND - OK to start playback |
|
484 |
|
485 Author(s) : Juha Ojanpera |
|
486 *************************************************************************/ |
|
487 |
|
488 INLINE SEEK_STATUS |
|
489 FreeFormat(TMpTransportHandle *tHandle, TBitStream *bs_mcu, ExecState *execState) |
|
490 { |
|
491 int16 exitCheck; |
|
492 TMPEG_Header oldHeader; |
|
493 uint16 sync_cand; |
|
494 uint32 bits_read, bits_left; |
|
495 |
|
496 tHandle->FreeFormatSlots = 0; |
|
497 |
|
498 if(execState->execMode == GLITCH_FREE) |
|
499 { |
|
500 int16 nSlots, minBytes; |
|
501 |
|
502 nSlots = GetSideInfoSlots(tHandle); |
|
503 minBytes = (uint16) (nSlots + 7); |
|
504 if((BsSlotsLeft(bs_mcu) - 1) < (uint16) minBytes) |
|
505 { |
|
506 execState->execMode = GLITCH_FREE; |
|
507 return (SYNC_BITS_OUT); |
|
508 } |
|
509 |
|
510 /*-- Read 1st header. --*/ |
|
511 decode_header(tHandle, bs_mcu); |
|
512 oldHeader.header = tHandle->header.header; |
|
513 |
|
514 /*-- Skip side info part. --*/ |
|
515 BsSkipNBits(bs_mcu, nSlots << 3); |
|
516 |
|
517 sync_cand = (uint16) BsGetBits(bs_mcu, tHandle->syncInfo.sync_length); |
|
518 bits_read = tHandle->syncInfo.sync_length; |
|
519 } |
|
520 else |
|
521 { |
|
522 sync_cand = (uint16) execState->a0_u32[0]; |
|
523 bits_read = (uint32) execState->a0_u32[1]; |
|
524 oldHeader.header = (uint32)execState->a0_u32[2]; |
|
525 } |
|
526 |
|
527 exitCheck = 1; |
|
528 bits_left = (BsSlotsLeft(bs_mcu) - 1) << 3; |
|
529 //mask = (uint16) ((1 << (tHandle->syncInfo.sync_length - 1)) - 1); |
|
530 |
|
531 while(exitCheck) |
|
532 { |
|
533 while(sync_cand != tHandle->syncInfo.sync_word && bits_left) |
|
534 { |
|
535 bits_read++; |
|
536 bits_left--; |
|
537 sync_cand = (uint16) ((sync_cand << 1) & tHandle->syncInfo.sync_mask); |
|
538 sync_cand |= (uint16) BsGetBits(bs_mcu, 1); |
|
539 } |
|
540 |
|
541 if(bits_left < (HEADER_BITS + 1)) |
|
542 { |
|
543 execState->a0_u32[0] = sync_cand; |
|
544 execState->a0_u32[1] = bits_read; |
|
545 execState->a0_u32[2] = oldHeader.header; |
|
546 execState->execMode = GLITCH0; |
|
547 |
|
548 return (SYNC_BITS_OUT); |
|
549 } |
|
550 else |
|
551 { |
|
552 uint32 hdr; |
|
553 |
|
554 bits_read++; |
|
555 bits_left--; |
|
556 sync_cand = (sync_cand << 1) & tHandle->syncInfo.sync_mask; |
|
557 sync_cand |= (int16) BsGetBits(bs_mcu, 1); |
|
558 |
|
559 tHandle->mpeg25 = !(sync_cand & 0x1); |
|
560 |
|
561 /* Check the next frame header. */ |
|
562 hdr = (!tHandle->mpeg25) << HEADER_BITS; |
|
563 tHandle->header.header = hdr | BsLookAhead(bs_mcu, HEADER_BITS); |
|
564 |
|
565 /* |
|
566 * Detect false frame boundraries. We could use header macros here |
|
567 * to speed up the comparison but since this function is called only |
|
568 * once (before playback/editing starts) the advantages of macros are |
|
569 * negligible. |
|
570 */ |
|
571 if(channels(&tHandle->header) == channels(&oldHeader) && |
|
572 sfreq(&tHandle->header) == sfreq(&oldHeader) && |
|
573 bit_rate(&tHandle->header) == bit_rate(&oldHeader) && |
|
574 layer_number(&tHandle->header) == layer_number(&oldHeader) && |
|
575 version(&tHandle->header) == version(&oldHeader) && |
|
576 mode(&tHandle->header) == mode(&oldHeader) && |
|
577 error_protection(&tHandle->header) == error_protection(&oldHeader)) |
|
578 exitCheck = 0; |
|
579 |
|
580 /* The payload size cannot be determined. */ |
|
581 else if(bits_read > SYNC_THRESHOLD) |
|
582 return (SYNC_LOST); |
|
583 } |
|
584 } |
|
585 |
|
586 /*-- Determine the size of the payload data. --*/ |
|
587 if(bits_read != 0) |
|
588 { |
|
589 bits_read -= (tHandle->syncInfo.sync_length + 1); |
|
590 tHandle->FreeFormatSlots = (int16) (bits_read >> 3); |
|
591 |
|
592 if(padding(&oldHeader)) |
|
593 tHandle->FreeFormatSlots -= 1; |
|
594 } |
|
595 else |
|
596 { |
|
597 tHandle->FreeFormatSlots = -1; |
|
598 |
|
599 return (SYNC_LOST); |
|
600 } |
|
601 |
|
602 execState->execMode = GLITCH_FREE; |
|
603 tHandle->transportType = GET_MPSYNC_STREAM; |
|
604 tHandle->syncInfo.sync_status = INIT_LAYER3_STREAM; |
|
605 |
|
606 return (SYNC_FOUND); |
|
607 } |
|
608 |
|
609 /************************************************************************** |
|
610 Title : mpSyncTransport |
|
611 |
|
612 Purpose : Sync layer interface for MPEG Layer I/II/III file formats. |
|
613 |
|
614 Usage : y = mpSyncTransport(tHandle, syncBuf, syncBufLen, readBits) |
|
615 |
|
616 Input : tHandle - handle to MPEG Layer I/II/III parser |
|
617 syncBuf - handle to sync layer buffer |
|
618 syncBufLen - # of bytes present in sync layer buffer |
|
619 |
|
620 Output : y - status of operation |
|
621 SYNC_BITS_OUT - the sync layer buffer needs to be updated |
|
622 SYNC_LOST - function failed |
|
623 SYNC_FOUND - sync layer processing successfull |
|
624 readBits - # of bits read from sync layer buffer |
|
625 |
|
626 Author(s) : Juha Ojanpera |
|
627 *************************************************************************/ |
|
628 |
|
629 |
|
630 SEEK_STATUS |
|
631 mpSyncTransport(TMpTransportHandle *tHandle, uint8 *syncBuf, |
|
632 uint32 syncBufLen, uint32 *readBits) |
|
633 { |
|
634 BOOL hitExit; |
|
635 ExecState *execState; |
|
636 TBitStream m_Bitstream; |
|
637 SEEK_STATUS frameStatus; |
|
638 |
|
639 *readBits = 0; |
|
640 hitExit = FALSE; |
|
641 frameStatus = SYNC_LOST; |
|
642 execState = &tHandle->execState; |
|
643 |
|
644 BsInit(&m_Bitstream, syncBuf, syncBufLen); |
|
645 |
|
646 if(tHandle->offsetBits) |
|
647 BsSkipNBits(&m_Bitstream, tHandle->offsetBits); |
|
648 tHandle->offsetBits = 0; |
|
649 |
|
650 while(hitExit == FALSE) |
|
651 { |
|
652 uint32 tmp; |
|
653 uint8 syncByte(0); |
|
654 |
|
655 switch(tHandle->transportType) |
|
656 { |
|
657 case INIT_MP_STREAM: |
|
658 frameStatus = SYNC_LOST; |
|
659 tHandle->transportType = GET_1ST_MPSYNC_STREAM; |
|
660 break; |
|
661 |
|
662 case GET_1ST_MPSYNC_STREAM: |
|
663 /* |
|
664 * Locate sync and on succes, switch to read |
|
665 * the headers values. |
|
666 */ |
|
667 frameStatus = SeekSync(tHandle, &m_Bitstream, execState); |
|
668 if((frameStatus == SYNC_FOUND) && IsMP3FreeFormat(tHandle)) |
|
669 { |
|
670 hitExit = TRUE; |
|
671 frameStatus = SYNC_MP3_FREE; |
|
672 tHandle->offsetBits = (int16) (BsGetBitsRead(&m_Bitstream) & 0x7); |
|
673 } |
|
674 else if(frameStatus == SYNC_FOUND) |
|
675 tHandle->transportType = GET_MPHEADER_STREAM; |
|
676 else |
|
677 { |
|
678 hitExit = TRUE; |
|
679 if(frameStatus != SYNC_LOST) |
|
680 { |
|
681 /* |
|
682 * The sync search locates the syncword which is at the |
|
683 * start of the header (1st 12 bits). Also in order to |
|
684 * make the search reliable, the rest of the header bits |
|
685 * are also checked via lookahead by the sync routine. |
|
686 * Because of this it is possible that the input buffer |
|
687 * may run out of bits in the lookahead part. In that case |
|
688 * the input buffer needs to be updated. The number of bytes |
|
689 * to be updated are calculated based on the number of read |
|
690 * bits. Thus, in the worst case, the update process will |
|
691 * throw away the 1st 8 bits from the syncword. This is |
|
692 * something we don't want to experience since subsequent |
|
693 * processing relies on the fact that the whole header can |
|
694 * be read from the input buffer once the start of the frame |
|
695 * has been found. That's why we reduce the update size of the |
|
696 * input buffer (shown below). |
|
697 */ |
|
698 tmp = BsGetBitsRead(&m_Bitstream); |
|
699 syncByte = syncBuf[MAX(0, ((int32) (tmp >> 3) - 1))]; |
|
700 if((tmp & 0x7) && syncByte == 0xFF) |
|
701 { |
|
702 /*-- Keep the previous byte in the buffer as it may be part of header. --*/ |
|
703 tHandle->offsetBits = (int16) (8 + (tmp & 0x7)); |
|
704 |
|
705 tmp -= 8; |
|
706 BsClearBitsRead(&m_Bitstream); |
|
707 BsSetBitsRead(&m_Bitstream, tmp); |
|
708 } |
|
709 else tHandle->offsetBits = (int16) (tmp & 0x7); |
|
710 } |
|
711 } |
|
712 break; |
|
713 |
|
714 case GET_MPSYNC_STREAM: |
|
715 /* |
|
716 * Locate sync and on succes, switch to read |
|
717 * the headers values. |
|
718 */ |
|
719 frameStatus = SeekSync(tHandle, &m_Bitstream, execState); |
|
720 if(frameStatus == SYNC_FOUND) |
|
721 tHandle->transportType = GET_MPHEADER_STREAM; |
|
722 else |
|
723 { |
|
724 hitExit = TRUE; |
|
725 if(frameStatus != SYNC_LOST) |
|
726 { |
|
727 /*-- See explanation above. --*/ |
|
728 tmp = BsGetBitsRead(&m_Bitstream); |
|
729 syncByte = syncBuf[MAX(0, ((int32) (tmp >> 3) - 1))]; |
|
730 if((tmp & 0x7) && syncByte == 0xFF) |
|
731 { |
|
732 /*-- Keep the previous byte in the buffer as it may be part of header. --*/ |
|
733 tHandle->offsetBits = (int16) (8 + (tmp & 0x7)); |
|
734 |
|
735 tmp -= 8; |
|
736 BsClearBitsRead(&m_Bitstream); |
|
737 BsSetBitsRead(&m_Bitstream, tmp); |
|
738 } |
|
739 else tHandle->offsetBits = (int16) (tmp & 0x7); |
|
740 } |
|
741 } |
|
742 break; |
|
743 |
|
744 case GET_MPHEADER_STREAM: |
|
745 /* |
|
746 * Read headers values and on success, switch the state back |
|
747 * to sync search for next frame. |
|
748 */ |
|
749 hitExit = TRUE; |
|
750 frameStatus = decode_header(tHandle, &m_Bitstream); |
|
751 if(frameStatus == SYNC_FOUND) |
|
752 tHandle->transportType = GET_MPSYNC_STREAM; |
|
753 else if(frameStatus != SYNC_LOST) |
|
754 { |
|
755 /*-- Don't loose the syncword... --*/ |
|
756 tmp = BsGetBitsRead(&m_Bitstream); |
|
757 syncByte = syncBuf[MAX(0, ((int32) (tmp >> 3) - 1))]; |
|
758 if((tmp & 0x7) && syncByte == 0xFF) |
|
759 { |
|
760 /*-- Keep the previous byte in the buffer as it may be part of header. --*/ |
|
761 tHandle->offsetBits = (int16) (8 + (tmp & 0x7)); |
|
762 |
|
763 tmp -= 8; |
|
764 BsClearBitsRead(&m_Bitstream); |
|
765 BsSetBitsRead(&m_Bitstream, tmp); |
|
766 } |
|
767 else tHandle->offsetBits = (int16) (tmp & 0x7); |
|
768 } |
|
769 break; |
|
770 |
|
771 default: |
|
772 hitExit = TRUE; |
|
773 frameStatus = SYNC_LOST; |
|
774 break; |
|
775 } |
|
776 } |
|
777 |
|
778 *readBits = BsGetBitsRead(&m_Bitstream); |
|
779 |
|
780 return (frameStatus); |
|
781 } |
|
782 |
|
783 /* |
|
784 * Returns the # of bytes reserved for the Layer I/II/III payload part of current frame. |
|
785 */ |
|
786 INLINE int16 |
|
787 mpGetTranportFrameLength(TMpTransportHandle *tHandle) |
|
788 { |
|
789 int16 frameBytes; |
|
790 |
|
791 tHandle->mainDataSlots = 0; |
|
792 |
|
793 switch(tHandle->transportType) |
|
794 { |
|
795 case GET_MPSYNC_STREAM: |
|
796 case GET_MPHEADER_STREAM: |
|
797 tHandle->mainDataSlots = (int16) main_data_slots(tHandle); |
|
798 frameBytes = (int16) (tHandle->mainDataSlots + GetSideInfoSlots(tHandle)); |
|
799 break; |
|
800 |
|
801 default: |
|
802 frameBytes = 0; |
|
803 break; |
|
804 } |
|
805 |
|
806 return (frameBytes); |
|
807 } |
|
808 |
|
809 /* |
|
810 * Initializes MPEG Layer I/II/III transport handle. |
|
811 */ |
|
812 void |
|
813 mpInitTransport(TMpTransportHandle *tHandle) |
|
814 { |
|
815 ZERO_MEMORY(tHandle, sizeof(TMpTransportHandle)); |
|
816 |
|
817 tHandle->syncInfo.sync_word = (int16) SYNC_WORD; |
|
818 tHandle->syncInfo.sync_length = (int16) MP_SYNC_WORD_LENGTH; |
|
819 tHandle->syncInfo.sync_mask = (uint16) ((1 << tHandle->syncInfo.sync_length) - 1); |
|
820 tHandle->syncInfo.sync_status = INIT_LAYER3_STREAM; |
|
821 tHandle->transportType = INIT_MP_STREAM; |
|
822 tHandle->execState.execMode = GLITCH_FREE; |
|
823 tHandle->offsetBits = 0; |
|
824 } |
|
825 |
|
826 /************************************************************************** |
|
827 Title : MP_SeekSync |
|
828 |
|
829 Purpose : Interface to layer I/II/III frame search implementation. |
|
830 |
|
831 Usage : y = MP_SeekSync(tHandle, syncBuf, syncBufLen, readBytes, |
|
832 frameBytes, headerBytes, initMode) |
|
833 |
|
834 Input : tHandle - layer I/II/III transport handle |
|
835 syncBuf - input buffer |
|
836 syncBufLen - length of 'sync_buf' |
|
837 initMode - '1' when searching the 1st frame, '0' otherwise |
|
838 |
|
839 Output : y - status of operation |
|
840 frameBytes - # of bytes reserved for the payload part of the frame |
|
841 readBytes - # of bytes read from the buffer |
|
842 headerBytes - # of bytes reserved for the header part of the frame |
|
843 |
|
844 Author(s) : Juha Ojanpera |
|
845 *************************************************************************/ |
|
846 |
|
847 int16 |
|
848 MP_SeekSync(TMpTransportHandle *tHandle, uint8 *syncBuf, uint32 syncBufLen, |
|
849 int16 *readBytes, int16 *frameBytes, int16 *headerBytes, |
|
850 uint8 initMode) |
|
851 { |
|
852 uint32 readBits; |
|
853 SEEK_STATUS syncSeekStatus; |
|
854 |
|
855 syncSeekStatus = mpSyncTransport(tHandle, syncBuf, syncBufLen, &readBits); |
|
856 if(initMode && syncSeekStatus == SYNC_FOUND) |
|
857 FillDataSlotTable(tHandle); |
|
858 |
|
859 *readBytes = (int16) (readBits >> 3); |
|
860 *frameBytes = (int16) mpGetTranportFrameLength(tHandle); |
|
861 *headerBytes = (int16) ((error_protection(&tHandle->header) ? 2 : 0) + 4); |
|
862 |
|
863 return (int16) (syncSeekStatus); |
|
864 } |
|
865 |
|
866 /************************************************************************** |
|
867 Title : MP_FreeMode |
|
868 |
|
869 Purpose : Interface for determining the frame/payload size of free format |
|
870 layer III bitstream. |
|
871 |
|
872 Usage : y = MP_FreeMode(tHandle, syncBuf, syncBufLen, readBytes, |
|
873 frameBytes, headerBytes) |
|
874 |
|
875 Input : tHandle - layer I/II/III transport handle |
|
876 syncBuf - input buffer |
|
877 syncBufLen - length of 'sync_buf' |
|
878 |
|
879 Output : y - status of operation |
|
880 frameBytes - # of bytes reserved for the payload part of the frames |
|
881 readBytes - # of bytes read from the buffer |
|
882 headerBytes - # of bytes reserved for the header part of the frame |
|
883 |
|
884 Author(s) : Juha Ojanpera |
|
885 *************************************************************************/ |
|
886 |
|
887 int16 |
|
888 MP_FreeMode(TMpTransportHandle *tHandle, uint8 *syncBuf, uint32 syncBufLen, |
|
889 int16 *readBytes, int16 *frameBytes, int16 *headerBytes) |
|
890 { |
|
891 TBitStream m_Bitstream; |
|
892 SEEK_STATUS syncSeekStatus; |
|
893 |
|
894 BsInit(&m_Bitstream, syncBuf, syncBufLen); |
|
895 |
|
896 if(tHandle->offsetBits) |
|
897 BsSkipNBits(&m_Bitstream, tHandle->offsetBits); |
|
898 tHandle->offsetBits = 0; |
|
899 |
|
900 syncSeekStatus = FreeFormat(tHandle, &m_Bitstream, &tHandle->execState); |
|
901 if(syncSeekStatus == SYNC_BITS_OUT) |
|
902 tHandle->offsetBits = (int16) (BsGetBitsRead(&m_Bitstream) & 0x7); |
|
903 |
|
904 *readBytes = (int16) (BsGetBitsRead(&m_Bitstream) >> 3); |
|
905 *frameBytes = (int16) mpGetTranportFrameLength(tHandle); |
|
906 *headerBytes = (int16) ((error_protection(&tHandle->header) ? 2 : 0) + 4); |
|
907 |
|
908 return (int16) (syncSeekStatus); |
|
909 } |