| 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 } MemBuffer; | 63 } MemBuffer; |
| 64 | 64 |
| 65 struct WebPIDecoder { | 65 struct WebPIDecoder { |
| 66 DecState state_; // current decoding state | 66 DecState state_; // current decoding state |
| 67 WebPDecParams params_; // Params to store output info | 67 WebPDecParams params_; // Params to store output info |
| 68 int is_lossless_; // for down-casting 'dec_'. | 68 int is_lossless_; // for down-casting 'dec_'. |
| 69 void* dec_; // either a VP8Decoder or a VP8LDecoder instance | 69 void* dec_; // either a VP8Decoder or a VP8LDecoder instance |
| 70 VP8Io io_; | 70 VP8Io io_; |
| 71 | 71 |
| 72 MemBuffer mem_; // input memory buffer. | 72 MemBuffer mem_; // input memory buffer. |
| 73 WebPDecBuffer output_; // output buffer (when no external one is supplied) | 73 WebPDecBuffer output_; // output buffer (when no external one is supplied, |
| 74 // or if the external one has slow-memory) |
| 75 WebPDecBuffer* final_output_; // Slow-memory output to copy to eventually. |
| 74 size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. | 76 size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. |
| 75 | 77 |
| 76 int last_mb_y_; // last row reached for intra-mode decoding | 78 int last_mb_y_; // last row reached for intra-mode decoding |
| 77 }; | 79 }; |
| 78 | 80 |
| 79 // MB context to restore in case VP8DecodeMB() fails | 81 // MB context to restore in case VP8DecodeMB() fails |
| 80 typedef struct { | 82 typedef struct { |
| 81 VP8MB left_; | 83 VP8MB left_; |
| 82 VP8MB info_; | 84 VP8MB info_; |
| 83 VP8BitReader token_br_; | 85 VP8BitReader token_br_; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 111 MemBuffer* const mem = &idec->mem_; | 113 MemBuffer* const mem = &idec->mem_; |
| 112 const uint8_t* const new_base = mem->buf_ + mem->start_; | 114 const uint8_t* const new_base = mem->buf_ + mem->start_; |
| 113 // note: for VP8, setting up idec->io_ is only really needed at the beginning | 115 // note: for VP8, setting up idec->io_ is only really needed at the beginning |
| 114 // of the decoding, till partition #0 is complete. | 116 // of the decoding, till partition #0 is complete. |
| 115 idec->io_.data = new_base; | 117 idec->io_.data = new_base; |
| 116 idec->io_.data_size = MemDataSize(mem); | 118 idec->io_.data_size = MemDataSize(mem); |
| 117 | 119 |
| 118 if (idec->dec_ != NULL) { | 120 if (idec->dec_ != NULL) { |
| 119 if (!idec->is_lossless_) { | 121 if (!idec->is_lossless_) { |
| 120 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; | 122 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
| 121 const int last_part = dec->num_parts_ - 1; | 123 const uint32_t last_part = dec->num_parts_minus_one_; |
| 122 if (offset != 0) { | 124 if (offset != 0) { |
| 123 int p; | 125 uint32_t p; |
| 124 for (p = 0; p <= last_part; ++p) { | 126 for (p = 0; p <= last_part; ++p) { |
| 125 VP8RemapBitReader(dec->parts_ + p, offset); | 127 VP8RemapBitReader(dec->parts_ + p, offset); |
| 126 } | 128 } |
| 127 // Remap partition #0 data pointer to new offset, but only in MAP | 129 // 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). | 130 // mode (in APPEND mode, partition #0 is copied into a fixed memory). |
| 129 if (mem->mode_ == MEM_MODE_MAP) { | 131 if (mem->mode_ == MEM_MODE_MAP) { |
| 130 VP8RemapBitReader(&dec->br_, offset); | 132 VP8RemapBitReader(&dec->br_, offset); |
| 131 } | 133 } |
| 132 } | 134 } |
| 133 { | 135 { |
| 134 const uint8_t* const last_start = dec->parts_[last_part].buf_; | 136 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 VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start, |
| 137 mem->buf_ + mem->end_ - last_start); | 138 mem->buf_ + mem->end_ - last_start); |
| 138 } | 139 } |
| 139 if (NeedCompressedAlpha(idec)) { | 140 if (NeedCompressedAlpha(idec)) { |
| 140 ALPHDecoder* const alph_dec = dec->alph_dec_; | 141 ALPHDecoder* const alph_dec = dec->alph_dec_; |
| 141 dec->alpha_data_ += offset; | 142 dec->alpha_data_ += offset; |
| 142 if (alph_dec != NULL) { | 143 if (alph_dec != NULL) { |
| 143 if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { | 144 if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { |
| 144 VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; | 145 VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; |
| 145 assert(alph_vp8l_dec != NULL); | 146 assert(alph_vp8l_dec != NULL); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 return 1; | 243 return 1; |
| 243 } | 244 } |
| 244 | 245 |
| 245 // To be called last. | 246 // To be called last. |
| 246 static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { | 247 static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { |
| 247 const WebPDecoderOptions* const options = idec->params_.options; | 248 const WebPDecoderOptions* const options = idec->params_.options; |
| 248 WebPDecBuffer* const output = idec->params_.output; | 249 WebPDecBuffer* const output = idec->params_.output; |
| 249 | 250 |
| 250 idec->state_ = STATE_DONE; | 251 idec->state_ = STATE_DONE; |
| 251 if (options != NULL && options->flip) { | 252 if (options != NULL && options->flip) { |
| 252 return WebPFlipBuffer(output); | 253 const VP8StatusCode status = WebPFlipBuffer(output); |
| 253 } else { | 254 if (status != VP8_STATUS_OK) return status; |
| 254 return VP8_STATUS_OK; | |
| 255 } | 255 } |
| 256 if (idec->final_output_ != NULL) { |
| 257 WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy |
| 258 WebPFreeDecBuffer(&idec->output_); |
| 259 *output = *idec->final_output_; |
| 260 idec->final_output_ = NULL; |
| 261 } |
| 262 return VP8_STATUS_OK; |
| 256 } | 263 } |
| 257 | 264 |
| 258 //------------------------------------------------------------------------------ | 265 //------------------------------------------------------------------------------ |
| 259 // Macroblock-decoding contexts | 266 // Macroblock-decoding contexts |
| 260 | 267 |
| 261 static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, | 268 static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, |
| 262 MBContext* const context) { | 269 MBContext* const context) { |
| 263 context->left_ = dec->mb_info_[-1]; | 270 context->left_ = dec->mb_info_[-1]; |
| 264 context->info_ = dec->mb_info_[dec->mb_x_]; | 271 context->info_ = dec->mb_info_[dec->mb_x_]; |
| 265 context->token_br_ = *token_br; | 272 context->token_br_ = *token_br; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 if (!VP8ParseIntraModeRow(&dec->br_, dec)) { | 457 if (!VP8ParseIntraModeRow(&dec->br_, dec)) { |
| 451 // note: normally, error shouldn't occur since we already have the whole | 458 // note: normally, error shouldn't occur since we already have the whole |
| 452 // partition0 available here in DecodeRemaining(). Reaching EOF while | 459 // partition0 available here in DecodeRemaining(). Reaching EOF while |
| 453 // reading intra modes really means a BITSTREAM_ERROR. | 460 // reading intra modes really means a BITSTREAM_ERROR. |
| 454 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); | 461 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); |
| 455 } | 462 } |
| 456 idec->last_mb_y_ = dec->mb_y_; | 463 idec->last_mb_y_ = dec->mb_y_; |
| 457 } | 464 } |
| 458 for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { | 465 for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { |
| 459 VP8BitReader* const token_br = | 466 VP8BitReader* const token_br = |
| 460 &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; | 467 &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_]; |
| 461 MBContext context; | 468 MBContext context; |
| 462 SaveContext(dec, token_br, &context); | 469 SaveContext(dec, token_br, &context); |
| 463 if (!VP8DecodeMB(dec, token_br)) { | 470 if (!VP8DecodeMB(dec, token_br)) { |
| 464 // We shouldn't fail when MAX_MB data was available | 471 // We shouldn't fail when MAX_MB data was available |
| 465 if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) { | 472 if (dec->num_parts_minus_one_ == 0 && |
| 473 MemDataSize(&idec->mem_) > MAX_MB_SIZE) { |
| 466 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); | 474 return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); |
| 467 } | 475 } |
| 468 RestoreContext(&context, dec, token_br); | 476 RestoreContext(&context, dec, token_br); |
| 469 return VP8_STATUS_SUSPENDED; | 477 return VP8_STATUS_SUSPENDED; |
| 470 } | 478 } |
| 471 // Release buffer only if there is only one partition | 479 // Release buffer only if there is only one partition |
| 472 if (dec->num_parts_ == 1) { | 480 if (dec->num_parts_minus_one_ == 0) { |
| 473 idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; | 481 idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; |
| 474 assert(idec->mem_.start_ <= idec->mem_.end_); | 482 assert(idec->mem_.start_ <= idec->mem_.end_); |
| 475 } | 483 } |
| 476 } | 484 } |
| 477 VP8InitScanline(dec); // Prepare for next scanline | 485 VP8InitScanline(dec); // Prepare for next scanline |
| 478 | 486 |
| 479 // Reconstruct, filter and emit the row. | 487 // Reconstruct, filter and emit the row. |
| 480 if (!VP8ProcessRow(dec, io)) { | 488 if (!VP8ProcessRow(dec, io)) { |
| 481 return IDecError(idec, VP8_STATUS_USER_ABORT); | 489 return IDecError(idec, VP8_STATUS_USER_ABORT); |
| 482 } | 490 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 if (idec->state_ == STATE_VP8L_HEADER) { | 576 if (idec->state_ == STATE_VP8L_HEADER) { |
| 569 status = DecodeVP8LHeader(idec); | 577 status = DecodeVP8LHeader(idec); |
| 570 } | 578 } |
| 571 if (idec->state_ == STATE_VP8L_DATA) { | 579 if (idec->state_ == STATE_VP8L_DATA) { |
| 572 status = DecodeVP8LData(idec); | 580 status = DecodeVP8LData(idec); |
| 573 } | 581 } |
| 574 return status; | 582 return status; |
| 575 } | 583 } |
| 576 | 584 |
| 577 //------------------------------------------------------------------------------ | 585 //------------------------------------------------------------------------------ |
| 578 // Public functions | 586 // Internal constructor |
| 579 | 587 |
| 580 WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { | 588 static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer, |
| 589 const WebPBitstreamFeatures* const features) { |
| 581 WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); | 590 WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); |
| 582 if (idec == NULL) { | 591 if (idec == NULL) { |
| 583 return NULL; | 592 return NULL; |
| 584 } | 593 } |
| 585 | 594 |
| 586 idec->state_ = STATE_WEBP_HEADER; | 595 idec->state_ = STATE_WEBP_HEADER; |
| 587 idec->chunk_size_ = 0; | 596 idec->chunk_size_ = 0; |
| 588 | 597 |
| 589 idec->last_mb_y_ = -1; | 598 idec->last_mb_y_ = -1; |
| 590 | 599 |
| 591 InitMemBuffer(&idec->mem_); | 600 InitMemBuffer(&idec->mem_); |
| 592 WebPInitDecBuffer(&idec->output_); | 601 WebPInitDecBuffer(&idec->output_); |
| 593 VP8InitIo(&idec->io_); | 602 VP8InitIo(&idec->io_); |
| 594 | 603 |
| 595 WebPResetDecParams(&idec->params_); | 604 WebPResetDecParams(&idec->params_); |
| 596 idec->params_.output = (output_buffer != NULL) ? output_buffer | 605 if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) { |
| 597 : &idec->output_; | 606 idec->params_.output = &idec->output_; |
| 607 idec->final_output_ = output_buffer; |
| 608 if (output_buffer != NULL) { |
| 609 idec->params_.output->colorspace = output_buffer->colorspace; |
| 610 } |
| 611 } else { |
| 612 idec->params_.output = output_buffer; |
| 613 idec->final_output_ = NULL; |
| 614 } |
| 598 WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. | 615 WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. |
| 599 | 616 |
| 600 return idec; | 617 return idec; |
| 601 } | 618 } |
| 602 | 619 |
| 620 //------------------------------------------------------------------------------ |
| 621 // Public functions |
| 622 |
| 623 WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { |
| 624 return NewDecoder(output_buffer, NULL); |
| 625 } |
| 626 |
| 603 WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, | 627 WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, |
| 604 WebPDecoderConfig* config) { | 628 WebPDecoderConfig* config) { |
| 605 WebPIDecoder* idec; | 629 WebPIDecoder* idec; |
| 630 WebPBitstreamFeatures tmp_features; |
| 631 WebPBitstreamFeatures* const features = |
| 632 (config == NULL) ? &tmp_features : &config->input; |
| 633 memset(&tmp_features, 0, sizeof(tmp_features)); |
| 606 | 634 |
| 607 // Parse the bitstream's features, if requested: | 635 // Parse the bitstream's features, if requested: |
| 608 if (data != NULL && data_size > 0 && config != NULL) { | 636 if (data != NULL && data_size > 0) { |
| 609 if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) { | 637 if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) { |
| 610 return NULL; | 638 return NULL; |
| 611 } | 639 } |
| 612 } | 640 } |
| 641 |
| 613 // Create an instance of the incremental decoder | 642 // Create an instance of the incremental decoder |
| 614 idec = WebPINewDecoder(config ? &config->output : NULL); | 643 idec = (config != NULL) ? NewDecoder(&config->output, features) |
| 644 : NewDecoder(NULL, features); |
| 615 if (idec == NULL) { | 645 if (idec == NULL) { |
| 616 return NULL; | 646 return NULL; |
| 617 } | 647 } |
| 618 // Finish initialization | 648 // Finish initialization |
| 619 if (config != NULL) { | 649 if (config != NULL) { |
| 620 idec->params_.options = &config->options; | 650 idec->params_.options = &config->options; |
| 621 } | 651 } |
| 622 return idec; | 652 return idec; |
| 623 } | 653 } |
| 624 | 654 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 638 ClearMemBuffer(&idec->mem_); | 668 ClearMemBuffer(&idec->mem_); |
| 639 WebPFreeDecBuffer(&idec->output_); | 669 WebPFreeDecBuffer(&idec->output_); |
| 640 WebPSafeFree(idec); | 670 WebPSafeFree(idec); |
| 641 } | 671 } |
| 642 | 672 |
| 643 //------------------------------------------------------------------------------ | 673 //------------------------------------------------------------------------------ |
| 644 // Wrapper toward WebPINewDecoder | 674 // Wrapper toward WebPINewDecoder |
| 645 | 675 |
| 646 WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, | 676 WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, |
| 647 size_t output_buffer_size, int output_stride) { | 677 size_t output_buffer_size, int output_stride) { |
| 648 const int is_external_memory = (output_buffer != NULL); | 678 const int is_external_memory = (output_buffer != NULL) ? 1 : 0; |
| 649 WebPIDecoder* idec; | 679 WebPIDecoder* idec; |
| 650 | 680 |
| 651 if (mode >= MODE_YUV) return NULL; | 681 if (mode >= MODE_YUV) return NULL; |
| 652 if (!is_external_memory) { // Overwrite parameters to sane values. | 682 if (is_external_memory == 0) { // Overwrite parameters to sane values. |
| 653 output_buffer_size = 0; | 683 output_buffer_size = 0; |
| 654 output_stride = 0; | 684 output_stride = 0; |
| 655 } else { // A buffer was passed. Validate the other params. | 685 } else { // A buffer was passed. Validate the other params. |
| 656 if (output_stride == 0 || output_buffer_size == 0) { | 686 if (output_stride == 0 || output_buffer_size == 0) { |
| 657 return NULL; // invalid parameter. | 687 return NULL; // invalid parameter. |
| 658 } | 688 } |
| 659 } | 689 } |
| 660 idec = WebPINewDecoder(NULL); | 690 idec = WebPINewDecoder(NULL); |
| 661 if (idec == NULL) return NULL; | 691 if (idec == NULL) return NULL; |
| 662 idec->output_.colorspace = mode; | 692 idec->output_.colorspace = mode; |
| 663 idec->output_.is_external_memory = is_external_memory; | 693 idec->output_.is_external_memory = is_external_memory; |
| 664 idec->output_.u.RGBA.rgba = output_buffer; | 694 idec->output_.u.RGBA.rgba = output_buffer; |
| 665 idec->output_.u.RGBA.stride = output_stride; | 695 idec->output_.u.RGBA.stride = output_stride; |
| 666 idec->output_.u.RGBA.size = output_buffer_size; | 696 idec->output_.u.RGBA.size = output_buffer_size; |
| 667 return idec; | 697 return idec; |
| 668 } | 698 } |
| 669 | 699 |
| 670 WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, | 700 WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, |
| 671 uint8_t* u, size_t u_size, int u_stride, | 701 uint8_t* u, size_t u_size, int u_stride, |
| 672 uint8_t* v, size_t v_size, int v_stride, | 702 uint8_t* v, size_t v_size, int v_stride, |
| 673 uint8_t* a, size_t a_size, int a_stride) { | 703 uint8_t* a, size_t a_size, int a_stride) { |
| 674 const int is_external_memory = (luma != NULL); | 704 const int is_external_memory = (luma != NULL) ? 1 : 0; |
| 675 WebPIDecoder* idec; | 705 WebPIDecoder* idec; |
| 676 WEBP_CSP_MODE colorspace; | 706 WEBP_CSP_MODE colorspace; |
| 677 | 707 |
| 678 if (!is_external_memory) { // Overwrite parameters to sane values. | 708 if (is_external_memory == 0) { // Overwrite parameters to sane values. |
| 679 luma_size = u_size = v_size = a_size = 0; | 709 luma_size = u_size = v_size = a_size = 0; |
| 680 luma_stride = u_stride = v_stride = a_stride = 0; | 710 luma_stride = u_stride = v_stride = a_stride = 0; |
| 681 u = v = a = NULL; | 711 u = v = a = NULL; |
| 682 colorspace = MODE_YUVA; | 712 colorspace = MODE_YUVA; |
| 683 } else { // A luma buffer was passed. Validate the other parameters. | 713 } else { // A luma buffer was passed. Validate the other parameters. |
| 684 if (u == NULL || v == NULL) return NULL; | 714 if (u == NULL || v == NULL) return NULL; |
| 685 if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; | 715 if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; |
| 686 if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; | 716 if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; |
| 687 if (a != NULL) { | 717 if (a != NULL) { |
| 688 if (a_size == 0 || a_stride == 0) return NULL; | 718 if (a_size == 0 || a_stride == 0) return NULL; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 | 806 |
| 777 //------------------------------------------------------------------------------ | 807 //------------------------------------------------------------------------------ |
| 778 | 808 |
| 779 static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { | 809 static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { |
| 780 if (idec == NULL || idec->dec_ == NULL) { | 810 if (idec == NULL || idec->dec_ == NULL) { |
| 781 return NULL; | 811 return NULL; |
| 782 } | 812 } |
| 783 if (idec->state_ <= STATE_VP8_PARTS0) { | 813 if (idec->state_ <= STATE_VP8_PARTS0) { |
| 784 return NULL; | 814 return NULL; |
| 785 } | 815 } |
| 816 if (idec->final_output_ != NULL) { |
| 817 return NULL; // not yet slow-copied |
| 818 } |
| 786 return idec->params_.output; | 819 return idec->params_.output; |
| 787 } | 820 } |
| 788 | 821 |
| 789 const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, | 822 const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, |
| 790 int* left, int* top, | 823 int* left, int* top, |
| 791 int* width, int* height) { | 824 int* width, int* height) { |
| 792 const WebPDecBuffer* const src = GetOutputBuffer(idec); | 825 const WebPDecBuffer* const src = GetOutputBuffer(idec); |
| 793 if (left != NULL) *left = 0; | 826 if (left != NULL) *left = 0; |
| 794 if (top != NULL) *top = 0; | 827 if (top != NULL) *top = 0; |
| 795 if (src) { | 828 if (src != NULL) { |
| 796 if (width != NULL) *width = src->width; | 829 if (width != NULL) *width = src->width; |
| 797 if (height != NULL) *height = idec->params_.last_y; | 830 if (height != NULL) *height = idec->params_.last_y; |
| 798 } else { | 831 } else { |
| 799 if (width != NULL) *width = 0; | 832 if (width != NULL) *width = 0; |
| 800 if (height != NULL) *height = 0; | 833 if (height != NULL) *height = 0; |
| 801 } | 834 } |
| 802 return src; | 835 return src; |
| 803 } | 836 } |
| 804 | 837 |
| 805 uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, | 838 uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 return 0; | 883 return 0; |
| 851 } | 884 } |
| 852 | 885 |
| 853 idec->io_.put = put; | 886 idec->io_.put = put; |
| 854 idec->io_.setup = setup; | 887 idec->io_.setup = setup; |
| 855 idec->io_.teardown = teardown; | 888 idec->io_.teardown = teardown; |
| 856 idec->io_.opaque = user_data; | 889 idec->io_.opaque = user_data; |
| 857 | 890 |
| 858 return 1; | 891 return 1; |
| 859 } | 892 } |
| OLD | NEW |