Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: third_party/libwebp/dec/idec.c

Issue 116213006: Update libwebp to 0.4.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: After Blink Roll Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/dec/frame.c ('k') | third_party/libwebp/dec/io.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/libwebp/dec/frame.c ('k') | third_party/libwebp/dec/io.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698