source: svn/trunk/newcon3bcm2_21bu/BSEAV/lib/bcmplayer/src/bvlc.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 9.9 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2005-2009, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bvlc.c $
11 * $brcm_Revision: 8 $
12 * $brcm_Date: 6/5/09 1:42p $
13 *
14 * Module Description: Converts startcode index to bcmplayer index
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /BSEAV/lib/utils/bvlc.c $
19 *
20 * 8   6/5/09 1:42p vsilyaev
21 * PR 55759: Fixed hanlding of rogue data when parsing VLC codes
22 *
23 * 7   3/6/09 11:21a vsilyaev
24 * PR 52903: Fixed use of initialized variable
25 *
26 * 6   9/1/05 3:36p erickson
27 * PR16964: added const to parameter
28 *
29 * 5   7/8/05 10:05a erickson
30 * PR16155: modified b_vlc_decode to require current_index instead of
31 * always starting from data[0]. This makes keeping track of where you
32 * are in the buffer much easier for the application. Also changed and
33 * expanded the examples.
34 *
35 * 4   4/4/05 1:28p erickson
36 * PR12728: fix warnings
37 *
38 * 3   3/23/05 9:02a erickson
39 * PR14451: use std debug interface
40 *
41 * 2   3/22/05 5:21p erickson
42 * PR14451: added optimizations
43 *
44 * 1   3/21/05 3:43p erickson
45 * PR14451: added generic vlc decode algorithm
46 *
47 ************************************************************/
48#include "bvlc.h"
49
50#ifndef USE_LEGACY_KERNAL_INTERFACE
51/* Magnum debug interface */
52#include "bstd.h"
53BDBG_MODULE(bvlc);
54#else
55/* Simplistic debug interface based on stdio */
56#include <stdio.h>
57#define BDBG_ERR(X) /* do {printf X; printf("\n"); } while(0) */
58#define BDBG_WRN(X) BDBG_ERR(X)
59#define BDBG_MSG(X) BDBG_ERR(X)
60#endif
61
62/**
63Advance both bit and index by one through the byte array
64**/
65#define ADVANCE(bit, index, size) \
66        do {if (bit) {(bit)--;} else {(bit)=7;if(++(index)>=size) {goto err_eof;}} } while (0)
67
68/* set next_index and next_bit so any function call then would return EOF */
69static int b_vlc_mark_eof(unsigned size, unsigned *next_index, unsigned *next_bit)
70{
71    *next_bit = 0;
72    if(size>0) {
73        *next_index = size-1;
74    } else {
75        *next_index = 0;
76    }
77    return -1;
78}
79
80static int b_vlc_measure_prefix(const uint8_t *data,unsigned size,unsigned index,unsigned current_bit, 
81        unsigned *next_index,unsigned *next_bit,unsigned *prefix_length)
82{
83        int bit = current_bit;
84        int done = 0;
85
86    *next_bit = current_bit; /* always initialize result */
87        if (bit > 7) {
88                BDBG_ERR(("Invalid bit. Must be 0..7."));
89                return -1;
90        }
91       
92        *prefix_length = 0;
93       
94        /* count 0's to determine prefix_length */
95        for (;;) {
96                while (bit >= 0 && !done) {
97                        if (data[index] & (0x1 << bit))
98                                done = 1;
99                        else {
100                                (*prefix_length)++;
101                                bit--;
102                        }
103                }
104                if (done)  {
105                        break;
106        }
107        index++;
108        if(index<size) {
109                    bit = 7;
110        } else {
111            bit = 0;
112            if(size>0) {
113                index = size-1;
114            } else {
115                index = 0;
116            }
117            goto err_eof;
118        }
119        }
120        /* make sure we have enough data */
121        if (*prefix_length > (size * 8)/2-1) {
122                BDBG_ERR(("not enough data sent for this vlc value"));
123        goto err_eof;
124        }
125       
126        *next_index = index;
127        *next_bit = bit;
128        return 0;
129err_eof:
130    return b_vlc_mark_eof(size, next_index, next_bit);
131}
132
133int b_vlc_skip(const uint8_t *data, unsigned size, unsigned current_index, unsigned current_bit, 
134        unsigned *next_index,unsigned *next_bit)
135{
136        unsigned prefix_length;
137       
138        if (b_vlc_measure_prefix(data, size, current_index, current_bit, next_index, next_bit, &prefix_length)) {
139        goto err_eof;
140    }
141
142#if 1
143        /* Optimization: use integer math to advance by prefix_length + 1 */
144        prefix_length++; /* take into account the middle 1 */
145        if (prefix_length <= *next_bit)
146                *next_bit -= prefix_length;
147        else {
148        unsigned index;
149        prefix_length -= *next_bit + 1;
150        index = *next_index +  1 + prefix_length/8;
151        if(index<size) {
152            *next_index = index;
153            *next_bit = 7 - (prefix_length % 8);
154        } else {
155            goto err_eof;
156        }
157        }
158#else
159        /* advance one bit at a time */
160        /* skip the middle 1 */
161        ADVANCE(*next_bit, *next_index, size);
162       
163        /* skip the suffix - measure_prefix has already guaranteed we have enough data */
164        while (prefix_length--)
165                ADVANCE(*next_bit, *next_index, size);
166#endif
167               
168        return 0;
169err_eof:
170    return b_vlc_mark_eof(size, next_index, next_bit);
171}
172
173int b_vlc_decode(const uint8_t *data,unsigned size,unsigned current_index,unsigned current_bit, 
174        unsigned *next_index,unsigned *next_bit)
175{
176        unsigned index;
177        int bit;
178        unsigned suffix_length, prefix_length;
179        unsigned value;
180        uint64_t suffix;
181               
182        BDBG_MSG(("vlc: %02x%02x %d, bit %d", data[current_index], (size>current_index+1)?data[current_index+1]:0, size, current_bit));
183
184        /* find the first 1, which determines prefix_length */
185        if (b_vlc_measure_prefix(data, size, current_index, current_bit, &index, (unsigned*)&bit, &prefix_length)) {
186        goto err_eof;
187    }
188       
189        if (prefix_length > 64) {
190                BDBG_ERR(("vlc value too large for this algorithm"));
191                /* If you hit this, rework the algorithm. I'm assuming I can load the
192                entire suffix into a primitive datatype. */
193        goto err_eof;
194        }
195       
196        /* advance past middle 1 */
197        ADVANCE(bit, index, size);
198       
199        /* get suffix based on prefix_length */
200       
201        /* Optimization: no prefix, no suffix, value is 0 */
202        if (!prefix_length) {
203                value = 0;
204                BDBG_MSG(("  prefix len 0, done"));
205        }
206        else {
207                /* Optimization: if the suffix is completely contained in this byte, we
208                don't have to operate bitwise */
209                if (prefix_length <= 8 && (int)prefix_length <= bit+1) {
210                        static unsigned char mask[] = {0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
211                        suffix = (data[index] >> (bit-(prefix_length-1))) & mask[prefix_length];
212                        BDBG_MSG(("  prefix len %d, suffix (in byte) val %x", prefix_length, (int)suffix));
213                        bit -= prefix_length;
214                        if (bit == -1) {
215                                bit = 7;
216                                index++;
217                if(index>=size) { goto err_eof; }
218                        }
219                }
220                else {
221                        /* step through it bit by bit. this is the most general way and will
222                        work with any value. */
223                        suffix = 0;
224                        BDBG_MSG(("  prefix len %d, index %d bit %d", prefix_length, index, bit));
225                        for (suffix_length = 0; suffix_length < prefix_length; suffix_length++) {
226                                suffix <<= 1;
227                                if (data[index] & (0x1 << bit))
228                                        suffix |= 1;
229                                ADVANCE(bit, index, size);
230                        }
231                        BDBG_MSG(("  prefix len %d, suffix val %x", prefix_length, (int)suffix));
232                }
233       
234                /* now do the final calculation: 2^prefix_length - 1 + suffix */
235                value = 1;
236                while (prefix_length--) value *= 2;
237                value = value - 1 + suffix;
238        }
239
240        /* move to the next bit so that subsequent calls to b_vld_decode are easy
241        to make for adjacent values. */
242        if (next_index) *next_index = index;
243        if (next_bit) *next_bit = bit;
244               
245        BDBG_MSG(("  result = %d (%d, %d)", value, index, bit));
246        return value;
247err_eof:
248    return b_vlc_mark_eof(size, next_index, next_bit);
249}
250
251#if 0
252/* The VLC algorithm is complicated, and probably should be optimized in the
253future. This routine helps test it. Please leave it in the code for reference. */
254#define BDBG_ASSERT assert
255#include <assert.h>
256
257#define ERROR() do{BDBG_ERR(("Error on line %d", __LINE__)); return -1;}while (0)
258
259int test(unsigned char byte0, unsigned char byte1, unsigned char byte2,
260        int size, int test_val, int test_next_index, int test_next_bit)
261{
262        char buf[3] = {byte0, byte1, byte2};
263        int val;
264        unsigned next_index, next_bit;
265       
266        next_index = 0; next_bit = 7;
267        val = b_vlc_decode(buf, size, next_index, next_bit, &next_index, &next_bit);
268        if (val != test_val) ERROR();
269        if (next_index != test_next_index) ERROR();
270        if (next_bit != test_next_bit) ERROR();
271
272        next_index = 0; next_bit = 7;
273        b_vlc_skip(buf, size, next_index, next_bit, &next_index, &next_bit);
274        if (next_index != test_next_index) ERROR();
275        if (next_bit != test_next_bit) ERROR();
276       
277        return 0;
278}
279
280int main()
281{
282        char buf[10];
283        int val;
284        unsigned next_index, next_bit;
285
286        test(0x80, 0x00, 0x00, 1,               0, 0, 6);
287        test(0x40, 0x00, 0x00, 1,               1, 4, 0);
288        test(0x60, 0x00, 0x00, 1,               2, 0, 4);
289        test(0x20, 0x00, 0x00, 1,               3, 0, 2);
290        test(0x28, 0x00, 0x00, 1,               4, 0, 2);
291        test(0x14, 0x00, 0x00, 1,               9, 0, 0);
292        test(0x05, 0x40, 0x00, 2,               41, 1, 4);
293        test(0x01, 0x40, 0x00, 2,               158, 1, 1);
294        test(0x01, 0xFF, 0x00, 2,               254, 1, 0);
295        test(0x00, 0x20, 0x00, 3,               1023, 2, 2);
296       
297        buf[0] = 0xf4; /* skip,skip,skip,skip, 010 */
298        next_index = 0; next_bit = 7;
299        b_vlc_skip(buf, 1, next_index, next_bit, &next_index, &next_bit);
300        BDBG_ASSERT(next_bit == 6);
301        b_vlc_skip(buf, 1, next_index, next_bit, &next_index, &next_bit);
302        BDBG_ASSERT(next_bit == 5);
303        b_vlc_skip(buf, 1, next_index, next_bit, &next_index, &next_bit);
304        BDBG_ASSERT(next_bit == 4);
305        b_vlc_skip(buf, 1, next_index, next_bit, &next_index, &next_bit);
306        BDBG_ASSERT(next_bit == 3);
307        val = b_vlc_decode(buf, 1, next_index, next_bit, &next_index, &next_bit);
308        BDBG_ASSERT(val == 1);
309        BDBG_ASSERT(next_index == 0);
310        BDBG_ASSERT(next_bit == 0);
311
312        buf[0] = 0xf0; /* 0, 0, 0, 0 */
313        next_index = 0; next_bit = 7;
314        val = b_vlc_decode(buf, 1, next_index, next_bit, &next_index, &next_bit);
315        BDBG_ASSERT(val == 0);
316        val = b_vlc_decode(buf, 1, next_index, next_bit, &next_index, &next_bit);
317        BDBG_ASSERT(val == 0);
318        val = b_vlc_decode(buf, 1, next_index, next_bit, &next_index, &next_bit);
319        BDBG_ASSERT(val == 0);
320        val = b_vlc_decode(buf, 1, next_index, next_bit, &next_index, &next_bit);
321        BDBG_ASSERT(val == 0);
322        BDBG_ASSERT(next_index == 0);
323        BDBG_ASSERT(next_bit == 3);
324       
325        buf[0] = 0x00;
326        buf[1] = 0xf0;
327        buf[2] = 0xe0;
328        next_index = 0; next_bit = 7;
329        val = b_vlc_decode(buf, 3, next_index, next_bit, &next_index, &next_bit);
330        BDBG_ASSERT(val == 480);
331        val = b_vlc_decode(buf, 3, next_index, next_bit, &next_index, &next_bit);
332        BDBG_ASSERT(val == 0);
333        val = b_vlc_decode(buf, 3, next_index, next_bit, &next_index, &next_bit);
334        BDBG_ASSERT(val == 0);
335        BDBG_ASSERT(next_index == 2);
336        BDBG_ASSERT(next_bit == 4);
337       
338        return 0;
339}
340#endif
Note: See TracBrowser for help on using the repository browser.