OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // This code is licensed under the same terms as WebM: | 3 // Use of this source code is governed by a BSD-style license |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // that can be found in the COPYING file in the root of the source |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. |
6 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
7 // | 9 // |
8 // Incremental decoding | 10 // Incremental decoding |
9 // | 11 // |
10 // Author: somnath@google.com (Somnath Banerjee) | 12 // Author: somnath@google.com (Somnath Banerjee) |
11 | 13 |
12 #include <assert.h> | 14 #include <assert.h> |
13 #include <string.h> | 15 #include <string.h> |
14 #include <stdlib.h> | 16 #include <stdlib.h> |
15 | 17 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 if (br->buf_ != NULL) { | 92 if (br->buf_ != NULL) { |
91 br->buf_ += offset; | 93 br->buf_ += offset; |
92 br->buf_end_ += offset; | 94 br->buf_end_ += offset; |
93 } | 95 } |
94 } | 96 } |
95 | 97 |
96 static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { | 98 static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { |
97 return (mem->end_ - mem->start_); | 99 return (mem->end_ - mem->start_); |
98 } | 100 } |
99 | 101 |
| 102 // Check if we need to preserve the compressed alpha data, as it may not have |
| 103 // been decoded yet. |
| 104 static int NeedCompressedAlpha(const WebPIDecoder* const idec) { |
| 105 if (idec->state_ == STATE_PRE_VP8) { |
| 106 // 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. |
| 108 return 0; |
| 109 } |
| 110 if (idec->is_lossless_) { |
| 111 return 0; // ALPH chunk is not present for lossless images. |
| 112 } else { |
| 113 const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
| 114 assert(dec != NULL); // Must be true as idec->state_ != STATE_PRE_VP8. |
| 115 return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; |
| 116 } |
| 117 } |
| 118 |
100 static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { | 119 static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { |
101 MemBuffer* const mem = &idec->mem_; | 120 MemBuffer* const mem = &idec->mem_; |
102 const uint8_t* const new_base = mem->buf_ + mem->start_; | 121 const uint8_t* const new_base = mem->buf_ + mem->start_; |
103 // note: for VP8, setting up idec->io_ is only really needed at the beginning | 122 // note: for VP8, setting up idec->io_ is only really needed at the beginning |
104 // of the decoding, till partition #0 is complete. | 123 // of the decoding, till partition #0 is complete. |
105 idec->io_.data = new_base; | 124 idec->io_.data = new_base; |
106 idec->io_.data_size = MemDataSize(mem); | 125 idec->io_.data_size = MemDataSize(mem); |
107 | 126 |
108 if (idec->dec_ != NULL) { | 127 if (idec->dec_ != NULL) { |
109 if (!idec->is_lossless_) { | 128 if (!idec->is_lossless_) { |
110 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; | 129 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
111 const int last_part = dec->num_parts_ - 1; | 130 const int last_part = dec->num_parts_ - 1; |
112 if (offset != 0) { | 131 if (offset != 0) { |
113 int p; | 132 int p; |
114 for (p = 0; p <= last_part; ++p) { | 133 for (p = 0; p <= last_part; ++p) { |
115 RemapBitReader(dec->parts_ + p, offset); | 134 RemapBitReader(dec->parts_ + p, offset); |
116 } | 135 } |
117 // Remap partition #0 data pointer to new offset, but only in MAP | 136 // Remap partition #0 data pointer to new offset, but only in MAP |
118 // mode (in APPEND mode, partition #0 is copied into a fixed memory). | 137 // mode (in APPEND mode, partition #0 is copied into a fixed memory). |
119 if (mem->mode_ == MEM_MODE_MAP) { | 138 if (mem->mode_ == MEM_MODE_MAP) { |
120 RemapBitReader(&dec->br_, offset); | 139 RemapBitReader(&dec->br_, offset); |
121 } | 140 } |
122 } | 141 } |
123 assert(last_part >= 0); | 142 assert(last_part >= 0); |
124 dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; | 143 dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; |
| 144 if (NeedCompressedAlpha(idec)) dec->alpha_data_ += offset; |
125 } else { // Resize lossless bitreader | 145 } else { // Resize lossless bitreader |
126 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; | 146 VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; |
127 VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); | 147 VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); |
128 } | 148 } |
129 } | 149 } |
130 } | 150 } |
131 | 151 |
132 // Appends data to the end of MemBuffer->buf_. It expands the allocated memory | 152 // Appends data to the end of MemBuffer->buf_. It expands the allocated memory |
133 // size if required and also updates VP8BitReader's if new memory is allocated. | 153 // size if required and also updates VP8BitReader's if new memory is allocated. |
134 static int AppendToMemBuffer(WebPIDecoder* const idec, | 154 static int AppendToMemBuffer(WebPIDecoder* const idec, |
135 const uint8_t* const data, size_t data_size) { | 155 const uint8_t* const data, size_t data_size) { |
| 156 VP8Decoder* const dec = (VP8Decoder*)idec->dec_; |
136 MemBuffer* const mem = &idec->mem_; | 157 MemBuffer* const mem = &idec->mem_; |
137 const uint8_t* const old_base = mem->buf_ + mem->start_; | 158 const int need_compressed_alpha = NeedCompressedAlpha(idec); |
| 159 const uint8_t* const old_start = mem->buf_ + mem->start_; |
| 160 const uint8_t* const old_base = |
| 161 need_compressed_alpha ? dec->alpha_data_ : old_start; |
138 assert(mem->mode_ == MEM_MODE_APPEND); | 162 assert(mem->mode_ == MEM_MODE_APPEND); |
139 if (data_size > MAX_CHUNK_PAYLOAD) { | 163 if (data_size > MAX_CHUNK_PAYLOAD) { |
140 // security safeguard: trying to allocate more than what the format | 164 // security safeguard: trying to allocate more than what the format |
141 // allows for a chunk should be considered a smoke smell. | 165 // allows for a chunk should be considered a smoke smell. |
142 return 0; | 166 return 0; |
143 } | 167 } |
144 | 168 |
145 if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory | 169 if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory |
146 const size_t current_size = MemDataSize(mem); | 170 const size_t new_mem_start = old_start - old_base; |
| 171 const size_t current_size = MemDataSize(mem) + new_mem_start; |
147 const uint64_t new_size = (uint64_t)current_size + data_size; | 172 const uint64_t new_size = (uint64_t)current_size + data_size; |
148 const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); | 173 const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); |
149 uint8_t* const new_buf = | 174 uint8_t* const new_buf = |
150 (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); | 175 (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); |
151 if (new_buf == NULL) return 0; | 176 if (new_buf == NULL) return 0; |
152 memcpy(new_buf, old_base, current_size); | 177 memcpy(new_buf, old_base, current_size); |
153 free(mem->buf_); | 178 free(mem->buf_); |
154 mem->buf_ = new_buf; | 179 mem->buf_ = new_buf; |
155 mem->buf_size_ = (size_t)extra_size; | 180 mem->buf_size_ = (size_t)extra_size; |
156 mem->start_ = 0; | 181 mem->start_ = new_mem_start; |
157 mem->end_ = current_size; | 182 mem->end_ = current_size; |
158 } | 183 } |
159 | 184 |
160 memcpy(mem->buf_ + mem->end_, data, data_size); | 185 memcpy(mem->buf_ + mem->end_, data, data_size); |
161 mem->end_ += data_size; | 186 mem->end_ += data_size; |
162 assert(mem->end_ <= mem->buf_size_); | 187 assert(mem->end_ <= mem->buf_size_); |
163 | 188 |
164 DoRemap(idec, mem->buf_ + mem->start_ - old_base); | 189 DoRemap(idec, mem->buf_ + mem->start_ - old_start); |
165 return 1; | 190 return 1; |
166 } | 191 } |
167 | 192 |
168 static int RemapMemBuffer(WebPIDecoder* const idec, | 193 static int RemapMemBuffer(WebPIDecoder* const idec, |
169 const uint8_t* const data, size_t data_size) { | 194 const uint8_t* const data, size_t data_size) { |
170 MemBuffer* const mem = &idec->mem_; | 195 MemBuffer* const mem = &idec->mem_; |
171 const uint8_t* const old_base = mem->buf_ + mem->start_; | 196 const uint8_t* const old_buf = mem->buf_; |
| 197 const uint8_t* const old_start = old_buf + mem->start_; |
172 assert(mem->mode_ == MEM_MODE_MAP); | 198 assert(mem->mode_ == MEM_MODE_MAP); |
173 | 199 |
174 if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! | 200 if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! |
175 | 201 |
176 mem->buf_ = (uint8_t*)data; | 202 mem->buf_ = (uint8_t*)data; |
177 mem->end_ = mem->buf_size_ = data_size; | 203 mem->end_ = mem->buf_size_ = data_size; |
178 | 204 |
179 DoRemap(idec, mem->buf_ + mem->start_ - old_base); | 205 DoRemap(idec, mem->buf_ + mem->start_ - old_start); |
180 return 1; | 206 return 1; |
181 } | 207 } |
182 | 208 |
183 static void InitMemBuffer(MemBuffer* const mem) { | 209 static void InitMemBuffer(MemBuffer* const mem) { |
184 mem->mode_ = MEM_MODE_NONE; | 210 mem->mode_ = MEM_MODE_NONE; |
185 mem->buf_ = NULL; | 211 mem->buf_ = NULL; |
186 mem->buf_size_ = 0; | 212 mem->buf_size_ = 0; |
187 mem->part0_buf_ = NULL; | 213 mem->part0_buf_ = NULL; |
188 mem->part0_size_ = 0; | 214 mem->part0_size_ = 0; |
189 } | 215 } |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 idec->io_.setup = setup; | 831 idec->io_.setup = setup; |
806 idec->io_.teardown = teardown; | 832 idec->io_.teardown = teardown; |
807 idec->io_.opaque = user_data; | 833 idec->io_.opaque = user_data; |
808 | 834 |
809 return 1; | 835 return 1; |
810 } | 836 } |
811 | 837 |
812 #if defined(__cplusplus) || defined(c_plusplus) | 838 #if defined(__cplusplus) || defined(c_plusplus) |
813 } // extern "C" | 839 } // extern "C" |
814 #endif | 840 #endif |
OLD | NEW |