ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / UVLC / uvlc.c
1 #include <VLIB/Platform/video_utils.h>
2 #include <VLIB/video_packetizer.h>
3
4 #include <VP_Os/vp_os_assert.h>
5
6 #include <VP_Os/vp_os_types.h>
7
8 #include <VLIB/UVLC/uvlc.h>
9
10 #ifndef HAS_UVLC_ENCODE
11
12 #define PACK_BITS( bits_out, length_out, bits_in, length_in ) \
13   bits_out  <<= length_in;                                    \
14   length_out += length_in;                                    \
15   bits_out   |= bits_in;
16
17 void uvlc_encode( video_stream_t* const stream, int32_t level, int32_t run, int32_t not_last )
18 {
19   int32_t sign, length, data, value_code, value_length;
20
21   /// Encode number of zeros
22   data = run;
23
24   length      = 0;
25   value_code  = 1;
26
27   if( data > 0 )
28   {
29     length = 32 - clz(data);      // compute number of bits used in run ( = length of run )
30     data  -= 1 << ( length - 1 ); // compute value of run
31   }
32
33   value_length  = length + 1;
34
35   length -= 1;
36   if( length > 0 )
37   {
38     PACK_BITS( value_code, value_length, data, length );
39   }
40
41   /// Encode level
42   data = level;
43
44   // sign handling
45   sign = 0;
46   if( data < 0 )
47   {
48     data = -data;
49     sign = 1;
50   }
51
52   // TODO Check saturation & if level == -128
53   length = 32 - clz(data);  // number of bits used in level ( = length of level )
54   if( length > 1 )
55   {
56     data   -= 1 << (length - 1);
57     length += 1;
58   }
59
60   PACK_BITS( value_code, value_length, 1, length );
61
62   VP_OS_ASSERT( length != 2 );
63
64   length -= 2;
65   if(length > 0)
66   {
67     PACK_BITS( value_code, value_length, data, length );
68   }
69
70   PACK_BITS( value_code, value_length, sign, 1 );
71
72   /// Encode last
73   // add sequence for end of block if required
74   if( not_last == 0 )
75   {
76     PACK_BITS( value_code, value_length, 0x5, 3 );
77   }
78
79   /// Write output
80   video_write_data( stream, value_code, value_length );
81 }
82
83 #endif // HAS_UVLC_ENCODE
84
85 C_RESULT uvlc_decode( video_stream_t* const stream, int32_t* run, int32_t* level, int32_t* last)
86 {
87   uint32_t stream_code, stream_length;
88   int32_t r = 0, z, sign;
89
90   stream_code = stream_length = 0;
91
92   // Peek 32 bits from stream because we know our datas fit in
93   video_peek_data( stream, &stream_code, 32 );
94
95
96   /// Decode number of zeros
97   z = clz(stream_code);
98
99   stream_code  <<= z + 1; // Skip all zeros & 1
100   stream_length += z + 1;
101
102   if( z > 1 )
103   {
104     r = stream_code >> (32 - (z-1));
105
106     stream_code   <<= (z-1);
107     stream_length  += (z-1);
108
109     *run = r + (1 << (z-1));
110   }
111   else
112   {
113     *run = z;
114   }
115
116
117   /// Decode level / last
118   z = clz(stream_code);
119
120   stream_code  <<= z + 1; // Skip all zeros & 1
121   stream_length += z + 1;
122
123   if( z == 1 )
124   {
125     *run  = 0;
126     *last = 1;
127   }
128   else
129   {
130     if( z == 0 )
131     {
132       z = 1;
133       r = 1;
134     }
135
136     stream_length  += z;
137
138     stream_code >>= (32 - z);
139     sign = stream_code & 1;
140
141     if( z != 0 )
142     {
143       r  = stream_code >> 1;
144       r += 1 << (z-1);
145     }
146
147     *level = sign ? -r : r;
148     *last  = 0;
149   }
150
151   // Do the real Read in stream to consume what we used
152   video_read_data( stream, &stream_code, stream_length );
153
154   return C_OK;
155 }