OLD | NEW |
1 // Copyright 2011 Google Inc. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // This code is licensed under the same terms as WebM: | 3 // This code is licensed under the same terms as WebM: |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // Software License Agreement: http://www.webmproject.org/license/software/ |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ |
6 // ----------------------------------------------------------------------------- | 6 // ----------------------------------------------------------------------------- |
7 // | 7 // |
8 // Bit writing and boolean coder | 8 // Bit writing and boolean coder |
9 // | 9 // |
10 // Author: Skal (pascal.massimino@gmail.com) | 10 // Author: Skal (pascal.massimino@gmail.com) |
| 11 // Vikas Arora (vikaas.arora@gmail.com) |
11 | 12 |
12 #include <assert.h> | 13 #include <assert.h> |
13 #include <string.h> // for memcpy() | 14 #include <string.h> // for memcpy() |
14 #include <stdlib.h> | 15 #include <stdlib.h> |
15 #include "./bit_writer.h" | 16 #include "./bit_writer.h" |
16 | 17 |
17 #if defined(__cplusplus) || defined(c_plusplus) | 18 #if defined(__cplusplus) || defined(c_plusplus) |
18 extern "C" { | 19 extern "C" { |
19 #endif | 20 #endif |
20 | 21 |
21 //------------------------------------------------------------------------------ | 22 //------------------------------------------------------------------------------ |
22 // VP8BitWriter | 23 // VP8BitWriter |
23 | 24 |
24 static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) { | 25 static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) { |
25 uint8_t* new_buf; | 26 uint8_t* new_buf; |
26 size_t new_size; | 27 size_t new_size; |
27 const size_t needed_size = bw->pos_ + extra_size; | 28 const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size; |
| 29 const size_t needed_size = (size_t)needed_size_64b; |
| 30 if (needed_size_64b != needed_size) { |
| 31 bw->error_ = 1; |
| 32 return 0; |
| 33 } |
28 if (needed_size <= bw->max_pos_) return 1; | 34 if (needed_size <= bw->max_pos_) return 1; |
| 35 // If the following line wraps over 32bit, the test just after will catch it. |
29 new_size = 2 * bw->max_pos_; | 36 new_size = 2 * bw->max_pos_; |
30 if (new_size < needed_size) | 37 if (new_size < needed_size) new_size = needed_size; |
31 new_size = needed_size; | |
32 if (new_size < 1024) new_size = 1024; | 38 if (new_size < 1024) new_size = 1024; |
33 new_buf = (uint8_t*)malloc(new_size); | 39 new_buf = (uint8_t*)malloc(new_size); |
34 if (new_buf == NULL) { | 40 if (new_buf == NULL) { |
35 bw->error_ = 1; | 41 bw->error_ = 1; |
36 return 0; | 42 return 0; |
37 } | 43 } |
38 if (bw->pos_ > 0) memcpy(new_buf, bw->buf_, bw->pos_); | 44 memcpy(new_buf, bw->buf_, bw->pos_); |
39 free(bw->buf_); | 45 free(bw->buf_); |
40 bw->buf_ = new_buf; | 46 bw->buf_ = new_buf; |
41 bw->max_pos_ = new_size; | 47 bw->max_pos_ = new_size; |
42 return 1; | 48 return 1; |
43 } | 49 } |
44 | 50 |
45 static void kFlush(VP8BitWriter* const bw) { | 51 static void kFlush(VP8BitWriter* const bw) { |
46 const int s = 8 + bw->nb_bits_; | 52 const int s = 8 + bw->nb_bits_; |
47 const int32_t bits = bw->value_ >> s; | 53 const int32_t bits = bw->value_ >> s; |
48 assert(bw->nb_bits_ >= 0); | 54 assert(bw->nb_bits_ >= 0); |
49 bw->value_ -= bits << s; | 55 bw->value_ -= bits << s; |
50 bw->nb_bits_ -= 8; | 56 bw->nb_bits_ -= 8; |
51 if ((bits & 0xff) != 0xff) { | 57 if ((bits & 0xff) != 0xff) { |
52 size_t pos = bw->pos_; | 58 size_t pos = bw->pos_; |
53 if (pos + bw->run_ >= bw->max_pos_) { // reallocate | 59 if (!BitWriterResize(bw, bw->run_ + 1)) { |
54 if (!BitWriterResize(bw, bw->run_ + 1)) { | 60 return; |
55 return; | |
56 } | |
57 } | 61 } |
58 if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's | 62 if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's |
59 if (pos > 0) bw->buf_[pos - 1]++; | 63 if (pos > 0) bw->buf_[pos - 1]++; |
60 } | 64 } |
61 if (bw->run_ > 0) { | 65 if (bw->run_ > 0) { |
62 const int value = (bits & 0x100) ? 0x00 : 0xff; | 66 const int value = (bits & 0x100) ? 0x00 : 0xff; |
63 for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value; | 67 for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value; |
64 } | 68 } |
65 bw->buf_[pos++] = bits; | 69 bw->buf_[pos++] = bits; |
66 bw->pos_ = pos; | 70 bw->pos_ = pos; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 int VP8BitWriterAppend(VP8BitWriter* const bw, | 176 int VP8BitWriterAppend(VP8BitWriter* const bw, |
173 const uint8_t* data, size_t size) { | 177 const uint8_t* data, size_t size) { |
174 assert(data); | 178 assert(data); |
175 if (bw->nb_bits_ != -8) return 0; // kFlush() must have been called | 179 if (bw->nb_bits_ != -8) return 0; // kFlush() must have been called |
176 if (!BitWriterResize(bw, size)) return 0; | 180 if (!BitWriterResize(bw, size)) return 0; |
177 memcpy(bw->buf_ + bw->pos_, data, size); | 181 memcpy(bw->buf_ + bw->pos_, data, size); |
178 bw->pos_ += size; | 182 bw->pos_ += size; |
179 return 1; | 183 return 1; |
180 } | 184 } |
181 | 185 |
| 186 void VP8BitWriterWipeOut(VP8BitWriter* const bw) { |
| 187 if (bw) { |
| 188 free(bw->buf_); |
| 189 memset(bw, 0, sizeof(*bw)); |
| 190 } |
| 191 } |
| 192 |
| 193 //------------------------------------------------------------------------------ |
| 194 // VP8LBitWriter |
| 195 |
| 196 // Returns 1 on success. |
| 197 static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) { |
| 198 uint8_t* allocated_buf; |
| 199 size_t allocated_size; |
| 200 const size_t current_size = VP8LBitWriterNumBytes(bw); |
| 201 const uint64_t size_required_64b = (uint64_t)current_size + extra_size; |
| 202 const size_t size_required = (size_t)size_required_64b; |
| 203 if (size_required != size_required_64b) { |
| 204 bw->error_ = 1; |
| 205 return 0; |
| 206 } |
| 207 if (bw->max_bytes_ > 0 && size_required <= bw->max_bytes_) return 1; |
| 208 allocated_size = (3 * bw->max_bytes_) >> 1; |
| 209 if (allocated_size < size_required) allocated_size = size_required; |
| 210 // make allocated size multiple of 1k |
| 211 allocated_size = (((allocated_size >> 10) + 1) << 10); |
| 212 allocated_buf = (uint8_t*)malloc(allocated_size); |
| 213 if (allocated_buf == NULL) { |
| 214 bw->error_ = 1; |
| 215 return 0; |
| 216 } |
| 217 memcpy(allocated_buf, bw->buf_, current_size); |
| 218 free(bw->buf_); |
| 219 bw->buf_ = allocated_buf; |
| 220 bw->max_bytes_ = allocated_size; |
| 221 memset(allocated_buf + current_size, 0, allocated_size - current_size); |
| 222 return 1; |
| 223 } |
| 224 |
| 225 int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { |
| 226 memset(bw, 0, sizeof(*bw)); |
| 227 return VP8LBitWriterResize(bw, expected_size); |
| 228 } |
| 229 |
| 230 void VP8LBitWriterDestroy(VP8LBitWriter* const bw) { |
| 231 if (bw != NULL) { |
| 232 free(bw->buf_); |
| 233 memset(bw, 0, sizeof(*bw)); |
| 234 } |
| 235 } |
| 236 |
| 237 void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits) { |
| 238 if (n_bits < 1) return; |
| 239 #if !defined(__BIG_ENDIAN__) |
| 240 // Technically, this branch of the code can write up to 25 bits at a time, |
| 241 // but in prefix encoding, the maximum number of bits written is 18 at a time. |
| 242 { |
| 243 uint8_t* const p = &bw->buf_[bw->bit_pos_ >> 3]; |
| 244 uint32_t v = *(const uint32_t*)p; |
| 245 v |= bits << (bw->bit_pos_ & 7); |
| 246 *(uint32_t*)p = v; |
| 247 bw->bit_pos_ += n_bits; |
| 248 } |
| 249 #else // BIG_ENDIAN |
| 250 { |
| 251 uint8_t* p = &bw->buf_[bw->bit_pos_ >> 3]; |
| 252 const int bits_reserved_in_first_byte = bw->bit_pos_ & 7; |
| 253 const int bits_left_to_write = n_bits - 8 + bits_reserved_in_first_byte; |
| 254 // implicit & 0xff is assumed for uint8_t arithmetics |
| 255 *p++ |= bits << bits_reserved_in_first_byte; |
| 256 bits >>= 8 - bits_reserved_in_first_byte; |
| 257 if (bits_left_to_write >= 1) { |
| 258 *p++ = bits; |
| 259 bits >>= 8; |
| 260 if (bits_left_to_write >= 9) { |
| 261 *p++ = bits; |
| 262 bits >>= 8; |
| 263 } |
| 264 } |
| 265 assert(n_bits <= 25); |
| 266 *p = bits; |
| 267 bw->bit_pos_ += n_bits; |
| 268 } |
| 269 #endif |
| 270 if ((bw->bit_pos_ >> 3) > (bw->max_bytes_ - 8)) { |
| 271 const uint64_t extra_size = 32768ULL + bw->max_bytes_; |
| 272 if (extra_size != (size_t)extra_size || |
| 273 !VP8LBitWriterResize(bw, (size_t)extra_size)) { |
| 274 bw->bit_pos_ = 0; |
| 275 bw->error_ = 1; |
| 276 } |
| 277 } |
| 278 } |
| 279 |
182 //------------------------------------------------------------------------------ | 280 //------------------------------------------------------------------------------ |
183 | 281 |
184 #if defined(__cplusplus) || defined(c_plusplus) | 282 #if defined(__cplusplus) || defined(c_plusplus) |
185 } // extern "C" | 283 } // extern "C" |
186 #endif | 284 #endif |
OLD | NEW |