OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
9 // | 9 // |
10 // Incremental decoding | 10 // Incremental decoding |
11 // | 11 // |
12 // Author: somnath@google.com (Somnath Banerjee) | 12 // Author: somnath@google.com (Somnath Banerjee) |
13 | 13 |
14 #include <assert.h> | 14 #include <assert.h> |
15 #include <string.h> | 15 #include <string.h> |
16 #include <stdlib.h> | 16 #include <stdlib.h> |
17 | 17 |
| 18 #include "./alphai.h" |
18 #include "./webpi.h" | 19 #include "./webpi.h" |
19 #include "./vp8i.h" | 20 #include "./vp8i.h" |
20 #include "../utils/utils.h" | 21 #include "../utils/utils.h" |
21 | 22 |
22 #if defined(__cplusplus) || defined(c_plusplus) | |
23 extern "C" { | |
24 #endif | |
25 | |
26 // In append mode, buffer allocations increase as multiples of this value. | 23 // In append mode, buffer allocations increase as multiples of this value. |
27 // Needs to be a power of 2. | 24 // Needs to be a power of 2. |
28 #define CHUNK_SIZE 4096 | 25 #define CHUNK_SIZE 4096 |
29 #define MAX_MB_SIZE 4096 | 26 #define MAX_MB_SIZE 4096 |
30 | 27 |
31 //------------------------------------------------------------------------------ | 28 //------------------------------------------------------------------------------ |
32 // Data structures for memory and states | 29 // Data structures for memory and states |
33 | 30 |
34 // Decoding states. State normally flows like HEADER->PARTS0->DATA->DONE. | 31 // Decoding states. State normally flows as: |
| 32 // WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and |
| 33 // WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. |
35 // If there is any error the decoder goes into state ERROR. | 34 // If there is any error the decoder goes into state ERROR. |
36 typedef enum { | 35 typedef enum { |
37 STATE_PRE_VP8, // All data before that of the first VP8 chunk. | 36 STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. |
38 STATE_VP8_FRAME_HEADER, // For VP8 Frame header (within VP8 chunk). | 37 STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). |
39 STATE_VP8_PARTS0, | 38 STATE_VP8_PARTS0, |
40 STATE_VP8_DATA, | 39 STATE_VP8_DATA, |
41 STATE_VP8L_HEADER, | 40 STATE_VP8L_HEADER, |
42 STATE_VP8L_DATA, | 41 STATE_VP8L_DATA, |
43 STATE_DONE, | 42 STATE_DONE, |
44 STATE_ERROR | 43 STATE_ERROR |
45 } DecState; | 44 } DecState; |
46 | 45 |
47 // Operating state for the MemBuffer | 46 // Operating state for the MemBuffer |
48 typedef enum { | 47 typedef enum { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 } | 94 } |
96 } | 95 } |
97 | 96 |
98 static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { | 97 static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { |
99 return (mem->end_ - mem->start_); | 98 return (mem->end_ - mem->start_); |
100 } | 99 } |
101 | 100 |
102 // Check if we need to preserve the compressed alpha data, as it may not have | 101 // Check if we need to preserve the compressed alpha data, as it may not have |
103 // been decoded yet. | 102 // been decoded yet. |
104 static int NeedCompressedAlpha(const WebPIDecoder* const idec) { | 103 static int NeedCompressedAlpha(const WebPIDecoder* const idec) { |
105 if (idec->state_ == STATE_PRE_VP8) { | 104 if (idec->state_ == STATE_WEBP_HEADER) { |
106 // We haven't parsed the headers yet, so we don't know whether the image is | 105 // We haven't parsed the headers yet, so we don't know whether the image is |
107 // lossy or lossless. This also means that we haven't parsed the ALPH chunk. | 106 // lossy or lossless. This also means that we haven't parsed the ALPH chunk. |
108 return 0; | 107 return 0; |
109 } | 108 } |
110 if (idec->is_lossless_) { | 109 if (idec->is_lossless_) { |
111 return 0; // ALPH chunk is not present for lossless images. | 110 return 0; // ALPH chunk is not present for lossless images. |
112 } else { | 111 } else { |
113 const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; | 112 const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
114 assert(dec != NULL); // Must be true as idec->state_ != STATE_PRE_VP8. | 113 assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER. |
115 return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; | 114 return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; |
116 } | 115 } |
117 } | 116 } |
118 | 117 |
119 static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { | 118 static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { |
120 MemBuffer* const mem = &idec->mem_; | 119 MemBuffer* const mem = &idec->mem_; |
121 const uint8_t* const new_base = mem->buf_ + mem->start_; | 120 const uint8_t* const new_base = mem->buf_ + mem->start_; |
122 // note: for VP8, setting up idec->io_ is only really needed at the beginning | 121 // note: for VP8, setting up idec->io_ is only really needed at the beginning |
123 // of the decoding, till partition #0 is complete. | 122 // of the decoding, till partition #0 is complete. |
124 idec->io_.data = new_base; | 123 idec->io_.data = new_base; |
125 idec->io_.data_size = MemDataSize(mem); | 124 idec->io_.data_size = MemDataSize(mem); |
126 | 125 |
127 if (idec->dec_ != NULL) { | 126 if (idec->dec_ != NULL) { |
128 if (!idec->is_lossless_) { | 127 if (!idec->is_lossless_) { |
129 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; | 128 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
130 const int last_part = dec->num_parts_ - 1; | 129 const int last_part = dec->num_parts_ - 1; |
131 if (offset != 0) { | 130 if (offset != 0) { |
132 int p; | 131 int p; |
133 for (p = 0; p <= last_part; ++p) { | 132 for (p = 0; p <= last_part; ++p) { |
134 RemapBitReader(dec->parts_ + p, offset); | 133 RemapBitReader(dec->parts_ + p, offset); |
135 } | 134 } |
136 // Remap partition #0 data pointer to new offset, but only in MAP | 135 // Remap partition #0 data pointer to new offset, but only in MAP |
137 // mode (in APPEND mode, partition #0 is copied into a fixed memory). | 136 // mode (in APPEND mode, partition #0 is copied into a fixed memory). |
138 if (mem->mode_ == MEM_MODE_MAP) { | 137 if (mem->mode_ == MEM_MODE_MAP) { |
139 RemapBitReader(&dec->br_, offset); | 138 RemapBitReader(&dec->br_, offset); |
140 } | 139 } |
141 } | 140 } |
142 assert(last_part >= 0); | 141 assert(last_part >= 0); |
143 dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; | 142 dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; |
144 if (NeedCompressedAlpha(idec)) dec->alpha_data_ += offset; | 143 if (NeedCompressedAlpha(idec)) { |
| 144 ALPHDecoder* const alph_dec = dec->alph_dec_; |
| 145 dec->alpha_data_ += offset; |
| 146 if (alph_dec != NULL) { |
| 147 if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { |
| 148 VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; |
| 149 assert(alph_vp8l_dec != NULL); |
| 150 assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); |
| 151 VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, |
| 152 dec->alpha_data_ + ALPHA_HEADER_LEN, |
| 153 dec->alpha_data_size_ - ALPHA_HEADER_LEN); |
| 154 } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION |
| 155 // Nothing special to do in this case. |
| 156 } |
| 157 } |
| 158 } |
145 } else { // Resize lossless bitreader | 159 } else { // Resize lossless bitreader |
146 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; | 160 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; |
147 VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); | 161 VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); |
148 } | 162 } |
149 } | 163 } |
150 } | 164 } |
151 | 165 |
152 // Appends data to the end of MemBuffer->buf_. It expands the allocated memory | 166 // Appends data to the end of MemBuffer->buf_. It expands the allocated memory |
153 // size if required and also updates VP8BitReader's if new memory is allocated. | 167 // size if required and also updates VP8BitReader's if new memory is allocated. |
154 static int AppendToMemBuffer(WebPIDecoder* const idec, | 168 static int AppendToMemBuffer(WebPIDecoder* const idec, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 *token_br = context->token_br_; | 275 *token_br = context->token_br_; |
262 memcpy(dec->intra_t_ + 4 * dec->mb_x_, context->intra_t_, 4); | 276 memcpy(dec->intra_t_ + 4 * dec->mb_x_, context->intra_t_, 4); |
263 memcpy(dec->intra_l_, context->intra_l_, 4); | 277 memcpy(dec->intra_l_, context->intra_l_, 4); |
264 } | 278 } |
265 | 279 |
266 //------------------------------------------------------------------------------ | 280 //------------------------------------------------------------------------------ |
267 | 281 |
268 static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { | 282 static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { |
269 if (idec->state_ == STATE_VP8_DATA) { | 283 if (idec->state_ == STATE_VP8_DATA) { |
270 VP8Io* const io = &idec->io_; | 284 VP8Io* const io = &idec->io_; |
271 if (io->teardown) { | 285 if (io->teardown != NULL) { |
272 io->teardown(io); | 286 io->teardown(io); |
273 } | 287 } |
274 } | 288 } |
275 idec->state_ = STATE_ERROR; | 289 idec->state_ = STATE_ERROR; |
276 return error; | 290 return error; |
277 } | 291 } |
278 | 292 |
279 static void ChangeState(WebPIDecoder* const idec, DecState new_state, | 293 static void ChangeState(WebPIDecoder* const idec, DecState new_state, |
280 size_t consumed_bytes) { | 294 size_t consumed_bytes) { |
281 MemBuffer* const mem = &idec->mem_; | 295 MemBuffer* const mem = &idec->mem_; |
(...skipping 22 matching lines...) Expand all Loading... |
304 } | 318 } |
305 | 319 |
306 idec->chunk_size_ = headers.compressed_size; | 320 idec->chunk_size_ = headers.compressed_size; |
307 idec->is_lossless_ = headers.is_lossless; | 321 idec->is_lossless_ = headers.is_lossless; |
308 if (!idec->is_lossless_) { | 322 if (!idec->is_lossless_) { |
309 VP8Decoder* const dec = VP8New(); | 323 VP8Decoder* const dec = VP8New(); |
310 if (dec == NULL) { | 324 if (dec == NULL) { |
311 return VP8_STATUS_OUT_OF_MEMORY; | 325 return VP8_STATUS_OUT_OF_MEMORY; |
312 } | 326 } |
313 idec->dec_ = dec; | 327 idec->dec_ = dec; |
314 #ifdef WEBP_USE_THREAD | |
315 dec->use_threads_ = (idec->params_.options != NULL) && | |
316 (idec->params_.options->use_threads > 0); | |
317 #else | |
318 dec->use_threads_ = 0; | |
319 #endif | |
320 dec->alpha_data_ = headers.alpha_data; | 328 dec->alpha_data_ = headers.alpha_data; |
321 dec->alpha_data_size_ = headers.alpha_data_size; | 329 dec->alpha_data_size_ = headers.alpha_data_size; |
322 ChangeState(idec, STATE_VP8_FRAME_HEADER, headers.offset); | 330 ChangeState(idec, STATE_VP8_HEADER, headers.offset); |
323 } else { | 331 } else { |
324 VP8LDecoder* const dec = VP8LNew(); | 332 VP8LDecoder* const dec = VP8LNew(); |
325 if (dec == NULL) { | 333 if (dec == NULL) { |
326 return VP8_STATUS_OUT_OF_MEMORY; | 334 return VP8_STATUS_OUT_OF_MEMORY; |
327 } | 335 } |
328 idec->dec_ = dec; | 336 idec->dec_ = dec; |
329 ChangeState(idec, STATE_VP8L_HEADER, headers.offset); | 337 ChangeState(idec, STATE_VP8L_HEADER, headers.offset); |
330 } | 338 } |
331 return VP8_STATUS_OK; | 339 return VP8_STATUS_OK; |
332 } | 340 } |
333 | 341 |
334 static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { | 342 static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { |
335 const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; | 343 const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; |
336 const size_t curr_size = MemDataSize(&idec->mem_); | 344 const size_t curr_size = MemDataSize(&idec->mem_); |
| 345 int width, height; |
337 uint32_t bits; | 346 uint32_t bits; |
338 | 347 |
339 if (curr_size < VP8_FRAME_HEADER_SIZE) { | 348 if (curr_size < VP8_FRAME_HEADER_SIZE) { |
340 // Not enough data bytes to extract VP8 Frame Header. | 349 // Not enough data bytes to extract VP8 Frame Header. |
341 return VP8_STATUS_SUSPENDED; | 350 return VP8_STATUS_SUSPENDED; |
342 } | 351 } |
343 if (!VP8GetInfo(data, curr_size, idec->chunk_size_, NULL, NULL)) { | 352 if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) { |
344 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); | 353 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); |
345 } | 354 } |
346 | 355 |
347 bits = data[0] | (data[1] << 8) | (data[2] << 16); | 356 bits = data[0] | (data[1] << 8) | (data[2] << 16); |
348 idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; | 357 idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; |
349 | 358 |
350 idec->io_.data = data; | 359 idec->io_.data = data; |
351 idec->io_.data_size = curr_size; | 360 idec->io_.data_size = curr_size; |
352 idec->state_ = STATE_VP8_PARTS0; | 361 idec->state_ = STATE_VP8_PARTS0; |
353 return VP8_STATUS_OK; | 362 return VP8_STATUS_OK; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 } | 409 } |
401 return IDecError(idec, status); | 410 return IDecError(idec, status); |
402 } | 411 } |
403 | 412 |
404 // Allocate/Verify output buffer now | 413 // Allocate/Verify output buffer now |
405 dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, | 414 dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, |
406 output); | 415 output); |
407 if (dec->status_ != VP8_STATUS_OK) { | 416 if (dec->status_ != VP8_STATUS_OK) { |
408 return IDecError(idec, dec->status_); | 417 return IDecError(idec, dec->status_); |
409 } | 418 } |
410 | 419 // This change must be done before calling VP8InitFrame() |
| 420 dec->mt_method_ = VP8GetThreadMethod(params->options, NULL, |
| 421 io->width, io->height); |
| 422 VP8InitDithering(params->options, dec); |
411 if (!CopyParts0Data(idec)) { | 423 if (!CopyParts0Data(idec)) { |
412 return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY); | 424 return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY); |
413 } | 425 } |
414 | 426 |
415 // Finish setting up the decoding parameters. Will call io->setup(). | 427 // Finish setting up the decoding parameters. Will call io->setup(). |
416 if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { | 428 if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { |
417 return IDecError(idec, dec->status_); | 429 return IDecError(idec, dec->status_); |
418 } | 430 } |
419 | 431 |
420 // Note: past this point, teardown() must always be called | 432 // Note: past this point, teardown() must always be called |
421 // in case of error. | 433 // in case of error. |
422 idec->state_ = STATE_VP8_DATA; | 434 idec->state_ = STATE_VP8_DATA; |
423 // Allocate memory and prepare everything. | 435 // Allocate memory and prepare everything. |
424 if (!VP8InitFrame(dec, io)) { | 436 if (!VP8InitFrame(dec, io)) { |
425 return IDecError(idec, dec->status_); | 437 return IDecError(idec, dec->status_); |
426 } | 438 } |
427 return VP8_STATUS_OK; | 439 return VP8_STATUS_OK; |
428 } | 440 } |
429 | 441 |
430 // Remaining partitions | 442 // Remaining partitions |
431 static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { | 443 static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { |
432 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; | 444 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
433 VP8Io* const io = &idec->io_; | 445 VP8Io* const io = &idec->io_; |
434 | 446 |
435 assert(dec->ready_); | 447 assert(dec->ready_); |
436 | |
437 for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { | 448 for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { |
438 VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; | 449 VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; |
439 if (dec->mb_x_ == 0) { | 450 for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { |
440 VP8InitScanline(dec); | |
441 } | |
442 for (; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) { | |
443 MBContext context; | 451 MBContext context; |
444 SaveContext(dec, token_br, &context); | 452 SaveContext(dec, token_br, &context); |
445 | |
446 if (!VP8DecodeMB(dec, token_br)) { | 453 if (!VP8DecodeMB(dec, token_br)) { |
447 RestoreContext(&context, dec, token_br); | 454 RestoreContext(&context, dec, token_br); |
448 // We shouldn't fail when MAX_MB data was available | 455 // We shouldn't fail when MAX_MB data was available |
449 if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) { | 456 if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) { |
450 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); | 457 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); |
451 } | 458 } |
452 return VP8_STATUS_SUSPENDED; | 459 return VP8_STATUS_SUSPENDED; |
453 } | 460 } |
454 // Reconstruct and emit samples. | |
455 VP8ReconstructBlock(dec); | |
456 | |
457 // Release buffer only if there is only one partition | 461 // Release buffer only if there is only one partition |
458 if (dec->num_parts_ == 1) { | 462 if (dec->num_parts_ == 1) { |
459 idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; | 463 idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; |
460 assert(idec->mem_.start_ <= idec->mem_.end_); | 464 assert(idec->mem_.start_ <= idec->mem_.end_); |
461 } | 465 } |
462 } | 466 } |
| 467 VP8InitScanline(dec); // Prepare for next scanline |
| 468 |
| 469 // Reconstruct, filter and emit the row. |
463 if (!VP8ProcessRow(dec, io)) { | 470 if (!VP8ProcessRow(dec, io)) { |
464 return IDecError(idec, VP8_STATUS_USER_ABORT); | 471 return IDecError(idec, VP8_STATUS_USER_ABORT); |
465 } | 472 } |
466 dec->mb_x_ = 0; | |
467 } | 473 } |
468 // Synchronize the thread and check for errors. | 474 // Synchronize the thread and check for errors. |
469 if (!VP8ExitCritical(dec, io)) { | 475 if (!VP8ExitCritical(dec, io)) { |
470 return IDecError(idec, VP8_STATUS_USER_ABORT); | 476 return IDecError(idec, VP8_STATUS_USER_ABORT); |
471 } | 477 } |
472 dec->ready_ = 0; | 478 dec->ready_ = 0; |
473 idec->state_ = STATE_DONE; | 479 idec->state_ = STATE_DONE; |
474 | 480 |
475 return VP8_STATUS_OK; | 481 return VP8_STATUS_OK; |
476 } | 482 } |
477 | 483 |
478 static int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) { | 484 static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec, |
| 485 VP8StatusCode status) { |
479 if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { | 486 if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { |
480 return VP8_STATUS_SUSPENDED; | 487 return VP8_STATUS_SUSPENDED; |
481 } | 488 } |
482 return IDecError(idec, status); | 489 return IDecError(idec, status); |
483 } | 490 } |
484 | 491 |
485 static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { | 492 static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { |
486 VP8Io* const io = &idec->io_; | 493 VP8Io* const io = &idec->io_; |
487 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; | 494 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; |
488 const WebPDecParams* const params = &idec->params_; | 495 const WebPDecParams* const params = &idec->params_; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 | 532 |
526 idec->state_ = STATE_DONE; | 533 idec->state_ = STATE_DONE; |
527 | 534 |
528 return VP8_STATUS_OK; | 535 return VP8_STATUS_OK; |
529 } | 536 } |
530 | 537 |
531 // Main decoding loop | 538 // Main decoding loop |
532 static VP8StatusCode IDecode(WebPIDecoder* idec) { | 539 static VP8StatusCode IDecode(WebPIDecoder* idec) { |
533 VP8StatusCode status = VP8_STATUS_SUSPENDED; | 540 VP8StatusCode status = VP8_STATUS_SUSPENDED; |
534 | 541 |
535 if (idec->state_ == STATE_PRE_VP8) { | 542 if (idec->state_ == STATE_WEBP_HEADER) { |
536 status = DecodeWebPHeaders(idec); | 543 status = DecodeWebPHeaders(idec); |
537 } else { | 544 } else { |
538 if (idec->dec_ == NULL) { | 545 if (idec->dec_ == NULL) { |
539 return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. | 546 return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. |
540 } | 547 } |
541 } | 548 } |
542 if (idec->state_ == STATE_VP8_FRAME_HEADER) { | 549 if (idec->state_ == STATE_VP8_HEADER) { |
543 status = DecodeVP8FrameHeader(idec); | 550 status = DecodeVP8FrameHeader(idec); |
544 } | 551 } |
545 if (idec->state_ == STATE_VP8_PARTS0) { | 552 if (idec->state_ == STATE_VP8_PARTS0) { |
546 status = DecodePartition0(idec); | 553 status = DecodePartition0(idec); |
547 } | 554 } |
548 if (idec->state_ == STATE_VP8_DATA) { | 555 if (idec->state_ == STATE_VP8_DATA) { |
549 status = DecodeRemaining(idec); | 556 status = DecodeRemaining(idec); |
550 } | 557 } |
551 if (idec->state_ == STATE_VP8L_HEADER) { | 558 if (idec->state_ == STATE_VP8L_HEADER) { |
552 status = DecodeVP8LHeader(idec); | 559 status = DecodeVP8LHeader(idec); |
553 } | 560 } |
554 if (idec->state_ == STATE_VP8L_DATA) { | 561 if (idec->state_ == STATE_VP8L_DATA) { |
555 status = DecodeVP8LData(idec); | 562 status = DecodeVP8LData(idec); |
556 } | 563 } |
557 return status; | 564 return status; |
558 } | 565 } |
559 | 566 |
560 //------------------------------------------------------------------------------ | 567 //------------------------------------------------------------------------------ |
561 // Public functions | 568 // Public functions |
562 | 569 |
563 WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { | 570 WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { |
564 WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec)); | 571 WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec)); |
565 if (idec == NULL) { | 572 if (idec == NULL) { |
566 return NULL; | 573 return NULL; |
567 } | 574 } |
568 | 575 |
569 idec->state_ = STATE_PRE_VP8; | 576 idec->state_ = STATE_WEBP_HEADER; |
570 idec->chunk_size_ = 0; | 577 idec->chunk_size_ = 0; |
571 | 578 |
572 InitMemBuffer(&idec->mem_); | 579 InitMemBuffer(&idec->mem_); |
573 WebPInitDecBuffer(&idec->output_); | 580 WebPInitDecBuffer(&idec->output_); |
574 VP8InitIo(&idec->io_); | 581 VP8InitIo(&idec->io_); |
575 | 582 |
576 WebPResetDecParams(&idec->params_); | 583 WebPResetDecParams(&idec->params_); |
577 idec->params_.output = output_buffer ? output_buffer : &idec->output_; | 584 idec->params_.output = (output_buffer != NULL) ? output_buffer |
| 585 : &idec->output_; |
578 WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. | 586 WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. |
579 | 587 |
580 return idec; | 588 return idec; |
581 } | 589 } |
582 | 590 |
583 WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, | 591 WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, |
584 WebPDecoderConfig* config) { | 592 WebPDecoderConfig* config) { |
585 WebPIDecoder* idec; | 593 WebPIDecoder* idec; |
586 | 594 |
587 // Parse the bitstream's features, if requested: | 595 // Parse the bitstream's features, if requested: |
(...skipping 13 matching lines...) Expand all Loading... |
601 } | 609 } |
602 return idec; | 610 return idec; |
603 } | 611 } |
604 | 612 |
605 void WebPIDelete(WebPIDecoder* idec) { | 613 void WebPIDelete(WebPIDecoder* idec) { |
606 if (idec == NULL) return; | 614 if (idec == NULL) return; |
607 if (idec->dec_ != NULL) { | 615 if (idec->dec_ != NULL) { |
608 if (!idec->is_lossless_) { | 616 if (!idec->is_lossless_) { |
609 if (idec->state_ == STATE_VP8_DATA) { | 617 if (idec->state_ == STATE_VP8_DATA) { |
610 // Synchronize the thread, clean-up and check for errors. | 618 // Synchronize the thread, clean-up and check for errors. |
611 VP8ExitCritical(idec->dec_, &idec->io_); | 619 VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); |
612 } | 620 } |
613 VP8Delete(idec->dec_); | 621 VP8Delete((VP8Decoder*)idec->dec_); |
614 } else { | 622 } else { |
615 VP8LDelete(idec->dec_); | 623 VP8LDelete((VP8LDecoder*)idec->dec_); |
616 } | 624 } |
617 } | 625 } |
618 ClearMemBuffer(&idec->mem_); | 626 ClearMemBuffer(&idec->mem_); |
619 WebPFreeDecBuffer(&idec->output_); | 627 WebPFreeDecBuffer(&idec->output_); |
620 free(idec); | 628 free(idec); |
621 } | 629 } |
622 | 630 |
623 //------------------------------------------------------------------------------ | 631 //------------------------------------------------------------------------------ |
624 // Wrapper toward WebPINewDecoder | 632 // Wrapper toward WebPINewDecoder |
625 | 633 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; | 828 if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; |
821 | 829 |
822 return src->u.YUVA.y; | 830 return src->u.YUVA.y; |
823 } | 831 } |
824 | 832 |
825 int WebPISetIOHooks(WebPIDecoder* const idec, | 833 int WebPISetIOHooks(WebPIDecoder* const idec, |
826 VP8IoPutHook put, | 834 VP8IoPutHook put, |
827 VP8IoSetupHook setup, | 835 VP8IoSetupHook setup, |
828 VP8IoTeardownHook teardown, | 836 VP8IoTeardownHook teardown, |
829 void* user_data) { | 837 void* user_data) { |
830 if (idec == NULL || idec->state_ > STATE_PRE_VP8) { | 838 if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) { |
831 return 0; | 839 return 0; |
832 } | 840 } |
833 | 841 |
834 idec->io_.put = put; | 842 idec->io_.put = put; |
835 idec->io_.setup = setup; | 843 idec->io_.setup = setup; |
836 idec->io_.teardown = teardown; | 844 idec->io_.teardown = teardown; |
837 idec->io_.opaque = user_data; | 845 idec->io_.opaque = user_data; |
838 | 846 |
839 return 1; | 847 return 1; |
840 } | 848 } |
841 | 849 |
842 #if defined(__cplusplus) || defined(c_plusplus) | |
843 } // extern "C" | |
844 #endif | |
OLD | NEW |