| 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 |