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

Side by Side Diff: third_party/libwebp/demux/anim_decode.c

Issue 2584033003: libwebp-0.5.2-rc2 (Closed)
Patch Set: layout tests Created 3 years, 12 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
OLDNEW
1 // Copyright 2015 Google Inc. All Rights Reserved. 1 // Copyright 2015 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 // AnimDecoder implementation. 10 // AnimDecoder implementation.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 105
106 dec->demux_ = WebPDemux(webp_data); 106 dec->demux_ = WebPDemux(webp_data);
107 if (dec->demux_ == NULL) goto Error; 107 if (dec->demux_ == NULL) goto Error;
108 108
109 dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); 109 dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH);
110 dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); 110 dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT);
111 dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); 111 dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT);
112 dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); 112 dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR);
113 dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); 113 dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT);
114 114
115 { 115 // Note: calloc() because we fill frame with zeroes as well.
116 const int canvas_bytes = 116 dec->curr_frame_ = (uint8_t*)WebPSafeCalloc(
117 dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height; 117 dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height);
118 // Note: calloc() because we fill frame with zeroes as well. 118 if (dec->curr_frame_ == NULL) goto Error;
119 dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes); 119 dec->prev_frame_disposed_ = (uint8_t*)WebPSafeCalloc(
120 if (dec->curr_frame_ == NULL) goto Error; 120 dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height);
121 dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes); 121 if (dec->prev_frame_disposed_ == NULL) goto Error;
122 if (dec->prev_frame_disposed_ == NULL) goto Error;
123 }
124 122
125 WebPAnimDecoderReset(dec); 123 WebPAnimDecoderReset(dec);
126
127 return dec; 124 return dec;
128 125
129 Error: 126 Error:
130 WebPAnimDecoderDelete(dec); 127 WebPAnimDecoderDelete(dec);
131 return NULL; 128 return NULL;
132 } 129 }
133 130
134 int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { 131 int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) {
135 if (dec == NULL || info == NULL) return 0; 132 if (dec == NULL || info == NULL) return 0;
136 *info = dec->info_; 133 *info = dec->info_;
137 return 1; 134 return 1;
138 } 135 }
139 136
140 // Returns true if the frame covers the full canvas. 137 // Returns true if the frame covers the full canvas.
141 static int IsFullFrame(int width, int height, int canvas_width, 138 static int IsFullFrame(int width, int height, int canvas_width,
142 int canvas_height) { 139 int canvas_height) {
143 return (width == canvas_width && height == canvas_height); 140 return (width == canvas_width && height == canvas_height);
144 } 141 }
145 142
146 // Clear the canvas to transparent. 143 // Clear the canvas to transparent.
147 static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, 144 static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
148 uint32_t canvas_height) { 145 uint32_t canvas_height) {
149 memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height); 146 const uint64_t size =
147 (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf);
148 if (size != (size_t)size) return 0;
149 memset(buf, 0, (size_t)size);
150 return 1;
150 } 151 }
151 152
152 // Clear given frame rectangle to transparent. 153 // Clear given frame rectangle to transparent.
153 static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, 154 static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
154 int y_offset, int width, int height) { 155 int y_offset, int width, int height) {
155 int j; 156 int j;
156 assert(width * NUM_CHANNELS <= buf_stride); 157 assert(width * NUM_CHANNELS <= buf_stride);
157 buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; 158 buf += y_offset * buf_stride + x_offset * NUM_CHANNELS;
158 for (j = 0; j < height; ++j) { 159 for (j = 0; j < height; ++j) {
159 memset(buf, 0, width * NUM_CHANNELS); 160 memset(buf, 0, width * NUM_CHANNELS);
160 buf += buf_stride; 161 buf += buf_stride;
161 } 162 }
162 } 163 }
163 164
164 // Copy width * height pixels from 'src' to 'dst'. 165 // Copy width * height pixels from 'src' to 'dst'.
165 static void CopyCanvas(const uint8_t* src, uint8_t* dst, 166 static int CopyCanvas(const uint8_t* src, uint8_t* dst,
166 uint32_t width, uint32_t height) { 167 uint32_t width, uint32_t height) {
168 const uint64_t size = (uint64_t)width * height * NUM_CHANNELS;
169 if (size != (size_t)size) return 0;
167 assert(src != NULL && dst != NULL); 170 assert(src != NULL && dst != NULL);
168 memcpy(dst, src, width * NUM_CHANNELS * height); 171 memcpy(dst, src, (size_t)size);
172 return 1;
169 } 173 }
170 174
171 // Returns true if the current frame is a key-frame. 175 // Returns true if the current frame is a key-frame.
172 static int IsKeyFrame(const WebPIterator* const curr, 176 static int IsKeyFrame(const WebPIterator* const curr,
173 const WebPIterator* const prev, 177 const WebPIterator* const prev,
174 int prev_frame_was_key_frame, 178 int prev_frame_was_key_frame,
175 int canvas_width, int canvas_height) { 179 int canvas_width, int canvas_height) {
176 if (curr->frame_num == 1) { 180 if (curr->frame_num == 1) {
177 return 1; 181 return 1;
178 } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && 182 } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) &&
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 // Get compressed frame. 325 // Get compressed frame.
322 if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { 326 if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) {
323 return 0; 327 return 0;
324 } 328 }
325 timestamp = dec->prev_frame_timestamp_ + iter.duration; 329 timestamp = dec->prev_frame_timestamp_ + iter.duration;
326 330
327 // Initialize. 331 // Initialize.
328 is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, 332 is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_,
329 dec->prev_frame_was_keyframe_, width, height); 333 dec->prev_frame_was_keyframe_, width, height);
330 if (is_key_frame) { 334 if (is_key_frame) {
331 ZeroFillCanvas(dec->curr_frame_, width, height); 335 if (!ZeroFillCanvas(dec->curr_frame_, width, height)) {
336 goto Error;
337 }
332 } else { 338 } else {
333 CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height); 339 if (!CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_,
340 width, height)) {
341 goto Error;
342 }
334 } 343 }
335 344
336 // Decode. 345 // Decode.
337 { 346 {
338 const uint8_t* in = iter.fragment.bytes; 347 const uint8_t* in = iter.fragment.bytes;
339 const size_t in_size = iter.fragment.size; 348 const size_t in_size = iter.fragment.size;
340 const size_t out_offset = 349 const size_t out_offset =
341 (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS; 350 (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS;
342 WebPDecoderConfig* const config = &dec->config_; 351 WebPDecoderConfig* const config = &dec->config_;
343 WebPRGBABuffer* const buf = &config->output.u.RGBA; 352 WebPRGBABuffer* const buf = &config->output.u.RGBA;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 const size_t offset2 = canvas_y * width + left2; 395 const size_t offset2 = canvas_y * width + left2;
387 blend_row((uint32_t*)dec->curr_frame_ + offset2, 396 blend_row((uint32_t*)dec->curr_frame_ + offset2,
388 (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); 397 (uint32_t*)dec->prev_frame_disposed_ + offset2, width2);
389 } 398 }
390 } 399 }
391 } 400 }
392 } 401 }
393 402
394 // Update info of the previous frame and dispose it for the next iteration. 403 // Update info of the previous frame and dispose it for the next iteration.
395 dec->prev_frame_timestamp_ = timestamp; 404 dec->prev_frame_timestamp_ = timestamp;
405 WebPDemuxReleaseIterator(&dec->prev_iter_);
396 dec->prev_iter_ = iter; 406 dec->prev_iter_ = iter;
397 dec->prev_frame_was_keyframe_ = is_key_frame; 407 dec->prev_frame_was_keyframe_ = is_key_frame;
398 CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); 408 CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height);
399 if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { 409 if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
400 ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, 410 ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS,
401 dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, 411 dec->prev_iter_.x_offset, dec->prev_iter_.y_offset,
402 dec->prev_iter_.width, dec->prev_iter_.height); 412 dec->prev_iter_.width, dec->prev_iter_.height);
403 } 413 }
404 ++dec->next_frame_; 414 ++dec->next_frame_;
405 415
406 // All OK, fill in the values. 416 // All OK, fill in the values.
407 *buf_ptr = dec->curr_frame_; 417 *buf_ptr = dec->curr_frame_;
408 *timestamp_ptr = timestamp; 418 *timestamp_ptr = timestamp;
409 return 1; 419 return 1;
410 420
411 Error: 421 Error:
412 WebPDemuxReleaseIterator(&iter); 422 WebPDemuxReleaseIterator(&iter);
413 return 0; 423 return 0;
414 } 424 }
415 425
416 int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { 426 int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) {
417 if (dec == NULL) return 0; 427 if (dec == NULL) return 0;
418 return (dec->next_frame_ <= (int)dec->info_.frame_count); 428 return (dec->next_frame_ <= (int)dec->info_.frame_count);
419 } 429 }
420 430
421 void WebPAnimDecoderReset(WebPAnimDecoder* dec) { 431 void WebPAnimDecoderReset(WebPAnimDecoder* dec) {
422 if (dec != NULL) { 432 if (dec != NULL) {
423 dec->prev_frame_timestamp_ = 0; 433 dec->prev_frame_timestamp_ = 0;
434 WebPDemuxReleaseIterator(&dec->prev_iter_);
424 memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); 435 memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_));
425 dec->prev_frame_was_keyframe_ = 0; 436 dec->prev_frame_was_keyframe_ = 0;
426 dec->next_frame_ = 1; 437 dec->next_frame_ = 1;
427 } 438 }
428 } 439 }
429 440
430 const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { 441 const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) {
431 if (dec == NULL) return NULL; 442 if (dec == NULL) return NULL;
432 return dec->demux_; 443 return dec->demux_;
433 } 444 }
434 445
435 void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { 446 void WebPAnimDecoderDelete(WebPAnimDecoder* dec) {
436 if (dec != NULL) { 447 if (dec != NULL) {
448 WebPDemuxReleaseIterator(&dec->prev_iter_);
437 WebPDemuxDelete(dec->demux_); 449 WebPDemuxDelete(dec->demux_);
438 WebPSafeFree(dec->curr_frame_); 450 WebPSafeFree(dec->curr_frame_);
439 WebPSafeFree(dec->prev_frame_disposed_); 451 WebPSafeFree(dec->prev_frame_disposed_);
440 WebPSafeFree(dec); 452 WebPSafeFree(dec);
441 } 453 }
442 } 454 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698