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

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

Issue 2149863002: libwebp: update to v0.5.1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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
« 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
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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 }
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