• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h"
11 
12 #include "webrtc/base/logging.h"
13 
14 namespace webrtc {
15 
16 namespace vp8 {
17 namespace {
18 const size_t kCommonPayloadHeaderLength = 3;
19 const size_t kKeyPayloadHeaderLength = 10;
20 }  // namespace
21 
BSwap32(uint32_t x)22 static uint32_t BSwap32(uint32_t x) {
23   return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
24 }
25 
VP8LoadFinalBytes(VP8BitReader * const br)26 static void VP8LoadFinalBytes(VP8BitReader* const br) {
27   // Only read 8bits at a time.
28   if (br->buf_ < br->buf_end_) {
29     br->bits_ += 8;
30     br->value_ = static_cast<uint32_t>(*br->buf_++) | (br->value_ << 8);
31   } else if (!br->eof_) {
32     br->value_ <<= 8;
33     br->bits_ += 8;
34     br->eof_ = 1;
35   }
36 }
37 
VP8LoadNewBytes(VP8BitReader * const br)38 static void VP8LoadNewBytes(VP8BitReader* const br) {
39   int BITS = 24;
40   // Read 'BITS' bits at a time.
41   if (br->buf_ + sizeof(uint32_t) <= br->buf_end_) {
42     uint32_t bits;
43     const uint32_t in_bits = *(const uint32_t*)(br->buf_);
44     br->buf_ += BITS >> 3;
45 #if defined(WEBRTC_ARCH_BIG_ENDIAN)
46     bits = static_cast<uint32_t>(in_bits);
47     if (BITS != 8 * sizeof(uint32_t))
48       bits >>= (8 * sizeof(uint32_t) - BITS);
49 #else
50     bits = BSwap32(in_bits);
51     bits >>= 32 - BITS;
52 #endif
53     br->value_ = bits | (br->value_ << BITS);
54     br->bits_ += BITS;
55   } else {
56     VP8LoadFinalBytes(br);
57   }
58 }
59 
VP8InitBitReader(VP8BitReader * const br,const uint8_t * const start,const uint8_t * const end)60 static void VP8InitBitReader(VP8BitReader* const br,
61                              const uint8_t* const start,
62                              const uint8_t* const end) {
63   br->range_ = 255 - 1;
64   br->buf_ = start;
65   br->buf_end_ = end;
66   br->value_ = 0;
67   br->bits_ = -8;  // To load the very first 8bits.
68   br->eof_ = 0;
69   VP8LoadNewBytes(br);
70 }
71 
72 // Read a bit with proba 'prob'.
VP8GetBit(VP8BitReader * const br,int prob)73 static int VP8GetBit(VP8BitReader* const br, int prob) {
74   uint8_t range = br->range_;
75   if (br->bits_ < 0) {
76     VP8LoadNewBytes(br);
77   }
78 
79   const int pos = br->bits_;
80   const uint8_t split = (range * prob) >> 8;
81   const uint8_t value = static_cast<uint8_t>(br->value_ >> pos);
82   int bit;
83   if (value > split) {
84     range -= split + 1;
85     br->value_ -= static_cast<uint32_t>(split + 1) << pos;
86     bit = 1;
87   } else {
88     range = split;
89     bit = 0;
90   }
91   if (range <= static_cast<uint8_t>(0x7e)) {
92     const int shift = kVP8Log2Range[range];
93     range = kVP8NewRange[range];
94     br->bits_ -= shift;
95   }
96   br->range_ = range;
97   return bit;
98 }
99 
VP8GetValue(VP8BitReader * const br,int bits)100 static uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
101   uint32_t v = 0;
102   while (bits-- > 0) {
103     v |= VP8GetBit(br, 0x80) << bits;
104   }
105   return v;
106 }
107 
VP8Get(VP8BitReader * const br)108 static uint32_t VP8Get(VP8BitReader* const br) {
109   return VP8GetValue(br, 1);
110 }
111 
VP8GetSignedValue(VP8BitReader * const br,int bits)112 static int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
113   const int value = VP8GetValue(br, bits);
114   return VP8Get(br) ? -value : value;
115 }
116 
ParseSegmentHeader(VP8BitReader * br)117 static void ParseSegmentHeader(VP8BitReader* br) {
118   int use_segment = VP8Get(br);
119   if (use_segment) {
120     int update_map = VP8Get(br);
121     if (VP8Get(br)) {
122       int s;
123       VP8Get(br);
124       for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
125         VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
126       }
127       for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
128         VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
129       }
130     }
131     if (update_map) {
132       int s;
133       for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
134         VP8Get(br) ? VP8GetValue(br, 8) : 255;
135       }
136     }
137   }
138 }
139 
ParseFilterHeader(VP8BitReader * br)140 static void ParseFilterHeader(VP8BitReader* br) {
141   VP8Get(br);
142   VP8GetValue(br, 6);
143   VP8GetValue(br, 3);
144   int use_lf_delta = VP8Get(br);
145   if (use_lf_delta) {
146     if (VP8Get(br)) {
147       int i;
148       for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
149         if (VP8Get(br)) {
150           VP8GetSignedValue(br, 6);
151         }
152       }
153       for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
154         if (VP8Get(br)) {
155           VP8GetSignedValue(br, 6);
156         }
157       }
158     }
159   }
160 }
161 
GetQp(const uint8_t * buf,size_t length,int * qp)162 bool GetQp(const uint8_t* buf, size_t length, int* qp) {
163   if (length < kCommonPayloadHeaderLength) {
164     LOG(LS_WARNING) << "Failed to get QP, invalid length.";
165     return false;
166   }
167   VP8BitReader br;
168   const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
169   int key_frame = !(bits & 1);
170   // Size of first partition in bytes.
171   uint32_t partition_length = (bits >> 5);
172   size_t header_length = kCommonPayloadHeaderLength;
173   if (key_frame) {
174     header_length = kKeyPayloadHeaderLength;
175   }
176   if (header_length + partition_length > length) {
177     LOG(LS_WARNING) << "Failed to get QP, invalid length: " << length;
178     return false;
179   }
180   buf += header_length;
181 
182   VP8InitBitReader(&br, buf, buf + partition_length);
183   if (key_frame) {
184     // Color space and pixel type.
185     VP8Get(&br);
186     VP8Get(&br);
187   }
188   ParseSegmentHeader(&br);
189   ParseFilterHeader(&br);
190   // Number of coefficient data partitions.
191   VP8GetValue(&br, 2);
192   // Base QP.
193   const int base_q0 = VP8GetValue(&br, 7);
194   if (br.eof_ == 1) {
195     LOG(LS_WARNING) << "Failed to get QP, end of file reached.";
196     return false;
197   }
198   *qp = base_q0;
199   return true;
200 }
201 
202 }  // namespace vp8
203 
204 }  // namespace webrtc
205