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 // This code is licensed under the same terms as WebM: |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // Software License Agreement: http://www.webmproject.org/license/software/ |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ |
6 // ----------------------------------------------------------------------------- | 6 // ----------------------------------------------------------------------------- |
7 // | 7 // |
8 // frame coding and analysis | 8 // frame coding and analysis |
9 // | 9 // |
10 // Author: Skal (pascal.massimino@gmail.com) | 10 // Author: Skal (pascal.massimino@gmail.com) |
11 | 11 |
| 12 #include <assert.h> |
12 #include <stdlib.h> | 13 #include <stdlib.h> |
13 #include <string.h> | 14 #include <string.h> |
14 #include <math.h> | 15 #include <math.h> |
15 | 16 |
16 #include "./vp8enci.h" | 17 #include "./vp8enci.h" |
17 #include "./cost.h" | 18 #include "./cost.h" |
18 | 19 |
19 #if defined(__cplusplus) || defined(c_plusplus) | 20 #if defined(__cplusplus) || defined(c_plusplus) |
20 extern "C" { | 21 extern "C" { |
21 #endif | 22 #endif |
(...skipping 15 matching lines...) Expand all Loading... |
37 } VP8Residual; | 38 } VP8Residual; |
38 | 39 |
39 //------------------------------------------------------------------------------ | 40 //------------------------------------------------------------------------------ |
40 // Tables for level coding | 41 // Tables for level coding |
41 | 42 |
42 const uint8_t VP8EncBands[16 + 1] = { | 43 const uint8_t VP8EncBands[16 + 1] = { |
43 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, | 44 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, |
44 0 // sentinel | 45 0 // sentinel |
45 }; | 46 }; |
46 | 47 |
47 static const uint8_t kCat3[] = { 173, 148, 140 }; | 48 const uint8_t VP8Cat3[] = { 173, 148, 140 }; |
48 static const uint8_t kCat4[] = { 176, 155, 140, 135 }; | 49 const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; |
49 static const uint8_t kCat5[] = { 180, 157, 141, 134, 130 }; | 50 const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; |
50 static const uint8_t kCat6[] = | 51 const uint8_t VP8Cat6[] = |
51 { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; | 52 { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; |
52 | 53 |
53 //------------------------------------------------------------------------------ | 54 //------------------------------------------------------------------------------ |
54 // Reset the statistics about: number of skips, token proba, level cost,... | 55 // Reset the statistics about: number of skips, token proba, level cost,... |
55 | 56 |
56 static void ResetStats(VP8Encoder* const enc, int precalc_cost) { | 57 static void ResetStats(VP8Encoder* const enc) { |
57 VP8Proba* const proba = &enc->proba_; | 58 VP8Proba* const proba = &enc->proba_; |
58 if (precalc_cost) VP8CalculateLevelCosts(proba); | 59 VP8CalculateLevelCosts(proba); |
59 proba->nb_skip_ = 0; | 60 proba->nb_skip_ = 0; |
60 } | 61 } |
61 | 62 |
62 //------------------------------------------------------------------------------ | 63 //------------------------------------------------------------------------------ |
63 // Skip decision probability | 64 // Skip decision probability |
64 | 65 |
65 #define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. | 66 #define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. |
66 | 67 |
67 static int CalcSkipProba(uint64_t nb, uint64_t total) { | 68 static int CalcSkipProba(uint64_t nb, uint64_t total) { |
68 return (int)(total ? (total - nb) * 255 / total : 255); | 69 return (int)(total ? (total - nb) * 255 / total : 255); |
(...skipping 18 matching lines...) Expand all Loading... |
87 | 88 |
88 //------------------------------------------------------------------------------ | 89 //------------------------------------------------------------------------------ |
89 // Recording of token probabilities. | 90 // Recording of token probabilities. |
90 | 91 |
91 static void ResetTokenStats(VP8Encoder* const enc) { | 92 static void ResetTokenStats(VP8Encoder* const enc) { |
92 VP8Proba* const proba = &enc->proba_; | 93 VP8Proba* const proba = &enc->proba_; |
93 memset(proba->stats_, 0, sizeof(proba->stats_)); | 94 memset(proba->stats_, 0, sizeof(proba->stats_)); |
94 } | 95 } |
95 | 96 |
96 // Record proba context used | 97 // Record proba context used |
97 static int Record(int bit, uint64_t* const stats) { | 98 static int Record(int bit, proba_t* const stats) { |
98 stats[0] += bit; | 99 proba_t p = *stats; |
99 stats[1] += 1; | 100 if (p >= 0xffff0000u) { // an overflow is inbound. |
| 101 p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. |
| 102 } |
| 103 // record bit count (lower 16 bits) and increment total count (upper 16 bits). |
| 104 p += 0x00010000u + bit; |
| 105 *stats = p; |
100 return bit; | 106 return bit; |
101 } | 107 } |
102 | 108 |
103 // We keep the table free variant around for reference, in case. | 109 // We keep the table free variant around for reference, in case. |
104 #define USE_LEVEL_CODE_TABLE | 110 #define USE_LEVEL_CODE_TABLE |
105 | 111 |
106 // Simulate block coding, but only record statistics. | 112 // Simulate block coding, but only record statistics. |
107 // Note: no need to record the fixed probas. | 113 // Note: no need to record the fixed probas. |
108 static int RecordCoeffs(int ctx, const VP8Residual* const res) { | 114 static int RecordCoeffs(int ctx, const VP8Residual* const res) { |
109 int n = res->first; | 115 int n = res->first; |
110 uint64_t (*s)[2] = res->stats[VP8EncBands[n]][ctx]; | 116 // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 |
111 if (!Record(res->last >= 0, s[0])) { | 117 proba_t* s = res->stats[n][ctx]; |
| 118 if (res->last < 0) { |
| 119 Record(0, s + 0); |
112 return 0; | 120 return 0; |
113 } | 121 } |
114 | 122 while (n <= res->last) { |
115 while (1) { | 123 int v; |
116 int v = res->coeffs[n++]; | 124 Record(1, s + 0); // order of record doesn't matter |
117 if (!Record(v != 0, s[1])) { | 125 while ((v = res->coeffs[n++]) == 0) { |
| 126 Record(0, s + 1); |
118 s = res->stats[VP8EncBands[n]][0]; | 127 s = res->stats[VP8EncBands[n]][0]; |
119 continue; | |
120 } | 128 } |
121 if (!Record(2u < (unsigned int)(v + 1), s[2])) { // v = -1 or 1 | 129 Record(1, s + 1); |
| 130 if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1 |
122 s = res->stats[VP8EncBands[n]][1]; | 131 s = res->stats[VP8EncBands[n]][1]; |
123 } else { | 132 } else { |
124 v = abs(v); | 133 v = abs(v); |
125 #if !defined(USE_LEVEL_CODE_TABLE) | 134 #if !defined(USE_LEVEL_CODE_TABLE) |
126 if (!Record(v > 4, s[3])) { | 135 if (!Record(v > 4, s + 3)) { |
127 if (Record(v != 2, s[4])) | 136 if (Record(v != 2, s + 4)) |
128 Record(v == 4, s[5]); | 137 Record(v == 4, s + 5); |
129 } else if (!Record(v > 10, s[6])) { | 138 } else if (!Record(v > 10, s + 6)) { |
130 Record(v > 6, s[7]); | 139 Record(v > 6, s + 7); |
131 } else if (!Record((v >= 3 + (8 << 2)), s[8])) { | 140 } else if (!Record((v >= 3 + (8 << 2)), s + 8)) { |
132 Record((v >= 3 + (8 << 1)), s[9]); | 141 Record((v >= 3 + (8 << 1)), s + 9); |
133 } else { | 142 } else { |
134 Record((v >= 3 + (8 << 3)), s[10]); | 143 Record((v >= 3 + (8 << 3)), s + 10); |
135 } | 144 } |
136 #else | 145 #else |
137 if (v > MAX_VARIABLE_LEVEL) | 146 if (v > MAX_VARIABLE_LEVEL) |
138 v = MAX_VARIABLE_LEVEL; | 147 v = MAX_VARIABLE_LEVEL; |
139 | 148 |
140 { | 149 { |
141 const int bits = VP8LevelCodes[v - 1][1]; | 150 const int bits = VP8LevelCodes[v - 1][1]; |
142 int pattern = VP8LevelCodes[v - 1][0]; | 151 int pattern = VP8LevelCodes[v - 1][0]; |
143 int i; | 152 int i; |
144 for (i = 0; (pattern >>= 1) != 0; ++i) { | 153 for (i = 0; (pattern >>= 1) != 0; ++i) { |
145 const int mask = 2 << i; | 154 const int mask = 2 << i; |
146 if (pattern & 1) Record(!!(bits & mask), s[3 + i]); | 155 if (pattern & 1) Record(!!(bits & mask), s + 3 + i); |
147 } | 156 } |
148 } | 157 } |
149 #endif | 158 #endif |
150 s = res->stats[VP8EncBands[n]][2]; | 159 s = res->stats[VP8EncBands[n]][2]; |
151 } | 160 } |
152 if (n == 16 || !Record(n <= res->last, s[0])) { | |
153 return 1; | |
154 } | |
155 } | 161 } |
| 162 if (n < 16) Record(0, s + 0); |
| 163 return 1; |
156 } | 164 } |
157 | 165 |
158 // Collect statistics and deduce probabilities for next coding pass. | 166 // Collect statistics and deduce probabilities for next coding pass. |
159 // Return the total bit-cost for coding the probability updates. | 167 // Return the total bit-cost for coding the probability updates. |
160 static int CalcTokenProba(uint64_t nb, uint64_t total) { | 168 static int CalcTokenProba(int nb, int total) { |
161 return (int)(nb ? ((total - nb) * 255 + total / 2) / total : 255); | 169 assert(nb <= total); |
| 170 return nb ? (255 - nb * 255 / total) : 255; |
162 } | 171 } |
163 | 172 |
164 static int FinalizeTokenProbas(VP8Encoder* const enc) { | 173 // Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. |
165 VP8Proba* const proba = &enc->proba_; | 174 static int BranchCost(int nb, int total, int proba) { |
| 175 return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); |
| 176 } |
| 177 |
| 178 static int FinalizeTokenProbas(VP8Proba* const proba) { |
| 179 int has_changed = 0; |
166 int size = 0; | 180 int size = 0; |
167 int t, b, c, p; | 181 int t, b, c, p; |
168 for (t = 0; t < NUM_TYPES; ++t) { | 182 for (t = 0; t < NUM_TYPES; ++t) { |
169 for (b = 0; b < NUM_BANDS; ++b) { | 183 for (b = 0; b < NUM_BANDS; ++b) { |
170 for (c = 0; c < NUM_CTX; ++c) { | 184 for (c = 0; c < NUM_CTX; ++c) { |
171 for (p = 0; p < NUM_PROBAS; ++p) { | 185 for (p = 0; p < NUM_PROBAS; ++p) { |
172 const uint64_t* const cnt = proba->stats_[t][b][c][p]; | 186 const proba_t stats = proba->stats_[t][b][c][p]; |
| 187 const int nb = (stats >> 0) & 0xffff; |
| 188 const int total = (stats >> 16) & 0xffff; |
173 const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; | 189 const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; |
174 const int old_p = VP8CoeffsProba0[t][b][c][p]; | 190 const int old_p = VP8CoeffsProba0[t][b][c][p]; |
175 const int new_p = CalcTokenProba(cnt[0], cnt[1]); | 191 const int new_p = CalcTokenProba(nb, total); |
176 const uint64_t old_cost = VP8BranchCost(cnt[0], cnt[1], old_p) | 192 const int old_cost = BranchCost(nb, total, old_p) |
177 + VP8BitCost(0, update_proba); | 193 + VP8BitCost(0, update_proba); |
178 const uint64_t new_cost = VP8BranchCost(cnt[0], cnt[1], new_p) | 194 const int new_cost = BranchCost(nb, total, new_p) |
179 + VP8BitCost(1, update_proba) + 8 * 256; | 195 + VP8BitCost(1, update_proba) |
| 196 + 8 * 256; |
180 const int use_new_p = (old_cost > new_cost); | 197 const int use_new_p = (old_cost > new_cost); |
181 size += VP8BitCost(use_new_p, update_proba); | 198 size += VP8BitCost(use_new_p, update_proba); |
182 if (use_new_p) { // only use proba that seem meaningful enough. | 199 if (use_new_p) { // only use proba that seem meaningful enough. |
183 proba->coeffs_[t][b][c][p] = new_p; | 200 proba->coeffs_[t][b][c][p] = new_p; |
| 201 has_changed |= (new_p != old_p); |
184 size += 8 * 256; | 202 size += 8 * 256; |
185 } else { | 203 } else { |
186 proba->coeffs_[t][b][c][p] = old_p; | 204 proba->coeffs_[t][b][c][p] = old_p; |
187 } | 205 } |
188 } | 206 } |
189 } | 207 } |
190 } | 208 } |
191 } | 209 } |
| 210 proba->dirty_ = has_changed; |
192 return size; | 211 return size; |
193 } | 212 } |
194 | 213 |
195 //------------------------------------------------------------------------------ | 214 //------------------------------------------------------------------------------ |
| 215 // Finalize Segment probability based on the coding tree |
| 216 |
| 217 static int GetProba(int a, int b) { |
| 218 const int total = a + b; |
| 219 return (total == 0) ? 255 // that's the default probability. |
| 220 : (255 * a + total / 2) / total; // rounded proba |
| 221 } |
| 222 |
| 223 static void SetSegmentProbas(VP8Encoder* const enc) { |
| 224 int p[NUM_MB_SEGMENTS] = { 0 }; |
| 225 int n; |
| 226 |
| 227 for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { |
| 228 const VP8MBInfo* const mb = &enc->mb_info_[n]; |
| 229 p[mb->segment_]++; |
| 230 } |
| 231 if (enc->pic_->stats != NULL) { |
| 232 for (n = 0; n < NUM_MB_SEGMENTS; ++n) { |
| 233 enc->pic_->stats->segment_size[n] = p[n]; |
| 234 } |
| 235 } |
| 236 if (enc->segment_hdr_.num_segments_ > 1) { |
| 237 uint8_t* const probas = enc->proba_.segments_; |
| 238 probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); |
| 239 probas[1] = GetProba(p[0], p[1]); |
| 240 probas[2] = GetProba(p[2], p[3]); |
| 241 |
| 242 enc->segment_hdr_.update_map_ = |
| 243 (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); |
| 244 enc->segment_hdr_.size_ = |
| 245 p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + |
| 246 p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + |
| 247 p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + |
| 248 p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); |
| 249 } else { |
| 250 enc->segment_hdr_.update_map_ = 0; |
| 251 enc->segment_hdr_.size_ = 0; |
| 252 } |
| 253 } |
| 254 |
| 255 //------------------------------------------------------------------------------ |
196 // helper functions for residuals struct VP8Residual. | 256 // helper functions for residuals struct VP8Residual. |
197 | 257 |
198 static void InitResidual(int first, int coeff_type, | 258 static void InitResidual(int first, int coeff_type, |
199 VP8Encoder* const enc, VP8Residual* const res) { | 259 VP8Encoder* const enc, VP8Residual* const res) { |
200 res->coeff_type = coeff_type; | 260 res->coeff_type = coeff_type; |
201 res->prob = enc->proba_.coeffs_[coeff_type]; | 261 res->prob = enc->proba_.coeffs_[coeff_type]; |
202 res->stats = enc->proba_.stats_[coeff_type]; | 262 res->stats = enc->proba_.stats_[coeff_type]; |
203 res->cost = enc->proba_.level_cost_[coeff_type]; | 263 res->cost = enc->proba_.level_cost_[coeff_type]; |
204 res->first = first; | 264 res->first = first; |
205 } | 265 } |
206 | 266 |
207 static void SetResidualCoeffs(const int16_t* const coeffs, | 267 static void SetResidualCoeffs(const int16_t* const coeffs, |
208 VP8Residual* const res) { | 268 VP8Residual* const res) { |
209 int n; | 269 int n; |
210 res->last = -1; | 270 res->last = -1; |
211 for (n = 15; n >= res->first; --n) { | 271 for (n = 15; n >= res->first; --n) { |
212 if (coeffs[n]) { | 272 if (coeffs[n]) { |
213 res->last = n; | 273 res->last = n; |
214 break; | 274 break; |
215 } | 275 } |
216 } | 276 } |
217 res->coeffs = coeffs; | 277 res->coeffs = coeffs; |
218 } | 278 } |
219 | 279 |
220 //------------------------------------------------------------------------------ | 280 //------------------------------------------------------------------------------ |
221 // Mode costs | 281 // Mode costs |
222 | 282 |
223 static int GetResidualCost(int ctx, const VP8Residual* const res) { | 283 static int GetResidualCost(int ctx0, const VP8Residual* const res) { |
224 int n = res->first; | 284 int n = res->first; |
225 const uint8_t* p = res->prob[VP8EncBands[n]][ctx]; | 285 // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 |
226 const uint16_t *t = res->cost[VP8EncBands[n]][ctx]; | 286 int p0 = res->prob[n][ctx0][0]; |
227 int last_p0 = p[0]; | 287 const uint16_t* t = res->cost[n][ctx0]; |
228 int cost; | 288 int cost; |
229 | 289 |
230 if (res->last < 0) { | 290 if (res->last < 0) { |
231 return VP8BitCost(0, last_p0); | 291 return VP8BitCost(0, p0); |
232 } | 292 } |
233 cost = 0; | 293 cost = 0; |
234 while (n <= res->last) { | 294 while (n < res->last) { |
235 const int v = res->coeffs[n]; | 295 int v = res->coeffs[n]; |
236 const int b = VP8EncBands[n + 1]; | 296 const int b = VP8EncBands[n + 1]; |
237 ++n; | 297 ++n; |
238 if (v == 0) { | 298 if (v == 0) { |
239 cost += VP8LevelCost(t, 0); | 299 // short-case for VP8LevelCost(t, 0) (note: VP8LevelFixedCosts[0] == 0): |
240 p = res->prob[b][0]; | 300 cost += t[0]; |
241 t = res->cost[b][0]; | 301 t = res->cost[b][0]; |
242 continue; | 302 continue; |
243 } | 303 } |
244 cost += VP8BitCost(1, last_p0); | 304 v = abs(v); |
245 if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1 | 305 cost += VP8BitCost(1, p0); |
246 cost += VP8LevelCost(t, 1); | 306 cost += VP8LevelCost(t, v); |
247 p = res->prob[b][1]; | 307 { |
248 t = res->cost[b][1]; | 308 const int ctx = (v == 1) ? 1 : 2; |
249 } else { | 309 p0 = res->prob[b][ctx][0]; |
250 cost += VP8LevelCost(t, abs(v)); | 310 t = res->cost[b][ctx]; |
251 p = res->prob[b][2]; | |
252 t = res->cost[b][2]; | |
253 } | 311 } |
254 last_p0 = p[0]; | |
255 } | 312 } |
256 if (n < 16) cost += VP8BitCost(0, last_p0); | 313 // Last coefficient is always non-zero |
| 314 { |
| 315 const int v = abs(res->coeffs[n]); |
| 316 assert(v != 0); |
| 317 cost += VP8BitCost(1, p0); |
| 318 cost += VP8LevelCost(t, v); |
| 319 if (n < 15) { |
| 320 const int b = VP8EncBands[n + 1]; |
| 321 const int ctx = (v == 1) ? 1 : 2; |
| 322 const int last_p0 = res->prob[b][ctx][0]; |
| 323 cost += VP8BitCost(0, last_p0); |
| 324 } |
| 325 } |
257 return cost; | 326 return cost; |
258 } | 327 } |
259 | 328 |
260 int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { | 329 int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { |
261 const int x = (it->i4_ & 3), y = (it->i4_ >> 2); | 330 const int x = (it->i4_ & 3), y = (it->i4_ >> 2); |
262 VP8Residual res; | 331 VP8Residual res; |
263 VP8Encoder* const enc = it->enc_; | 332 VP8Encoder* const enc = it->enc_; |
264 int R = 0; | 333 int R = 0; |
265 int ctx; | 334 int ctx; |
266 | 335 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 } | 386 } |
318 } | 387 } |
319 return R; | 388 return R; |
320 } | 389 } |
321 | 390 |
322 //------------------------------------------------------------------------------ | 391 //------------------------------------------------------------------------------ |
323 // Coefficient coding | 392 // Coefficient coding |
324 | 393 |
325 static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { | 394 static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { |
326 int n = res->first; | 395 int n = res->first; |
327 const uint8_t* p = res->prob[VP8EncBands[n]][ctx]; | 396 // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 |
| 397 const uint8_t* p = res->prob[n][ctx]; |
328 if (!VP8PutBit(bw, res->last >= 0, p[0])) { | 398 if (!VP8PutBit(bw, res->last >= 0, p[0])) { |
329 return 0; | 399 return 0; |
330 } | 400 } |
331 | 401 |
332 while (n < 16) { | 402 while (n < 16) { |
333 const int c = res->coeffs[n++]; | 403 const int c = res->coeffs[n++]; |
334 const int sign = c < 0; | 404 const int sign = c < 0; |
335 int v = sign ? -c : c; | 405 int v = sign ? -c : c; |
336 if (!VP8PutBit(bw, v != 0, p[1])) { | 406 if (!VP8PutBit(bw, v != 0, p[1])) { |
337 p = res->prob[VP8EncBands[n]][0]; | 407 p = res->prob[VP8EncBands[n]][0]; |
338 continue; | 408 continue; |
339 } | 409 } |
340 if (!VP8PutBit(bw, v > 1, p[2])) { | 410 if (!VP8PutBit(bw, v > 1, p[2])) { |
341 p = res->prob[VP8EncBands[n]][1]; | 411 p = res->prob[VP8EncBands[n]][1]; |
342 } else { | 412 } else { |
343 if (!VP8PutBit(bw, v > 4, p[3])) { | 413 if (!VP8PutBit(bw, v > 4, p[3])) { |
344 if (VP8PutBit(bw, v != 2, p[4])) | 414 if (VP8PutBit(bw, v != 2, p[4])) |
345 VP8PutBit(bw, v == 4, p[5]); | 415 VP8PutBit(bw, v == 4, p[5]); |
346 } else if (!VP8PutBit(bw, v > 10, p[6])) { | 416 } else if (!VP8PutBit(bw, v > 10, p[6])) { |
347 if (!VP8PutBit(bw, v > 6, p[7])) { | 417 if (!VP8PutBit(bw, v > 6, p[7])) { |
348 VP8PutBit(bw, v == 6, 159); | 418 VP8PutBit(bw, v == 6, 159); |
349 } else { | 419 } else { |
350 VP8PutBit(bw, v >= 9, 165); | 420 VP8PutBit(bw, v >= 9, 165); |
351 VP8PutBit(bw, !(v & 1), 145); | 421 VP8PutBit(bw, !(v & 1), 145); |
352 } | 422 } |
353 } else { | 423 } else { |
354 int mask; | 424 int mask; |
355 const uint8_t* tab; | 425 const uint8_t* tab; |
356 if (v < 3 + (8 << 1)) { // kCat3 (3b) | 426 if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) |
357 VP8PutBit(bw, 0, p[8]); | 427 VP8PutBit(bw, 0, p[8]); |
358 VP8PutBit(bw, 0, p[9]); | 428 VP8PutBit(bw, 0, p[9]); |
359 v -= 3 + (8 << 0); | 429 v -= 3 + (8 << 0); |
360 mask = 1 << 2; | 430 mask = 1 << 2; |
361 tab = kCat3; | 431 tab = VP8Cat3; |
362 } else if (v < 3 + (8 << 2)) { // kCat4 (4b) | 432 } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) |
363 VP8PutBit(bw, 0, p[8]); | 433 VP8PutBit(bw, 0, p[8]); |
364 VP8PutBit(bw, 1, p[9]); | 434 VP8PutBit(bw, 1, p[9]); |
365 v -= 3 + (8 << 1); | 435 v -= 3 + (8 << 1); |
366 mask = 1 << 3; | 436 mask = 1 << 3; |
367 tab = kCat4; | 437 tab = VP8Cat4; |
368 } else if (v < 3 + (8 << 3)) { // kCat5 (5b) | 438 } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) |
369 VP8PutBit(bw, 1, p[8]); | 439 VP8PutBit(bw, 1, p[8]); |
370 VP8PutBit(bw, 0, p[10]); | 440 VP8PutBit(bw, 0, p[10]); |
371 v -= 3 + (8 << 2); | 441 v -= 3 + (8 << 2); |
372 mask = 1 << 4; | 442 mask = 1 << 4; |
373 tab = kCat5; | 443 tab = VP8Cat5; |
374 } else { // kCat6 (11b) | 444 } else { // VP8Cat6 (11b) |
375 VP8PutBit(bw, 1, p[8]); | 445 VP8PutBit(bw, 1, p[8]); |
376 VP8PutBit(bw, 1, p[10]); | 446 VP8PutBit(bw, 1, p[10]); |
377 v -= 3 + (8 << 3); | 447 v -= 3 + (8 << 3); |
378 mask = 1 << 10; | 448 mask = 1 << 10; |
379 tab = kCat6; | 449 tab = VP8Cat6; |
380 } | 450 } |
381 while (mask) { | 451 while (mask) { |
382 VP8PutBit(bw, !!(v & mask), *tab++); | 452 VP8PutBit(bw, !!(v & mask), *tab++); |
383 mask >>= 1; | 453 mask >>= 1; |
384 } | 454 } |
385 } | 455 } |
386 p = res->prob[VP8EncBands[n]][2]; | 456 p = res->prob[VP8EncBands[n]][2]; |
387 } | 457 } |
388 VP8PutBitUniform(bw, sign); | 458 VP8PutBitUniform(bw, sign); |
389 if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { | 459 if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { |
390 return 1; // EOB | 460 return 1; // EOB |
391 } | 461 } |
392 } | 462 } |
393 return 1; | 463 return 1; |
394 } | 464 } |
395 | 465 |
396 static void CodeResiduals(VP8BitWriter* const bw, | 466 static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, |
397 VP8EncIterator* const it, | |
398 const VP8ModeScore* const rd) { | 467 const VP8ModeScore* const rd) { |
399 int x, y, ch; | 468 int x, y, ch; |
400 VP8Residual res; | 469 VP8Residual res; |
401 uint64_t pos1, pos2, pos3; | 470 uint64_t pos1, pos2, pos3; |
402 const int i16 = (it->mb_->type_ == 1); | 471 const int i16 = (it->mb_->type_ == 1); |
403 const int segment = it->mb_->segment_; | 472 const int segment = it->mb_->segment_; |
404 VP8Encoder* const enc = it->enc_; | 473 VP8Encoder* const enc = it->enc_; |
405 | 474 |
406 VP8IteratorNzToBytes(it); | 475 VP8IteratorNzToBytes(it); |
407 | 476 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 } | 556 } |
488 } | 557 } |
489 } | 558 } |
490 | 559 |
491 VP8IteratorBytesToNz(it); | 560 VP8IteratorBytesToNz(it); |
492 } | 561 } |
493 | 562 |
494 //------------------------------------------------------------------------------ | 563 //------------------------------------------------------------------------------ |
495 // Token buffer | 564 // Token buffer |
496 | 565 |
497 #ifdef USE_TOKEN_BUFFER | 566 #if !defined(DISABLE_TOKEN_BUFFER) |
498 | 567 |
499 void VP8TBufferInit(VP8TBuffer* const b) { | 568 static void RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, |
500 b->rows_ = NULL; | 569 VP8TBuffer* const tokens) { |
501 b->tokens_ = NULL; | |
502 b->last_ = &b->rows_; | |
503 b->left_ = 0; | |
504 b->error_ = 0; | |
505 } | |
506 | |
507 int VP8TBufferNewPage(VP8TBuffer* const b) { | |
508 VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page)); | |
509 if (page == NULL) { | |
510 b->error_ = 1; | |
511 return 0; | |
512 } | |
513 *b->last_ = page; | |
514 b->last_ = &page->next_; | |
515 b->left_ = MAX_NUM_TOKEN; | |
516 b->tokens_ = page->tokens_; | |
517 return 1; | |
518 } | |
519 | |
520 void VP8TBufferClear(VP8TBuffer* const b) { | |
521 if (b != NULL) { | |
522 const VP8Tokens* p = b->rows_; | |
523 while (p != NULL) { | |
524 const VP8Tokens* const next = p->next_; | |
525 free((void*)p); | |
526 p = next; | |
527 } | |
528 VP8TBufferInit(b); | |
529 } | |
530 } | |
531 | |
532 int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw, | |
533 const uint8_t* const probas) { | |
534 VP8Tokens* p = b->rows_; | |
535 if (b->error_) return 0; | |
536 while (p != NULL) { | |
537 const int N = (p->next_ == NULL) ? b->left_ : 0; | |
538 int n = MAX_NUM_TOKEN; | |
539 while (n-- > N) { | |
540 VP8PutBit(bw, (p->tokens_[n] >> 15) & 1, probas[p->tokens_[n] & 0x7fff]); | |
541 } | |
542 p = p->next_; | |
543 } | |
544 return 1; | |
545 } | |
546 | |
547 #define TOKEN_ID(b, ctx, p) ((p) + NUM_PROBAS * ((ctx) + (b) * NUM_CTX)) | |
548 | |
549 static int RecordCoeffTokens(int ctx, const VP8Residual* const res, | |
550 VP8TBuffer* tokens) { | |
551 int n = res->first; | |
552 int b = VP8EncBands[n]; | |
553 if (!VP8AddToken(tokens, res->last >= 0, TOKEN_ID(b, ctx, 0))) { | |
554 return 0; | |
555 } | |
556 | |
557 while (n < 16) { | |
558 const int c = res->coeffs[n++]; | |
559 const int sign = c < 0; | |
560 int v = sign ? -c : c; | |
561 const int base_id = TOKEN_ID(b, ctx, 0); | |
562 if (!VP8AddToken(tokens, v != 0, base_id + 1)) { | |
563 b = VP8EncBands[n]; | |
564 ctx = 0; | |
565 continue; | |
566 } | |
567 if (!VP8AddToken(tokens, v > 1, base_id + 2)) { | |
568 b = VP8EncBands[n]; | |
569 ctx = 1; | |
570 } else { | |
571 if (!VP8AddToken(tokens, v > 4, base_id + 3)) { | |
572 if (VP8AddToken(tokens, v != 2, base_id + 4)) | |
573 VP8AddToken(tokens, v == 4, base_id + 5); | |
574 } else if (!VP8AddToken(tokens, v > 10, base_id + 6)) { | |
575 if (!VP8AddToken(tokens, v > 6, base_id + 7)) { | |
576 // VP8AddToken(tokens, v == 6, 159); | |
577 } else { | |
578 // VP8AddToken(tokens, v >= 9, 165); | |
579 // VP8AddToken(tokens, !(v & 1), 145); | |
580 } | |
581 } else { | |
582 int mask; | |
583 const uint8_t* tab; | |
584 if (v < 3 + (8 << 1)) { // kCat3 (3b) | |
585 VP8AddToken(tokens, 0, base_id + 8); | |
586 VP8AddToken(tokens, 0, base_id + 9); | |
587 v -= 3 + (8 << 0); | |
588 mask = 1 << 2; | |
589 tab = kCat3; | |
590 } else if (v < 3 + (8 << 2)) { // kCat4 (4b) | |
591 VP8AddToken(tokens, 0, base_id + 8); | |
592 VP8AddToken(tokens, 1, base_id + 9); | |
593 v -= 3 + (8 << 1); | |
594 mask = 1 << 3; | |
595 tab = kCat4; | |
596 } else if (v < 3 + (8 << 3)) { // kCat5 (5b) | |
597 VP8AddToken(tokens, 1, base_id + 8); | |
598 VP8AddToken(tokens, 0, base_id + 10); | |
599 v -= 3 + (8 << 2); | |
600 mask = 1 << 4; | |
601 tab = kCat5; | |
602 } else { // kCat6 (11b) | |
603 VP8AddToken(tokens, 1, base_id + 8); | |
604 VP8AddToken(tokens, 1, base_id + 10); | |
605 v -= 3 + (8 << 3); | |
606 mask = 1 << 10; | |
607 tab = kCat6; | |
608 } | |
609 while (mask) { | |
610 // VP8AddToken(tokens, !!(v & mask), *tab++); | |
611 mask >>= 1; | |
612 } | |
613 } | |
614 ctx = 2; | |
615 } | |
616 b = VP8EncBands[n]; | |
617 // VP8PutBitUniform(bw, sign); | |
618 if (n == 16 || !VP8AddToken(tokens, n <= res->last, TOKEN_ID(b, ctx, 0))) { | |
619 return 1; // EOB | |
620 } | |
621 } | |
622 return 1; | |
623 } | |
624 | |
625 static void RecordTokens(VP8EncIterator* const it, | |
626 const VP8ModeScore* const rd, VP8TBuffer tokens[2]) { | |
627 int x, y, ch; | 570 int x, y, ch; |
628 VP8Residual res; | 571 VP8Residual res; |
629 VP8Encoder* const enc = it->enc_; | 572 VP8Encoder* const enc = it->enc_; |
630 | 573 |
631 VP8IteratorNzToBytes(it); | 574 VP8IteratorNzToBytes(it); |
632 if (it->mb_->type_ == 1) { // i16x16 | 575 if (it->mb_->type_ == 1) { // i16x16 |
| 576 const int ctx = it->top_nz_[8] + it->left_nz_[8]; |
633 InitResidual(0, 1, enc, &res); | 577 InitResidual(0, 1, enc, &res); |
634 SetResidualCoeffs(rd->y_dc_levels, &res); | 578 SetResidualCoeffs(rd->y_dc_levels, &res); |
635 // TODO(skal): FIX -> it->top_nz_[8] = it->left_nz_[8] = | 579 it->top_nz_[8] = it->left_nz_[8] = |
636 RecordCoeffTokens(it->top_nz_[8] + it->left_nz_[8], &res, &tokens[0]); | 580 VP8RecordCoeffTokens(ctx, 1, |
| 581 res.first, res.last, res.coeffs, tokens); |
| 582 RecordCoeffs(ctx, &res); |
637 InitResidual(1, 0, enc, &res); | 583 InitResidual(1, 0, enc, &res); |
638 } else { | 584 } else { |
639 InitResidual(0, 3, enc, &res); | 585 InitResidual(0, 3, enc, &res); |
640 } | 586 } |
641 | 587 |
642 // luma-AC | 588 // luma-AC |
643 for (y = 0; y < 4; ++y) { | 589 for (y = 0; y < 4; ++y) { |
644 for (x = 0; x < 4; ++x) { | 590 for (x = 0; x < 4; ++x) { |
645 const int ctx = it->top_nz_[x] + it->left_nz_[y]; | 591 const int ctx = it->top_nz_[x] + it->left_nz_[y]; |
646 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); | 592 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); |
647 it->top_nz_[x] = it->left_nz_[y] = | 593 it->top_nz_[x] = it->left_nz_[y] = |
648 RecordCoeffTokens(ctx, &res, &tokens[0]); | 594 VP8RecordCoeffTokens(ctx, res.coeff_type, |
| 595 res.first, res.last, res.coeffs, tokens); |
| 596 RecordCoeffs(ctx, &res); |
649 } | 597 } |
650 } | 598 } |
651 | 599 |
652 // U/V | 600 // U/V |
653 InitResidual(0, 2, enc, &res); | 601 InitResidual(0, 2, enc, &res); |
654 for (ch = 0; ch <= 2; ch += 2) { | 602 for (ch = 0; ch <= 2; ch += 2) { |
655 for (y = 0; y < 2; ++y) { | 603 for (y = 0; y < 2; ++y) { |
656 for (x = 0; x < 2; ++x) { | 604 for (x = 0; x < 2; ++x) { |
657 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; | 605 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; |
658 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); | 606 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); |
659 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = | 607 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = |
660 RecordCoeffTokens(ctx, &res, &tokens[1]); | 608 VP8RecordCoeffTokens(ctx, 2, |
| 609 res.first, res.last, res.coeffs, tokens); |
| 610 RecordCoeffs(ctx, &res); |
661 } | 611 } |
662 } | 612 } |
663 } | 613 } |
| 614 VP8IteratorBytesToNz(it); |
664 } | 615 } |
665 | 616 |
666 #endif // USE_TOKEN_BUFFER | 617 #endif // !DISABLE_TOKEN_BUFFER |
667 | 618 |
668 //------------------------------------------------------------------------------ | 619 //------------------------------------------------------------------------------ |
669 // ExtraInfo map / Debug function | 620 // ExtraInfo map / Debug function |
670 | 621 |
671 #if SEGMENT_VISU | 622 #if SEGMENT_VISU |
672 static void SetBlock(uint8_t* p, int value, int size) { | 623 static void SetBlock(uint8_t* p, int value, int size) { |
673 int y; | 624 int y; |
674 for (y = 0; y < size; ++y) { | 625 for (y = 0; y < size; ++y) { |
675 memset(p, value, size); | 626 memset(p, value, size); |
676 p += BPS; | 627 p += BPS; |
677 } | 628 } |
678 } | 629 } |
679 #endif | 630 #endif |
680 | 631 |
681 static void ResetSSE(VP8Encoder* const enc) { | 632 static void ResetSSE(VP8Encoder* const enc) { |
682 memset(enc->sse_, 0, sizeof(enc->sse_)); | 633 enc->sse_[0] = 0; |
| 634 enc->sse_[1] = 0; |
| 635 enc->sse_[2] = 0; |
| 636 // Note: enc->sse_[3] is managed by alpha.c |
683 enc->sse_count_ = 0; | 637 enc->sse_count_ = 0; |
684 } | 638 } |
685 | 639 |
686 static void StoreSSE(const VP8EncIterator* const it) { | 640 static void StoreSSE(const VP8EncIterator* const it) { |
687 VP8Encoder* const enc = it->enc_; | 641 VP8Encoder* const enc = it->enc_; |
688 const uint8_t* const in = it->yuv_in_; | 642 const uint8_t* const in = it->yuv_in_; |
689 const uint8_t* const out = it->yuv_out_; | 643 const uint8_t* const out = it->yuv_out_; |
690 // Note: not totally accurate at boundary. And doesn't include in-loop filter. | 644 // Note: not totally accurate at boundary. And doesn't include in-loop filter. |
691 enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF); | 645 enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF); |
692 enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF); | 646 enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF); |
(...skipping 18 matching lines...) Expand all Loading... |
711 switch (pic->extra_info_type) { | 665 switch (pic->extra_info_type) { |
712 case 1: *info = mb->type_; break; | 666 case 1: *info = mb->type_; break; |
713 case 2: *info = mb->segment_; break; | 667 case 2: *info = mb->segment_; break; |
714 case 3: *info = enc->dqm_[mb->segment_].quant_; break; | 668 case 3: *info = enc->dqm_[mb->segment_].quant_; break; |
715 case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; | 669 case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; |
716 case 5: *info = mb->uv_mode_; break; | 670 case 5: *info = mb->uv_mode_; break; |
717 case 6: { | 671 case 6: { |
718 const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); | 672 const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); |
719 *info = (b > 255) ? 255 : b; break; | 673 *info = (b > 255) ? 255 : b; break; |
720 } | 674 } |
| 675 case 7: *info = mb->alpha_; break; |
721 default: *info = 0; break; | 676 default: *info = 0; break; |
722 }; | 677 }; |
723 } | 678 } |
724 #if SEGMENT_VISU // visualize segments and prediction modes | 679 #if SEGMENT_VISU // visualize segments and prediction modes |
725 SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16); | 680 SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16); |
726 SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8); | 681 SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8); |
727 SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8); | 682 SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8); |
728 #endif | 683 #endif |
729 } | 684 } |
730 | 685 |
731 //------------------------------------------------------------------------------ | 686 //------------------------------------------------------------------------------ |
732 // Main loops | 687 // StatLoop(): only collect statistics (number of skips, token usage, ...). |
733 // | 688 // This is used for deciding optimal probabilities. It also modifies the |
734 // VP8EncLoop(): does the final bitstream coding. | 689 // quantizer value if some target (size, PNSR) was specified. |
735 | |
736 static void ResetAfterSkip(VP8EncIterator* const it) { | |
737 if (it->mb_->type_ == 1) { | |
738 *it->nz_ = 0; // reset all predictors | |
739 it->left_nz_[8] = 0; | |
740 } else { | |
741 *it->nz_ &= (1 << 24); // preserve the dc_nz bit | |
742 } | |
743 } | |
744 | |
745 int VP8EncLoop(VP8Encoder* const enc) { | |
746 int i, s, p; | |
747 int ok = 1; | |
748 VP8EncIterator it; | |
749 VP8ModeScore info; | |
750 const int dont_use_skip = !enc->proba_.use_skip_proba_; | |
751 const int rd_opt = enc->rd_opt_level_; | |
752 const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10] | |
753 const int bytes_per_parts = | |
754 enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_; | |
755 | |
756 // Initialize the bit-writers | |
757 for (p = 0; p < enc->num_parts_; ++p) { | |
758 VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); | |
759 } | |
760 | |
761 ResetStats(enc, rd_opt != 0); | |
762 ResetSSE(enc); | |
763 | |
764 VP8IteratorInit(enc, &it); | |
765 VP8InitFilter(&it); | |
766 do { | |
767 VP8IteratorImport(&it); | |
768 // Warning! order is important: first call VP8Decimate() and | |
769 // *then* decide how to code the skip decision if there's one. | |
770 if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { | |
771 CodeResiduals(it.bw_, &it, &info); | |
772 } else { // reset predictors after a skip | |
773 ResetAfterSkip(&it); | |
774 } | |
775 #ifdef WEBP_EXPERIMENTAL_FEATURES | |
776 if (enc->use_layer_) { | |
777 VP8EncCodeLayerBlock(&it); | |
778 } | |
779 #endif | |
780 StoreSideInfo(&it); | |
781 VP8StoreFilterStats(&it); | |
782 VP8IteratorExport(&it); | |
783 ok = VP8IteratorProgress(&it, 20); | |
784 } while (ok && VP8IteratorNext(&it, it.yuv_out_)); | |
785 | |
786 if (ok) { // Finalize the partitions, check for extra errors. | |
787 for (p = 0; p < enc->num_parts_; ++p) { | |
788 VP8BitWriterFinish(enc->parts_ + p); | |
789 ok &= !enc->parts_[p].error_; | |
790 } | |
791 } | |
792 | |
793 if (ok) { // All good. Finish up. | |
794 if (enc->pic_->stats) { // finalize byte counters... | |
795 for (i = 0; i <= 2; ++i) { | |
796 for (s = 0; s < NUM_MB_SEGMENTS; ++s) { | |
797 enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3); | |
798 } | |
799 } | |
800 } | |
801 VP8AdjustFilterStrength(&it); // ...and store filter stats. | |
802 } else { | |
803 // Something bad happened -> need to do some memory cleanup. | |
804 VP8EncFreeBitWriters(enc); | |
805 } | |
806 | |
807 return ok; | |
808 } | |
809 | |
810 //------------------------------------------------------------------------------ | |
811 // VP8StatLoop(): only collect statistics (number of skips, token usage, ...) | |
812 // This is used for deciding optimal probabilities. It also | |
813 // modifies the quantizer value if some target (size, PNSR) | |
814 // was specified. | |
815 | 690 |
816 #define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better | 691 #define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better |
817 | 692 |
818 static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs, | 693 static void SetLoopParams(VP8Encoder* const enc, float q) { |
819 float* const PSNR, int percent_delta) { | |
820 VP8EncIterator it; | |
821 uint64_t size = 0; | |
822 uint64_t distortion = 0; | |
823 const uint64_t pixel_count = nb_mbs * 384; | |
824 | |
825 // Make sure the quality parameter is inside valid bounds | 694 // Make sure the quality parameter is inside valid bounds |
826 if (q < 0.) { | 695 if (q < 0.) { |
827 q = 0; | 696 q = 0; |
828 } else if (q > 100.) { | 697 } else if (q > 100.) { |
829 q = 100; | 698 q = 100; |
830 } | 699 } |
831 | 700 |
832 VP8SetSegmentParams(enc, q); // setup segment quantizations and filters | 701 VP8SetSegmentParams(enc, q); // setup segment quantizations and filters |
| 702 SetSegmentProbas(enc); // compute segment probabilities |
833 | 703 |
834 ResetStats(enc, rd_opt != 0); | 704 ResetStats(enc); |
835 ResetTokenStats(enc); | 705 ResetTokenStats(enc); |
836 | 706 |
| 707 ResetSSE(enc); |
| 708 } |
| 709 |
| 710 static int OneStatPass(VP8Encoder* const enc, float q, VP8RDLevel rd_opt, |
| 711 int nb_mbs, float* const PSNR, int percent_delta) { |
| 712 VP8EncIterator it; |
| 713 uint64_t size = 0; |
| 714 uint64_t distortion = 0; |
| 715 const uint64_t pixel_count = nb_mbs * 384; |
| 716 |
| 717 SetLoopParams(enc, q); |
| 718 |
837 VP8IteratorInit(enc, &it); | 719 VP8IteratorInit(enc, &it); |
838 do { | 720 do { |
839 VP8ModeScore info; | 721 VP8ModeScore info; |
840 VP8IteratorImport(&it); | 722 VP8IteratorImport(&it); |
841 if (VP8Decimate(&it, &info, rd_opt)) { | 723 if (VP8Decimate(&it, &info, rd_opt)) { |
842 // Just record the number of skips and act like skip_proba is not used. | 724 // Just record the number of skips and act like skip_proba is not used. |
843 enc->proba_.nb_skip_++; | 725 enc->proba_.nb_skip_++; |
844 } | 726 } |
845 RecordResiduals(&it, &info); | 727 RecordResiduals(&it, &info); |
846 size += info.R; | 728 size += info.R; |
847 distortion += info.D; | 729 distortion += info.D; |
848 if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) | 730 if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) |
849 return 0; | 731 return 0; |
850 } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0); | 732 } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0); |
851 size += FinalizeSkipProba(enc); | 733 size += FinalizeSkipProba(enc); |
852 size += FinalizeTokenProbas(enc); | 734 size += FinalizeTokenProbas(&enc->proba_); |
853 size += enc->segment_hdr_.size_; | 735 size += enc->segment_hdr_.size_; |
854 size = ((size + 1024) >> 11) + kHeaderSizeEstimate; | 736 size = ((size + 1024) >> 11) + kHeaderSizeEstimate; |
855 | 737 |
856 if (PSNR) { | 738 if (PSNR) { |
857 *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion)); | 739 *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion)); |
858 } | 740 } |
859 return (int)size; | 741 return (int)size; |
860 } | 742 } |
861 | 743 |
862 // successive refinement increments. | 744 // successive refinement increments. |
863 static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 }; | 745 static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 }; |
864 | 746 |
865 int VP8StatLoop(VP8Encoder* const enc) { | 747 static int StatLoop(VP8Encoder* const enc) { |
866 const int do_search = | 748 const int method = enc->method_; |
867 (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0); | 749 const int do_search = enc->do_search_; |
868 const int fast_probe = (enc->method_ < 2 && !do_search); | 750 const int fast_probe = ((method == 0 || method == 3) && !do_search); |
869 float q = enc->config_->quality; | 751 float q = enc->config_->quality; |
870 const int max_passes = enc->config_->pass; | 752 const int max_passes = enc->config_->pass; |
871 const int task_percent = 20; | 753 const int task_percent = 20; |
872 const int percent_per_pass = (task_percent + max_passes / 2) / max_passes; | 754 const int percent_per_pass = (task_percent + max_passes / 2) / max_passes; |
873 const int final_percent = enc->percent_ + task_percent; | 755 const int final_percent = enc->percent_ + task_percent; |
874 int pass; | 756 int pass; |
875 int nb_mbs; | 757 int nb_mbs; |
876 | 758 |
877 // Fast mode: quick analysis pass over few mbs. Better than nothing. | 759 // Fast mode: quick analysis pass over few mbs. Better than nothing. |
878 nb_mbs = enc->mb_w_ * enc->mb_h_; | 760 nb_mbs = enc->mb_w_ * enc->mb_h_; |
879 if (fast_probe && nb_mbs > 100) nb_mbs = 100; | 761 if (fast_probe) { |
| 762 if (method == 3) { // we need more stats for method 3 to be reliable. |
| 763 nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; |
| 764 } else { |
| 765 nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; |
| 766 } |
| 767 } |
880 | 768 |
881 // No target size: just do several pass without changing 'q' | 769 // No target size: just do several pass without changing 'q' |
882 if (!do_search) { | 770 if (!do_search) { |
883 for (pass = 0; pass < max_passes; ++pass) { | 771 for (pass = 0; pass < max_passes; ++pass) { |
884 const int rd_opt = (enc->method_ > 2); | 772 const VP8RDLevel rd_opt = (method >= 3) ? RD_OPT_BASIC : RD_OPT_NONE; |
885 if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) { | 773 if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) { |
886 return 0; | 774 return 0; |
887 } | 775 } |
888 } | 776 } |
889 } else { | 777 } else { |
890 // binary search for a size close to target | 778 // binary search for a size close to target |
891 for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) { | 779 for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) { |
892 const int rd_opt = 1; | |
893 float PSNR; | 780 float PSNR; |
894 int criterion; | 781 int criterion; |
895 const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR, | 782 const int size = OneStatPass(enc, q, RD_OPT_BASIC, nb_mbs, &PSNR, |
896 percent_per_pass); | 783 percent_per_pass); |
897 #if DEBUG_SEARCH | 784 #if DEBUG_SEARCH |
898 printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q); | 785 printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q); |
899 #endif | 786 #endif |
900 if (!size) return 0; | 787 if (size == 0) return 0; |
901 if (enc->config_->target_PSNR > 0) { | 788 if (enc->config_->target_PSNR > 0) { |
902 criterion = (PSNR < enc->config_->target_PSNR); | 789 criterion = (PSNR < enc->config_->target_PSNR); |
903 } else { | 790 } else { |
904 criterion = (size < enc->config_->target_size); | 791 criterion = (size < enc->config_->target_size); |
905 } | 792 } |
906 // dichotomize | 793 // dichotomize |
907 if (criterion) { | 794 if (criterion) { |
908 q += dqs[pass]; | 795 q += dqs[pass]; |
909 } else { | 796 } else { |
910 q -= dqs[pass]; | 797 q -= dqs[pass]; |
911 } | 798 } |
912 } | 799 } |
913 } | 800 } |
| 801 VP8CalculateLevelCosts(&enc->proba_); // finalize costs |
914 return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); | 802 return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); |
915 } | 803 } |
916 | 804 |
917 //------------------------------------------------------------------------------ | 805 //------------------------------------------------------------------------------ |
| 806 // Main loops |
| 807 // |
| 808 |
| 809 static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; |
| 810 |
| 811 static int PreLoopInitialize(VP8Encoder* const enc) { |
| 812 int p; |
| 813 int ok = 1; |
| 814 const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; |
| 815 const int bytes_per_parts = |
| 816 enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; |
| 817 // Initialize the bit-writers |
| 818 for (p = 0; ok && p < enc->num_parts_; ++p) { |
| 819 ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); |
| 820 } |
| 821 if (!ok) VP8EncFreeBitWriters(enc); // malloc error occurred |
| 822 return ok; |
| 823 } |
| 824 |
| 825 static int PostLoopFinalize(VP8EncIterator* const it, int ok) { |
| 826 VP8Encoder* const enc = it->enc_; |
| 827 if (ok) { // Finalize the partitions, check for extra errors. |
| 828 int p; |
| 829 for (p = 0; p < enc->num_parts_; ++p) { |
| 830 VP8BitWriterFinish(enc->parts_ + p); |
| 831 ok &= !enc->parts_[p].error_; |
| 832 } |
| 833 } |
| 834 |
| 835 if (ok) { // All good. Finish up. |
| 836 if (enc->pic_->stats) { // finalize byte counters... |
| 837 int i, s; |
| 838 for (i = 0; i <= 2; ++i) { |
| 839 for (s = 0; s < NUM_MB_SEGMENTS; ++s) { |
| 840 enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); |
| 841 } |
| 842 } |
| 843 } |
| 844 VP8AdjustFilterStrength(it); // ...and store filter stats. |
| 845 } else { |
| 846 // Something bad happened -> need to do some memory cleanup. |
| 847 VP8EncFreeBitWriters(enc); |
| 848 } |
| 849 return ok; |
| 850 } |
| 851 |
| 852 //------------------------------------------------------------------------------ |
| 853 // VP8EncLoop(): does the final bitstream coding. |
| 854 |
| 855 static void ResetAfterSkip(VP8EncIterator* const it) { |
| 856 if (it->mb_->type_ == 1) { |
| 857 *it->nz_ = 0; // reset all predictors |
| 858 it->left_nz_[8] = 0; |
| 859 } else { |
| 860 *it->nz_ &= (1 << 24); // preserve the dc_nz bit |
| 861 } |
| 862 } |
| 863 |
| 864 int VP8EncLoop(VP8Encoder* const enc) { |
| 865 VP8EncIterator it; |
| 866 int ok = PreLoopInitialize(enc); |
| 867 if (!ok) return 0; |
| 868 |
| 869 StatLoop(enc); // stats-collection loop |
| 870 |
| 871 VP8IteratorInit(enc, &it); |
| 872 VP8InitFilter(&it); |
| 873 do { |
| 874 VP8ModeScore info; |
| 875 const int dont_use_skip = !enc->proba_.use_skip_proba_; |
| 876 const VP8RDLevel rd_opt = enc->rd_opt_level_; |
| 877 |
| 878 VP8IteratorImport(&it); |
| 879 // Warning! order is important: first call VP8Decimate() and |
| 880 // *then* decide how to code the skip decision if there's one. |
| 881 if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { |
| 882 CodeResiduals(it.bw_, &it, &info); |
| 883 } else { // reset predictors after a skip |
| 884 ResetAfterSkip(&it); |
| 885 } |
| 886 #ifdef WEBP_EXPERIMENTAL_FEATURES |
| 887 if (enc->use_layer_) { |
| 888 VP8EncCodeLayerBlock(&it); |
| 889 } |
| 890 #endif |
| 891 StoreSideInfo(&it); |
| 892 VP8StoreFilterStats(&it); |
| 893 VP8IteratorExport(&it); |
| 894 ok = VP8IteratorProgress(&it, 20); |
| 895 } while (ok && VP8IteratorNext(&it, it.yuv_out_)); |
| 896 |
| 897 return PostLoopFinalize(&it, ok); |
| 898 } |
| 899 |
| 900 //------------------------------------------------------------------------------ |
| 901 // Single pass using Token Buffer. |
| 902 |
| 903 #if !defined(DISABLE_TOKEN_BUFFER) |
| 904 |
| 905 #define MIN_COUNT 96 // minimum number of macroblocks before updating stats |
| 906 |
| 907 int VP8EncTokenLoop(VP8Encoder* const enc) { |
| 908 int ok; |
| 909 // Roughly refresh the proba height times per pass |
| 910 int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; |
| 911 int cnt; |
| 912 VP8EncIterator it; |
| 913 VP8Proba* const proba = &enc->proba_; |
| 914 const VP8RDLevel rd_opt = enc->rd_opt_level_; |
| 915 |
| 916 if (max_count < MIN_COUNT) max_count = MIN_COUNT; |
| 917 cnt = max_count; |
| 918 |
| 919 assert(enc->num_parts_ == 1); |
| 920 assert(enc->use_tokens_); |
| 921 assert(proba->use_skip_proba_ == 0); |
| 922 assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful |
| 923 assert(!enc->do_search_); // TODO(skal): handle pass and dichotomy |
| 924 |
| 925 SetLoopParams(enc, enc->config_->quality); |
| 926 |
| 927 ok = PreLoopInitialize(enc); |
| 928 if (!ok) return 0; |
| 929 |
| 930 VP8IteratorInit(enc, &it); |
| 931 VP8InitFilter(&it); |
| 932 do { |
| 933 VP8ModeScore info; |
| 934 VP8IteratorImport(&it); |
| 935 if (--cnt < 0) { |
| 936 FinalizeTokenProbas(proba); |
| 937 VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt |
| 938 cnt = max_count; |
| 939 } |
| 940 VP8Decimate(&it, &info, rd_opt); |
| 941 RecordTokens(&it, &info, &enc->tokens_); |
| 942 #ifdef WEBP_EXPERIMENTAL_FEATURES |
| 943 if (enc->use_layer_) { |
| 944 VP8EncCodeLayerBlock(&it); |
| 945 } |
| 946 #endif |
| 947 StoreSideInfo(&it); |
| 948 VP8StoreFilterStats(&it); |
| 949 VP8IteratorExport(&it); |
| 950 ok = VP8IteratorProgress(&it, 20); |
| 951 } while (ok && VP8IteratorNext(&it, it.yuv_out_)); |
| 952 |
| 953 ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); |
| 954 |
| 955 if (ok) { |
| 956 FinalizeTokenProbas(proba); |
| 957 ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, |
| 958 (const uint8_t*)proba->coeffs_, 1); |
| 959 } |
| 960 |
| 961 return PostLoopFinalize(&it, ok); |
| 962 } |
| 963 |
| 964 #else |
| 965 |
| 966 int VP8EncTokenLoop(VP8Encoder* const enc) { |
| 967 (void)enc; |
| 968 return 0; // we shouldn't be here. |
| 969 } |
| 970 |
| 971 #endif // DISABLE_TOKEN_BUFFER |
| 972 |
| 973 //------------------------------------------------------------------------------ |
918 | 974 |
919 #if defined(__cplusplus) || defined(c_plusplus) | 975 #if defined(__cplusplus) || defined(c_plusplus) |
920 } // extern "C" | 976 } // extern "C" |
921 #endif | 977 #endif |
OLD | NEW |