quality_estimate.c (3886B)
1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the COPYING file in the root of the source 5 // tree. An additional intellectual property rights grant can be found 6 // in the file PATENTS. All contributing project authors may 7 // be found in the AUTHORS file in the root of the source tree. 8 // ----------------------------------------------------------------------------- 9 // 10 // VP8EstimateQuality(): rough encoding quality estimate 11 // 12 // Author: Skal (pascal.massimino@gmail.com) 13 14 #include <math.h> 15 #include <stddef.h> 16 17 #include "extras/extras.h" 18 #include "src/webp/types.h" 19 #include "webp/decode.h" 20 21 //------------------------------------------------------------------------------ 22 23 #define INVALID_BIT_POS (1ull << 63) 24 25 // In most cases, we don't need to use a full arithmetic decoder, since 26 // all the header's bits are written using a uniform probability of 128. 27 // We can just parse the header as if it was bits (works in 99.999% cases). 28 static WEBP_INLINE uint32_t GetBit(const uint8_t* const data, size_t nb, 29 uint64_t max_size, uint64_t* const bit_pos) { 30 uint32_t val = 0; 31 if (*bit_pos + nb <= 8 * max_size) { 32 while (nb-- > 0) { 33 const uint64_t p = (*bit_pos)++; 34 const int bit = !!(data[p >> 3] & (128 >> ((p & 7)))); 35 val = (val << 1) | bit; 36 } 37 } else { 38 *bit_pos = INVALID_BIT_POS; 39 } 40 return val; 41 } 42 43 #define GET_BIT(n) GetBit(data, (n), size, &bit_pos) 44 #define CONDITIONAL_SKIP(n) (GET_BIT(1) ? GET_BIT((n)) : 0) 45 46 int VP8EstimateQuality(const uint8_t* const data, size_t size) { 47 size_t pos = 0; 48 uint64_t bit_pos; 49 uint64_t sig = 0x00; 50 int ok = 0; 51 int Q = -1; 52 WebPBitstreamFeatures features; 53 54 if (data == NULL) return -1; 55 56 if (WebPGetFeatures(data, size, &features) != VP8_STATUS_OK) { 57 return -1; // invalid file 58 } 59 if (features.format == 2) return 101; // lossless 60 if (features.format == 0 || features.has_animation) return -1; // mixed 61 62 while (pos < size) { 63 sig = (sig >> 8) | ((uint64_t)data[pos++] << 40); 64 if ((sig >> 24) == 0x2a019dull) { 65 ok = 1; 66 break; 67 } 68 } 69 if (!ok) return -1; 70 if (pos + 4 > size) return -1; 71 72 // Skip main Header 73 // width = (data[pos + 0] | (data[pos + 1] << 8)) & 0x3fff; 74 // height = (data[pos + 2] | (data[pos + 3] << 8)) & 0x3fff; 75 pos += 4; 76 bit_pos = pos * 8; 77 78 GET_BIT(2); // colorspace + clamp type 79 80 // Segment header 81 if (GET_BIT(1)) { // use_segment 82 int s; 83 const int update_map = GET_BIT(1); 84 if (GET_BIT(1)) { // update data 85 const int absolute_delta = GET_BIT(1); 86 int q[4] = { 0, 0, 0, 0 }; 87 for (s = 0; s < 4; ++s) { 88 if (GET_BIT(1)) { 89 q[s] = GET_BIT(7); 90 if (GET_BIT(1)) q[s] = -q[s]; // sign 91 } 92 } 93 if (absolute_delta) Q = q[0]; // just use the first segment's quantizer 94 for (s = 0; s < 4; ++s) CONDITIONAL_SKIP(7); // filter strength 95 } 96 if (update_map) { 97 for (s = 0; s < 3; ++s) CONDITIONAL_SKIP(8); 98 } 99 } 100 // Filter header 101 GET_BIT(1 + 6 + 3); // simple + level + sharpness 102 if (GET_BIT(1)) { // use_lf_delta 103 if (GET_BIT(1)) { // update lf_delta? 104 int n; 105 for (n = 0; n < 4 + 4; ++n) CONDITIONAL_SKIP(6); 106 } 107 } 108 // num partitions 109 GET_BIT(2); 110 111 // ParseQuant 112 { 113 const int base_q = GET_BIT(7); 114 /* dqy1_dc = */ CONDITIONAL_SKIP(5); 115 /* dqy2_dc = */ CONDITIONAL_SKIP(5); 116 /* dqy2_ac = */ CONDITIONAL_SKIP(5); 117 /* dquv_dc = */ CONDITIONAL_SKIP(5); 118 /* dquv_ac = */ CONDITIONAL_SKIP(5); 119 120 if (Q < 0) Q = base_q; 121 } 122 if (bit_pos == INVALID_BIT_POS) return -1; 123 124 // base mapping 125 Q = (127 - Q) * 100 / 127; 126 // correction for power-law behavior in low range 127 if (Q < 80) { 128 Q = (int)(pow(Q / 80., 1. / 0.38) * 80); 129 } 130 return Q; 131 }