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 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 int p; | 123 int p; |
124 for (p = 0; p <= last_part; ++p) { | 124 for (p = 0; p <= last_part; ++p) { |
125 VP8RemapBitReader(dec->parts_ + p, offset); | 125 VP8RemapBitReader(dec->parts_ + p, offset); |
126 } | 126 } |
127 // Remap partition #0 data pointer to new offset, but only in MAP | 127 // Remap partition #0 data pointer to new offset, but only in MAP |
128 // mode (in APPEND mode, partition #0 is copied into a fixed memory). | 128 // mode (in APPEND mode, partition #0 is copied into a fixed memory). |
129 if (mem->mode_ == MEM_MODE_MAP) { | 129 if (mem->mode_ == MEM_MODE_MAP) { |
130 VP8RemapBitReader(&dec->br_, offset); | 130 VP8RemapBitReader(&dec->br_, offset); |
131 } | 131 } |
132 } | 132 } |
133 assert(last_part >= 0); | 133 { |
134 dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; | 134 const uint8_t* const last_start = dec->parts_[last_part].buf_; |
| 135 assert(last_part >= 0); |
| 136 VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start, |
| 137 mem->buf_ + mem->end_ - last_start); |
| 138 } |
135 if (NeedCompressedAlpha(idec)) { | 139 if (NeedCompressedAlpha(idec)) { |
136 ALPHDecoder* const alph_dec = dec->alph_dec_; | 140 ALPHDecoder* const alph_dec = dec->alph_dec_; |
137 dec->alpha_data_ += offset; | 141 dec->alpha_data_ += offset; |
138 if (alph_dec != NULL) { | 142 if (alph_dec != NULL) { |
139 if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { | 143 if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { |
140 VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; | 144 VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; |
141 assert(alph_vp8l_dec != NULL); | 145 assert(alph_vp8l_dec != NULL); |
142 assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); | 146 assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); |
143 VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, | 147 VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, |
144 dec->alpha_data_ + ALPHA_HEADER_LEN, | 148 dec->alpha_data_ + ALPHA_HEADER_LEN, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 mem->mode_ = expected; // switch to the expected mode | 237 mem->mode_ = expected; // switch to the expected mode |
234 } else if (mem->mode_ != expected) { | 238 } else if (mem->mode_ != expected) { |
235 return 0; // we mixed the modes => error | 239 return 0; // we mixed the modes => error |
236 } | 240 } |
237 assert(mem->mode_ == expected); // mode is ok | 241 assert(mem->mode_ == expected); // mode is ok |
238 return 1; | 242 return 1; |
239 } | 243 } |
240 | 244 |
241 // To be called last. | 245 // To be called last. |
242 static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { | 246 static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { |
243 #if WEBP_DECODER_ABI_VERSION > 0x0203 | |
244 const WebPDecoderOptions* const options = idec->params_.options; | 247 const WebPDecoderOptions* const options = idec->params_.options; |
245 WebPDecBuffer* const output = idec->params_.output; | 248 WebPDecBuffer* const output = idec->params_.output; |
246 | 249 |
247 idec->state_ = STATE_DONE; | 250 idec->state_ = STATE_DONE; |
248 if (options != NULL && options->flip) { | 251 if (options != NULL && options->flip) { |
249 return WebPFlipBuffer(output); | 252 return WebPFlipBuffer(output); |
| 253 } else { |
| 254 return VP8_STATUS_OK; |
250 } | 255 } |
251 #endif | |
252 idec->state_ = STATE_DONE; | |
253 return VP8_STATUS_OK; | |
254 } | 256 } |
255 | 257 |
256 //------------------------------------------------------------------------------ | 258 //------------------------------------------------------------------------------ |
257 // Macroblock-decoding contexts | 259 // Macroblock-decoding contexts |
258 | 260 |
259 static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, | 261 static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, |
260 MBContext* const context) { | 262 MBContext* const context) { |
261 context->left_ = dec->mb_info_[-1]; | 263 context->left_ = dec->mb_info_[-1]; |
262 context->info_ = dec->mb_info_[dec->mb_x_]; | 264 context->info_ = dec->mb_info_[dec->mb_x_]; |
263 context->token_br_ = *token_br; | 265 context->token_br_ = *token_br; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 return VP8_STATUS_BITSTREAM_ERROR; | 372 return VP8_STATUS_BITSTREAM_ERROR; |
371 } | 373 } |
372 if (mem->mode_ == MEM_MODE_APPEND) { | 374 if (mem->mode_ == MEM_MODE_APPEND) { |
373 // We copy and grab ownership of the partition #0 data. | 375 // We copy and grab ownership of the partition #0 data. |
374 uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); | 376 uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); |
375 if (part0_buf == NULL) { | 377 if (part0_buf == NULL) { |
376 return VP8_STATUS_OUT_OF_MEMORY; | 378 return VP8_STATUS_OUT_OF_MEMORY; |
377 } | 379 } |
378 memcpy(part0_buf, br->buf_, part_size); | 380 memcpy(part0_buf, br->buf_, part_size); |
379 mem->part0_buf_ = part0_buf; | 381 mem->part0_buf_ = part0_buf; |
380 br->buf_ = part0_buf; | 382 VP8BitReaderSetBuffer(br, part0_buf, part_size); |
381 br->buf_end_ = part0_buf + part_size; | |
382 } else { | 383 } else { |
383 // Else: just keep pointers to the partition #0's data in dec_->br_. | 384 // Else: just keep pointers to the partition #0's data in dec_->br_. |
384 } | 385 } |
385 mem->start_ += part_size; | 386 mem->start_ += part_size; |
386 return VP8_STATUS_OK; | 387 return VP8_STATUS_OK; |
387 } | 388 } |
388 | 389 |
389 static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { | 390 static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { |
390 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; | 391 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
391 VP8Io* const io = &idec->io_; | 392 VP8Io* const io = &idec->io_; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { | 500 static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { |
500 VP8Io* const io = &idec->io_; | 501 VP8Io* const io = &idec->io_; |
501 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; | 502 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; |
502 const WebPDecParams* const params = &idec->params_; | 503 const WebPDecParams* const params = &idec->params_; |
503 WebPDecBuffer* const output = params->output; | 504 WebPDecBuffer* const output = params->output; |
504 size_t curr_size = MemDataSize(&idec->mem_); | 505 size_t curr_size = MemDataSize(&idec->mem_); |
505 assert(idec->is_lossless_); | 506 assert(idec->is_lossless_); |
506 | 507 |
507 // Wait until there's enough data for decoding header. | 508 // Wait until there's enough data for decoding header. |
508 if (curr_size < (idec->chunk_size_ >> 3)) { | 509 if (curr_size < (idec->chunk_size_ >> 3)) { |
509 return VP8_STATUS_SUSPENDED; | 510 dec->status_ = VP8_STATUS_SUSPENDED; |
| 511 return ErrorStatusLossless(idec, dec->status_); |
510 } | 512 } |
| 513 |
511 if (!VP8LDecodeHeader(dec, io)) { | 514 if (!VP8LDecodeHeader(dec, io)) { |
| 515 if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && |
| 516 curr_size < idec->chunk_size_) { |
| 517 dec->status_ = VP8_STATUS_SUSPENDED; |
| 518 } |
512 return ErrorStatusLossless(idec, dec->status_); | 519 return ErrorStatusLossless(idec, dec->status_); |
513 } | 520 } |
514 // Allocate/verify output buffer now. | 521 // Allocate/verify output buffer now. |
515 dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, | 522 dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, |
516 output); | 523 output); |
517 if (dec->status_ != VP8_STATUS_OK) { | 524 if (dec->status_ != VP8_STATUS_OK) { |
518 return IDecError(idec, dec->status_); | 525 return IDecError(idec, dec->status_); |
519 } | 526 } |
520 | 527 |
521 idec->state_ = STATE_VP8L_DATA; | 528 idec->state_ = STATE_VP8L_DATA; |
522 return VP8_STATUS_OK; | 529 return VP8_STATUS_OK; |
523 } | 530 } |
524 | 531 |
525 static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { | 532 static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { |
526 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; | 533 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; |
527 const size_t curr_size = MemDataSize(&idec->mem_); | 534 const size_t curr_size = MemDataSize(&idec->mem_); |
528 assert(idec->is_lossless_); | 535 assert(idec->is_lossless_); |
529 | 536 |
530 // At present Lossless decoder can't decode image incrementally. So wait till | 537 // Switch to incremental decoding if we don't have all the bytes available. |
531 // all the image data is aggregated before image can be decoded. | 538 dec->incremental_ = (curr_size < idec->chunk_size_); |
532 if (curr_size < idec->chunk_size_) { | |
533 return VP8_STATUS_SUSPENDED; | |
534 } | |
535 | 539 |
536 if (!VP8LDecodeImage(dec)) { | 540 if (!VP8LDecodeImage(dec)) { |
537 // The decoding is called after all the data-bytes are aggregated. Change | |
538 // the error to VP8_BITSTREAM_ERROR in case lossless decoder fails to decode | |
539 // all the pixels (VP8_STATUS_SUSPENDED). | |
540 if (dec->status_ == VP8_STATUS_SUSPENDED) { | |
541 dec->status_ = VP8_STATUS_BITSTREAM_ERROR; | |
542 } | |
543 return ErrorStatusLossless(idec, dec->status_); | 541 return ErrorStatusLossless(idec, dec->status_); |
544 } | 542 } |
545 | 543 assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED); |
546 return FinishDecoding(idec); | 544 return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_ |
| 545 : FinishDecoding(idec); |
547 } | 546 } |
548 | 547 |
549 // Main decoding loop | 548 // Main decoding loop |
550 static VP8StatusCode IDecode(WebPIDecoder* idec) { | 549 static VP8StatusCode IDecode(WebPIDecoder* idec) { |
551 VP8StatusCode status = VP8_STATUS_SUSPENDED; | 550 VP8StatusCode status = VP8_STATUS_SUSPENDED; |
552 | 551 |
553 if (idec->state_ == STATE_WEBP_HEADER) { | 552 if (idec->state_ == STATE_WEBP_HEADER) { |
554 status = DecodeWebPHeaders(idec); | 553 status = DecodeWebPHeaders(idec); |
555 } else { | 554 } else { |
556 if (idec->dec_ == NULL) { | 555 if (idec->dec_ == NULL) { |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 } | 785 } |
787 return idec->params_.output; | 786 return idec->params_.output; |
788 } | 787 } |
789 | 788 |
790 const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, | 789 const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, |
791 int* left, int* top, | 790 int* left, int* top, |
792 int* width, int* height) { | 791 int* width, int* height) { |
793 const WebPDecBuffer* const src = GetOutputBuffer(idec); | 792 const WebPDecBuffer* const src = GetOutputBuffer(idec); |
794 if (left != NULL) *left = 0; | 793 if (left != NULL) *left = 0; |
795 if (top != NULL) *top = 0; | 794 if (top != NULL) *top = 0; |
796 // TODO(skal): later include handling of rotations. | |
797 if (src) { | 795 if (src) { |
798 if (width != NULL) *width = src->width; | 796 if (width != NULL) *width = src->width; |
799 if (height != NULL) *height = idec->params_.last_y; | 797 if (height != NULL) *height = idec->params_.last_y; |
800 } else { | 798 } else { |
801 if (width != NULL) *width = 0; | 799 if (width != NULL) *width = 0; |
802 if (height != NULL) *height = 0; | 800 if (height != NULL) *height = 0; |
803 } | 801 } |
804 return src; | 802 return src; |
805 } | 803 } |
806 | 804 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
852 return 0; | 850 return 0; |
853 } | 851 } |
854 | 852 |
855 idec->io_.put = put; | 853 idec->io_.put = put; |
856 idec->io_.setup = setup; | 854 idec->io_.setup = setup; |
857 idec->io_.teardown = teardown; | 855 idec->io_.teardown = teardown; |
858 idec->io_.opaque = user_data; | 856 idec->io_.opaque = user_data; |
859 | 857 |
860 return 1; | 858 return 1; |
861 } | 859 } |
862 | |
OLD | NEW |