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