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

Side by Side Diff: third_party/libwebp/enc/iterator.c

Issue 116213006: Update libwebp to 0.4.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: After Blink Roll Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/enc/histogram.c ('k') | third_party/libwebp/enc/layer.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 // VP8Iterator: block iterator 10 // VP8Iterator: block iterator
11 // 11 //
12 // Author: Skal (pascal.massimino@gmail.com) 12 // Author: Skal (pascal.massimino@gmail.com)
13 13
14 #include <string.h> 14 #include <string.h>
15 15
16 #include "./vp8enci.h" 16 #include "./vp8enci.h"
17 17
18 #if defined(__cplusplus) || defined(c_plusplus)
19 extern "C" {
20 #endif
21
22 //------------------------------------------------------------------------------ 18 //------------------------------------------------------------------------------
23 // VP8Iterator 19 // VP8Iterator
24 //------------------------------------------------------------------------------ 20 //------------------------------------------------------------------------------
25 21
26 static void InitLeft(VP8EncIterator* const it) { 22 static void InitLeft(VP8EncIterator* const it) {
27 const VP8Encoder* const enc = it->enc_; 23 it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] =
28 enc->y_left_[-1] = enc->u_left_[-1] = enc->v_left_[-1] =
29 (it->y_ > 0) ? 129 : 127; 24 (it->y_ > 0) ? 129 : 127;
30 memset(enc->y_left_, 129, 16); 25 memset(it->y_left_, 129, 16);
31 memset(enc->u_left_, 129, 8); 26 memset(it->u_left_, 129, 8);
32 memset(enc->v_left_, 129, 8); 27 memset(it->v_left_, 129, 8);
33 it->left_nz_[8] = 0; 28 it->left_nz_[8] = 0;
34 } 29 }
35 30
36 static void InitTop(VP8EncIterator* const it) { 31 static void InitTop(VP8EncIterator* const it) {
37 const VP8Encoder* const enc = it->enc_; 32 const VP8Encoder* const enc = it->enc_;
38 const size_t top_size = enc->mb_w_ * 16; 33 const size_t top_size = enc->mb_w_ * 16;
39 memset(enc->y_top_, 127, 2 * top_size); 34 memset(enc->y_top_, 127, 2 * top_size);
40 memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_)); 35 memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
41 } 36 }
42 37
38 void VP8IteratorSetRow(VP8EncIterator* const it, int y) {
39 VP8Encoder* const enc = it->enc_;
40 it->x_ = 0;
41 it->y_ = y;
42 it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)];
43 it->preds_ = enc->preds_ + y * 4 * enc->preds_w_;
44 it->nz_ = enc->nz_;
45 it->mb_ = enc->mb_info_ + y * enc->mb_w_;
46 it->y_top_ = enc->y_top_;
47 it->uv_top_ = enc->uv_top_;
48 InitLeft(it);
49 }
50
43 void VP8IteratorReset(VP8EncIterator* const it) { 51 void VP8IteratorReset(VP8EncIterator* const it) {
44 VP8Encoder* const enc = it->enc_; 52 VP8Encoder* const enc = it->enc_;
45 it->x_ = 0; 53 VP8IteratorSetRow(it, 0);
46 it->y_ = 0; 54 VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default
47 it->y_offset_ = 0;
48 it->uv_offset_ = 0;
49 it->mb_ = enc->mb_info_;
50 it->preds_ = enc->preds_;
51 it->nz_ = enc->nz_;
52 it->bw_ = &enc->parts_[0];
53 it->done_ = enc->mb_w_* enc->mb_h_;
54 InitTop(it); 55 InitTop(it);
55 InitLeft(it); 56 InitLeft(it);
56 memset(it->bit_count_, 0, sizeof(it->bit_count_)); 57 memset(it->bit_count_, 0, sizeof(it->bit_count_));
57 it->do_trellis_ = 0; 58 it->do_trellis_ = 0;
58 } 59 }
59 60
61 void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) {
62 it->count_down_ = it->count_down0_ = count_down;
63 }
64
65 int VP8IteratorIsDone(const VP8EncIterator* const it) {
66 return (it->count_down_ <= 0);
67 }
68
60 void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) { 69 void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
61 it->enc_ = enc; 70 it->enc_ = enc;
62 it->y_stride_ = enc->pic_->y_stride; 71 it->y_stride_ = enc->pic_->y_stride;
63 it->uv_stride_ = enc->pic_->uv_stride; 72 it->uv_stride_ = enc->pic_->uv_stride;
64 // TODO(later): for multithreading, these should be owned by 'it'. 73 it->yuv_in_ = (uint8_t*)DO_ALIGN(it->yuv_mem_);
65 it->yuv_in_ = enc->yuv_in_; 74 it->yuv_out_ = it->yuv_in_ + YUV_SIZE;
66 it->yuv_out_ = enc->yuv_out_; 75 it->yuv_out2_ = it->yuv_out_ + YUV_SIZE;
67 it->yuv_out2_ = enc->yuv_out2_; 76 it->yuv_p_ = it->yuv_out2_ + YUV_SIZE;
68 it->yuv_p_ = enc->yuv_p_;
69 it->lf_stats_ = enc->lf_stats_; 77 it->lf_stats_ = enc->lf_stats_;
70 it->percent0_ = enc->percent_; 78 it->percent0_ = enc->percent_;
79 it->y_left_ = (uint8_t*)DO_ALIGN(it->yuv_left_mem_ + 1);
80 it->u_left_ = it->y_left_ + 16 + 16;
81 it->v_left_ = it->u_left_ + 16;
71 VP8IteratorReset(it); 82 VP8IteratorReset(it);
72 } 83 }
73 84
74 int VP8IteratorProgress(const VP8EncIterator* const it, int delta) { 85 int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
75 VP8Encoder* const enc = it->enc_; 86 VP8Encoder* const enc = it->enc_;
76 if (delta && enc->pic_->progress_hook) { 87 if (delta && enc->pic_->progress_hook != NULL) {
77 const int percent = (enc->mb_h_ <= 1) 88 const int done = it->count_down0_ - it->count_down_;
89 const int percent = (it->count_down0_ <= 0)
78 ? it->percent0_ 90 ? it->percent0_
79 : it->percent0_ + delta * it->y_ / (enc->mb_h_ - 1); 91 : it->percent0_ + delta * done / it->count_down0_;
80 return WebPReportProgress(enc->pic_, percent, &enc->percent_); 92 return WebPReportProgress(enc->pic_, percent, &enc->percent_);
81 } 93 }
82 return 1; 94 return 1;
83 } 95 }
84 96
85 //------------------------------------------------------------------------------ 97 //------------------------------------------------------------------------------
86 // Import the source samples into the cache. Takes care of replicating 98 // Import the source samples into the cache. Takes care of replicating
87 // boundary pixels if necessary. 99 // boundary pixels if necessary.
88 100
101 static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; }
102
89 static void ImportBlock(const uint8_t* src, int src_stride, 103 static void ImportBlock(const uint8_t* src, int src_stride,
90 uint8_t* dst, int w, int h, int size) { 104 uint8_t* dst, int w, int h, int size) {
91 int i; 105 int i;
92 for (i = 0; i < h; ++i) { 106 for (i = 0; i < h; ++i) {
93 memcpy(dst, src, w); 107 memcpy(dst, src, w);
94 if (w < size) { 108 if (w < size) {
95 memset(dst + w, dst[w - 1], size - w); 109 memset(dst + w, dst[w - 1], size - w);
96 } 110 }
97 dst += BPS; 111 dst += BPS;
98 src += src_stride; 112 src += src_stride;
99 } 113 }
100 for (i = h; i < size; ++i) { 114 for (i = h; i < size; ++i) {
101 memcpy(dst, dst - BPS, size); 115 memcpy(dst, dst - BPS, size);
102 dst += BPS; 116 dst += BPS;
103 } 117 }
104 } 118 }
105 119
106 void VP8IteratorImport(const VP8EncIterator* const it) { 120 static void ImportLine(const uint8_t* src, int src_stride,
121 uint8_t* dst, int len, int total_len) {
122 int i;
123 for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src;
124 for (; i < total_len; ++i) dst[i] = dst[len - 1];
125 }
126
127 void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
107 const VP8Encoder* const enc = it->enc_; 128 const VP8Encoder* const enc = it->enc_;
108 const int x = it->x_, y = it->y_; 129 const int x = it->x_, y = it->y_;
109 const WebPPicture* const pic = enc->pic_; 130 const WebPPicture* const pic = enc->pic_;
110 const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16; 131 const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
111 const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8; 132 const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8;
112 const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8; 133 const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8;
113 uint8_t* const ydst = it->yuv_in_ + Y_OFF; 134 const int w = MinSize(pic->width - x * 16, 16);
114 uint8_t* const udst = it->yuv_in_ + U_OFF; 135 const int h = MinSize(pic->height - y * 16, 16);
115 uint8_t* const vdst = it->yuv_in_ + V_OFF; 136 const int uv_w = (w + 1) >> 1;
116 int w = (pic->width - x * 16); 137 const int uv_h = (h + 1) >> 1;
117 int h = (pic->height - y * 16);
118 138
119 if (w > 16) w = 16; 139 ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF, w, h, 16);
120 if (h > 16) h = 16; 140 ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF, uv_w, uv_h, 8);
141 ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF, uv_w, uv_h, 8);
121 142
122 // Luma plane 143 if (tmp_32 == NULL) return;
123 ImportBlock(ysrc, pic->y_stride, ydst, w, h, 16);
124 144
125 { // U/V planes 145 // Import source (uncompressed) samples into boundary.
126 const int uv_w = (w + 1) >> 1; 146 if (x == 0) {
127 const int uv_h = (h + 1) >> 1; 147 InitLeft(it);
128 ImportBlock(usrc, pic->uv_stride, udst, uv_w, uv_h, 8); 148 } else {
129 ImportBlock(vsrc, pic->uv_stride, vdst, uv_w, uv_h, 8); 149 if (y == 0) {
150 it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127;
151 } else {
152 it->y_left_[-1] = ysrc[- 1 - pic->y_stride];
153 it->u_left_[-1] = usrc[- 1 - pic->uv_stride];
154 it->v_left_[-1] = vsrc[- 1 - pic->uv_stride];
155 }
156 ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16);
157 ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8);
158 ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8);
159 }
160
161 it->y_top_ = tmp_32 + 0;
162 it->uv_top_ = tmp_32 + 16;
163 if (y == 0) {
164 memset(tmp_32, 127, 32 * sizeof(*tmp_32));
165 } else {
166 ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16);
167 ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8);
168 ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8);
130 } 169 }
131 } 170 }
132 171
133 //------------------------------------------------------------------------------ 172 //------------------------------------------------------------------------------
134 // Copy back the compressed samples into user space if requested. 173 // Copy back the compressed samples into user space if requested.
135 174
136 static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride, 175 static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride,
137 int w, int h) { 176 int w, int h) {
138 while (h-- > 0) { 177 while (h-- > 0) {
139 memcpy(dst, src, w); 178 memcpy(dst, src, w);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 nz |= (left_nz[0] << 3) | (left_nz[1] << 7); 274 nz |= (left_nz[0] << 3) | (left_nz[1] << 7);
236 nz |= (left_nz[2] << 11); 275 nz |= (left_nz[2] << 11);
237 nz |= (left_nz[4] << 17) | (left_nz[6] << 21); 276 nz |= (left_nz[4] << 17) | (left_nz[6] << 21);
238 277
239 *it->nz_ = nz; 278 *it->nz_ = nz;
240 } 279 }
241 280
242 #undef BIT 281 #undef BIT
243 282
244 //------------------------------------------------------------------------------ 283 //------------------------------------------------------------------------------
245 // Advance to the next position, doing the bookeeping. 284 // Advance to the next position, doing the bookkeeping.
246 285
247 int VP8IteratorNext(VP8EncIterator* const it, 286 void VP8IteratorSaveBoundary(VP8EncIterator* const it) {
248 const uint8_t* const block_to_save) {
249 VP8Encoder* const enc = it->enc_; 287 VP8Encoder* const enc = it->enc_;
250 if (block_to_save) { 288 const int x = it->x_, y = it->y_;
251 const int x = it->x_, y = it->y_; 289 const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
252 const uint8_t* const ysrc = block_to_save + Y_OFF; 290 const uint8_t* const uvsrc = it->yuv_out_ + U_OFF;
253 const uint8_t* const usrc = block_to_save + U_OFF; 291 if (x < enc->mb_w_ - 1) { // left
254 if (x < enc->mb_w_ - 1) { // left 292 int i;
255 int i; 293 for (i = 0; i < 16; ++i) {
256 for (i = 0; i < 16; ++i) { 294 it->y_left_[i] = ysrc[15 + i * BPS];
257 enc->y_left_[i] = ysrc[15 + i * BPS];
258 }
259 for (i = 0; i < 8; ++i) {
260 enc->u_left_[i] = usrc[7 + i * BPS];
261 enc->v_left_[i] = usrc[15 + i * BPS];
262 }
263 // top-left (before 'top'!)
264 enc->y_left_[-1] = enc->y_top_[x * 16 + 15];
265 enc->u_left_[-1] = enc->uv_top_[x * 16 + 0 + 7];
266 enc->v_left_[-1] = enc->uv_top_[x * 16 + 8 + 7];
267 } 295 }
268 if (y < enc->mb_h_ - 1) { // top 296 for (i = 0; i < 8; ++i) {
269 memcpy(enc->y_top_ + x * 16, ysrc + 15 * BPS, 16); 297 it->u_left_[i] = uvsrc[7 + i * BPS];
270 memcpy(enc->uv_top_ + x * 16, usrc + 7 * BPS, 8 + 8); 298 it->v_left_[i] = uvsrc[15 + i * BPS];
271 } 299 }
300 // top-left (before 'top'!)
301 it->y_left_[-1] = it->y_top_[15];
302 it->u_left_[-1] = it->uv_top_[0 + 7];
303 it->v_left_[-1] = it->uv_top_[8 + 7];
272 } 304 }
305 if (y < enc->mb_h_ - 1) { // top
306 memcpy(it->y_top_, ysrc + 15 * BPS, 16);
307 memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8);
308 }
309 }
273 310
274 it->mb_++; 311 int VP8IteratorNext(VP8EncIterator* const it) {
275 it->preds_ += 4; 312 it->preds_ += 4;
276 it->nz_++; 313 it->mb_ += 1;
277 it->x_++; 314 it->nz_ += 1;
278 if (it->x_ == enc->mb_w_) { 315 it->y_top_ += 16;
279 it->x_ = 0; 316 it->uv_top_ += 16;
280 it->y_++; 317 it->x_ += 1;
281 it->bw_ = &enc->parts_[it->y_ & (enc->num_parts_ - 1)]; 318 if (it->x_ == it->enc_->mb_w_) {
282 it->preds_ = enc->preds_ + it->y_ * 4 * enc->preds_w_; 319 VP8IteratorSetRow(it, ++it->y_);
283 it->nz_ = enc->nz_;
284 InitLeft(it);
285 } 320 }
286 return (0 < --it->done_); 321 return (0 < --it->count_down_);
287 } 322 }
288 323
289 //------------------------------------------------------------------------------ 324 //------------------------------------------------------------------------------
290 // Helper function to set mode properties 325 // Helper function to set mode properties
291 326
292 void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) { 327 void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) {
293 uint8_t* preds = it->preds_; 328 uint8_t* preds = it->preds_;
294 int y; 329 int y;
295 for (y = 0; y < 4; ++y) { 330 for (y = 0; y < 4; ++y) {
296 memset(preds, mode, 4); 331 memset(preds, mode, 4);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 398
364 void VP8IteratorStartI4(VP8EncIterator* const it) { 399 void VP8IteratorStartI4(VP8EncIterator* const it) {
365 const VP8Encoder* const enc = it->enc_; 400 const VP8Encoder* const enc = it->enc_;
366 int i; 401 int i;
367 402
368 it->i4_ = 0; // first 4x4 sub-block 403 it->i4_ = 0; // first 4x4 sub-block
369 it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0]; 404 it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0];
370 405
371 // Import the boundary samples 406 // Import the boundary samples
372 for (i = 0; i < 17; ++i) { // left 407 for (i = 0; i < 17; ++i) { // left
373 it->i4_boundary_[i] = enc->y_left_[15 - i]; 408 it->i4_boundary_[i] = it->y_left_[15 - i];
374 } 409 }
375 for (i = 0; i < 16; ++i) { // top 410 for (i = 0; i < 16; ++i) { // top
376 it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i]; 411 it->i4_boundary_[17 + i] = it->y_top_[i];
377 } 412 }
378 // top-right samples have a special case on the far right of the picture 413 // top-right samples have a special case on the far right of the picture
379 if (it->x_ < enc->mb_w_ - 1) { 414 if (it->x_ < enc->mb_w_ - 1) {
380 for (i = 16; i < 16 + 4; ++i) { 415 for (i = 16; i < 16 + 4; ++i) {
381 it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i]; 416 it->i4_boundary_[17 + i] = it->y_top_[i];
382 } 417 }
383 } else { // else, replicate the last valid pixel four times 418 } else { // else, replicate the last valid pixel four times
384 for (i = 16; i < 16 + 4; ++i) { 419 for (i = 16; i < 16 + 4; ++i) {
385 it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15]; 420 it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15];
386 } 421 }
387 } 422 }
388 VP8IteratorNzToBytes(it); // import the non-zero context 423 VP8IteratorNzToBytes(it); // import the non-zero context
389 } 424 }
390 425
391 int VP8IteratorRotateI4(VP8EncIterator* const it, 426 int VP8IteratorRotateI4(VP8EncIterator* const it,
(...skipping 20 matching lines...) Expand all
412 if (it->i4_ == 16) { // we're done 447 if (it->i4_ == 16) { // we're done
413 return 0; 448 return 0;
414 } 449 }
415 450
416 it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_]; 451 it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_];
417 return 1; 452 return 1;
418 } 453 }
419 454
420 //------------------------------------------------------------------------------ 455 //------------------------------------------------------------------------------
421 456
422 #if defined(__cplusplus) || defined(c_plusplus)
423 } // extern "C"
424 #endif
OLDNEW
« no previous file with comments | « third_party/libwebp/enc/histogram.c ('k') | third_party/libwebp/enc/layer.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698