1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18/*
19------------------------------------------------------------------------------
20
21   PacketVideo Corp.
22   MP3 Decoder Library
23
24   Filename: pvmp3_seek_synch.cpp
25
26   Functions:
27        pvmp3_seek_synch
28        pvmp3_header_sync
29
30
31     Date: 9/21/2007
32
33------------------------------------------------------------------------------
34 REVISION HISTORY
35
36
37 Description:
38
39------------------------------------------------------------------------------
40 INPUT AND OUTPUT DEFINITIONS
41
42pvmp3_frame_synch
43
44Input
45    pExt = pointer to the external interface structure. See the file
46           pvmp3decoder_api.h for a description of each field.
47           Data type of pointer to a tPVMP3DecoderExternal
48           structure.
49
50    pMem = void pointer to hide the internal implementation of the library
51           It is cast back to a tmp3dec_file structure. This structure
52           contains information that needs to persist between calls to
53           this function, or is too big to be placed on the stack, even
54           though the data is only needed during execution of this function
55           Data type void pointer, internally pointer to a tmp3dec_file
56           structure.
57
58
59------------------------------------------------------------------------------
60 FUNCTION DESCRIPTION
61
62    search mp3 sync word, when found, it verifies, based on header parameters,
63    the locations of the very next sync word,
64    - if fails, then indicates a false sync,
65    - otherwise, it confirm synchronization of at least 2 consecutives frames
66
67------------------------------------------------------------------------------
68 REQUIREMENTS
69
70
71------------------------------------------------------------------------------
72 REFERENCES
73
74------------------------------------------------------------------------------
75 PSEUDO-CODE
76
77------------------------------------------------------------------------------
78*/
79
80
81/*----------------------------------------------------------------------------
82; INCLUDES
83----------------------------------------------------------------------------*/
84
85#include "pvmp3_seek_synch.h"
86#include "pvmp3_getbits.h"
87#include "s_tmp3dec_file.h"
88#include "pv_mp3dec_fxd_op.h"
89#include "pvmp3_tables.h"
90
91
92/*----------------------------------------------------------------------------
93; MACROS
94; Define module specific macros here
95----------------------------------------------------------------------------*/
96
97
98/*----------------------------------------------------------------------------
99; DEFINES
100; Include all pre-processor statements here. Include conditional
101; compile variables also.
102----------------------------------------------------------------------------*/
103
104/*----------------------------------------------------------------------------
105; LOCAL FUNCTION DEFINITIONS
106; Function Prototype declaration
107----------------------------------------------------------------------------*/
108
109/*----------------------------------------------------------------------------
110; LOCAL STORE/BUFFER/POINTER DEFINITIONS
111; Variable declaration - defined here and used outside this module
112----------------------------------------------------------------------------*/
113
114/*----------------------------------------------------------------------------
115; EXTERNAL FUNCTION REFERENCES
116; Declare functions defined elsewhere and referenced in this module
117----------------------------------------------------------------------------*/
118
119/*----------------------------------------------------------------------------
120; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
121; Declare variables used in this module but defined elsewhere
122----------------------------------------------------------------------------*/
123
124/*----------------------------------------------------------------------------
125; FUNCTION CODE
126----------------------------------------------------------------------------*/
127
128
129
130ERROR_CODE pvmp3_frame_synch(tPVMP3DecoderExternal *pExt,
131                             void                  *pMem) /* bit stream structure */
132{
133    uint16 val;
134    ERROR_CODE err;
135
136    tmp3dec_file      *pVars;
137
138    pVars = (tmp3dec_file *)pMem;
139
140    pVars->inputStream.pBuffer = pExt->pInputBuffer;
141    pVars->inputStream.usedBits = (pExt->inputBufferUsedLength << 3); // in bits
142
143
144    pVars->inputStream.inputBufferCurrentLength = (pExt->inputBufferCurrentLength); // in bits
145
146    err = pvmp3_header_sync(&pVars->inputStream);
147
148    if (err == NO_DECODING_ERROR)
149    {
150        /* validate synchronization by checking two consecutive sync words */
151
152        // to avoid multiple bitstream accesses
153        uint32 temp = getNbits(&pVars->inputStream, 21);
154        // put back whole header
155        pVars->inputStream.usedBits -= 21 + SYNC_WORD_LNGTH;
156
157        int32  version;
158
159        switch (temp >> 19)  /* 2 */
160        {
161            case 0:
162                version = MPEG_2_5;
163                break;
164            case 2:
165                version = MPEG_2;
166                break;
167            case 3:
168                version = MPEG_1;
169                break;
170            default:
171                version = INVALID_VERSION;
172                break;
173        }
174
175        int32 freq_index = (temp << 20) >> 30;
176
177        if (version != INVALID_VERSION && (freq_index != 3))
178        {
179            int32 numBytes = fxp_mul32_Q28(mp3_bitrate[version][(temp<<16)>>28] << 20,
180                                           inv_sfreq[freq_index]);
181
182            numBytes >>= (20 - version);
183
184            if (version != MPEG_1)
185            {
186                numBytes >>= 1;
187            }
188            if ((temp << 22) >> 31)
189            {
190                numBytes++;
191            }
192
193            if (numBytes > (int32)pVars->inputStream.inputBufferCurrentLength)
194            {
195                /* frame should account for padding and 2 bytes to check sync */
196                pExt->CurrentFrameLength = numBytes + 3;
197                return (SYNCH_LOST_ERROR);
198            }
199            else if (numBytes == (int32)pVars->inputStream.inputBufferCurrentLength)
200            {
201                /* No enough data to validate, but current frame appears to be correct ( EOF case) */
202                pExt->inputBufferUsedLength = pVars->inputStream.usedBits >> 3;
203                return (NO_DECODING_ERROR);
204            }
205            else
206            {
207
208                int32 offset = pVars->inputStream.usedBits + ((numBytes) << 3);
209
210                offset >>= INBUF_ARRAY_INDEX_SHIFT;
211                uint8    *pElem  = pVars->inputStream.pBuffer + offset;
212                uint16 tmp1 = *(pElem++);
213                uint16 tmp2 = *(pElem);
214
215                val = (tmp1 << 3);
216                val |= (tmp2 >> 5);
217            }
218        }
219        else
220        {
221            val = 0; // force mismatch
222        }
223
224        if (val == SYNC_WORD)
225        {
226            pExt->inputBufferUsedLength = pVars->inputStream.usedBits >> 3; ///  !!!!!
227            err = NO_DECODING_ERROR;
228        }
229        else
230        {
231            pExt->inputBufferCurrentLength = 0;
232            err = SYNCH_LOST_ERROR;
233        }
234    }
235    else
236    {
237        pExt->inputBufferCurrentLength = 0;
238    }
239
240    return(err);
241
242}
243
244/*
245------------------------------------------------------------------------------
246 REVISION HISTORY
247
248
249 Description:
250
251------------------------------------------------------------------------------
252 INPUT AND OUTPUT DEFINITIONS
253
254pvmp3_header_sync
255
256Input
257    tmp3Bits *inputStream,     structure holding the input stream parameters
258
259------------------------------------------------------------------------------
260 FUNCTION DESCRIPTION
261
262    search mp3 sync word
263
264------------------------------------------------------------------------------
265 REQUIREMENTS
266
267
268------------------------------------------------------------------------------
269 REFERENCES
270
271------------------------------------------------------------------------------
272 PSEUDO-CODE
273
274------------------------------------------------------------------------------
275*/
276
277/*----------------------------------------------------------------------------
278; FUNCTION CODE
279----------------------------------------------------------------------------*/
280
281
282ERROR_CODE pvmp3_header_sync(tmp3Bits  *inputStream)
283{
284    uint16 val;
285    uint32 availableBits = (inputStream->inputBufferCurrentLength << 3); // in bits
286
287    // byte aligment
288    inputStream->usedBits = (inputStream->usedBits + 7) & 8;
289
290    val = (uint16)getUpTo17bits(inputStream, SYNC_WORD_LNGTH);
291
292    while (((val&SYNC_WORD) != SYNC_WORD) && (inputStream->usedBits < availableBits))
293    {
294        val <<= 8;
295        val |= getUpTo9bits(inputStream, 8);
296    }
297
298    if ((val&SYNC_WORD) == SYNC_WORD && (inputStream->usedBits < availableBits))
299    {
300        return(NO_DECODING_ERROR);
301    }
302    else
303    {
304        return(SYNCH_LOST_ERROR);
305    }
306
307}
308
309