mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 22:00:47 +01:00

This CL has been generated with the following script: for m in PLOG \ LOG_TAG \ LOG_GLEM \ LOG_GLE_EX \ LOG_GLE \ LAST_SYSTEM_ERROR \ LOG_ERRNO_EX \ LOG_ERRNO \ LOG_ERR_EX \ LOG_ERR \ LOG_V \ LOG_F \ LOG_T_F \ LOG_E \ LOG_T \ LOG_CHECK_LEVEL_V \ LOG_CHECK_LEVEL \ LOG do git grep -l $m | xargs sed -i "s,\b$m\b,RTC_$m,g" done git checkout rtc_base/logging.h git cl format Bug: webrtc:8452 Change-Id: I1a53ef3e0a5ef6e244e62b2e012b864914784600 Reviewed-on: https://webrtc-review.googlesource.com/21325 Reviewed-by: Niels Moller <nisse@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20617}
205 lines
5.2 KiB
C++
205 lines
5.2 KiB
C++
/*
|
|
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
#include "modules/video_coding/utility/vp8_header_parser.h"
|
|
|
|
#include "rtc_base/logging.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace vp8 {
|
|
namespace {
|
|
const size_t kCommonPayloadHeaderLength = 3;
|
|
const size_t kKeyPayloadHeaderLength = 10;
|
|
} // namespace
|
|
|
|
static uint32_t BSwap32(uint32_t x) {
|
|
return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
|
|
}
|
|
|
|
static void VP8LoadFinalBytes(VP8BitReader* const br) {
|
|
// Only read 8bits at a time.
|
|
if (br->buf_ < br->buf_end_) {
|
|
br->bits_ += 8;
|
|
br->value_ = static_cast<uint32_t>(*br->buf_++) | (br->value_ << 8);
|
|
} else if (!br->eof_) {
|
|
br->value_ <<= 8;
|
|
br->bits_ += 8;
|
|
br->eof_ = 1;
|
|
}
|
|
}
|
|
|
|
static void VP8LoadNewBytes(VP8BitReader* const br) {
|
|
int BITS = 24;
|
|
// Read 'BITS' bits at a time.
|
|
if (br->buf_ + sizeof(uint32_t) <= br->buf_end_) {
|
|
uint32_t bits;
|
|
const uint32_t in_bits = *(const uint32_t*)(br->buf_);
|
|
br->buf_ += BITS >> 3;
|
|
#if defined(WEBRTC_ARCH_BIG_ENDIAN)
|
|
bits = static_cast<uint32_t>(in_bits);
|
|
if (BITS != 8 * sizeof(uint32_t))
|
|
bits >>= (8 * sizeof(uint32_t) - BITS);
|
|
#else
|
|
bits = BSwap32(in_bits);
|
|
bits >>= 32 - BITS;
|
|
#endif
|
|
br->value_ = bits | (br->value_ << BITS);
|
|
br->bits_ += BITS;
|
|
} else {
|
|
VP8LoadFinalBytes(br);
|
|
}
|
|
}
|
|
|
|
static void VP8InitBitReader(VP8BitReader* const br,
|
|
const uint8_t* const start,
|
|
const uint8_t* const end) {
|
|
br->range_ = 255 - 1;
|
|
br->buf_ = start;
|
|
br->buf_end_ = end;
|
|
br->value_ = 0;
|
|
br->bits_ = -8; // To load the very first 8bits.
|
|
br->eof_ = 0;
|
|
VP8LoadNewBytes(br);
|
|
}
|
|
|
|
// Read a bit with proba 'prob'.
|
|
static int VP8GetBit(VP8BitReader* const br, int prob) {
|
|
uint8_t range = br->range_;
|
|
if (br->bits_ < 0) {
|
|
VP8LoadNewBytes(br);
|
|
if (br->eof_)
|
|
return 0;
|
|
}
|
|
const int pos = br->bits_;
|
|
const uint8_t split = (range * prob) >> 8;
|
|
const uint8_t value = static_cast<uint8_t>(br->value_ >> pos);
|
|
int bit;
|
|
if (value > split) {
|
|
range -= split + 1;
|
|
br->value_ -= static_cast<uint32_t>(split + 1) << pos;
|
|
bit = 1;
|
|
} else {
|
|
range = split;
|
|
bit = 0;
|
|
}
|
|
if (range <= static_cast<uint8_t>(0x7e)) {
|
|
const int shift = kVP8Log2Range[range];
|
|
range = kVP8NewRange[range];
|
|
br->bits_ -= shift;
|
|
}
|
|
br->range_ = range;
|
|
return bit;
|
|
}
|
|
|
|
static uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
|
|
uint32_t v = 0;
|
|
while (bits-- > 0) {
|
|
v |= VP8GetBit(br, 0x80) << bits;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
static uint32_t VP8Get(VP8BitReader* const br) {
|
|
return VP8GetValue(br, 1);
|
|
}
|
|
|
|
static int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
|
|
const int value = VP8GetValue(br, bits);
|
|
return VP8Get(br) ? -value : value;
|
|
}
|
|
|
|
static void ParseSegmentHeader(VP8BitReader* br) {
|
|
int use_segment = VP8Get(br);
|
|
if (use_segment) {
|
|
int update_map = VP8Get(br);
|
|
if (VP8Get(br)) {
|
|
int s;
|
|
VP8Get(br);
|
|
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
|
|
VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
|
|
}
|
|
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
|
|
VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
|
|
}
|
|
}
|
|
if (update_map) {
|
|
int s;
|
|
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
|
|
VP8Get(br) ? VP8GetValue(br, 8) : 255;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ParseFilterHeader(VP8BitReader* br) {
|
|
VP8Get(br);
|
|
VP8GetValue(br, 6);
|
|
VP8GetValue(br, 3);
|
|
int use_lf_delta = VP8Get(br);
|
|
if (use_lf_delta) {
|
|
if (VP8Get(br)) {
|
|
int i;
|
|
for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
|
|
if (VP8Get(br)) {
|
|
VP8GetSignedValue(br, 6);
|
|
}
|
|
}
|
|
for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
|
|
if (VP8Get(br)) {
|
|
VP8GetSignedValue(br, 6);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GetQp(const uint8_t* buf, size_t length, int* qp) {
|
|
if (length < kCommonPayloadHeaderLength) {
|
|
RTC_LOG(LS_WARNING) << "Failed to get QP, invalid length.";
|
|
return false;
|
|
}
|
|
VP8BitReader br;
|
|
const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
|
|
int key_frame = !(bits & 1);
|
|
// Size of first partition in bytes.
|
|
uint32_t partition_length = (bits >> 5);
|
|
size_t header_length = kCommonPayloadHeaderLength;
|
|
if (key_frame) {
|
|
header_length = kKeyPayloadHeaderLength;
|
|
}
|
|
if (header_length + partition_length > length) {
|
|
RTC_LOG(LS_WARNING) << "Failed to get QP, invalid length: " << length;
|
|
return false;
|
|
}
|
|
buf += header_length;
|
|
|
|
VP8InitBitReader(&br, buf, buf + partition_length);
|
|
if (key_frame) {
|
|
// Color space and pixel type.
|
|
VP8Get(&br);
|
|
VP8Get(&br);
|
|
}
|
|
ParseSegmentHeader(&br);
|
|
ParseFilterHeader(&br);
|
|
// Number of coefficient data partitions.
|
|
VP8GetValue(&br, 2);
|
|
// Base QP.
|
|
const int base_q0 = VP8GetValue(&br, 7);
|
|
if (br.eof_ == 1) {
|
|
RTC_LOG(LS_WARNING) << "Failed to get QP, end of file reached.";
|
|
return false;
|
|
}
|
|
*qp = base_q0;
|
|
return true;
|
|
}
|
|
|
|
} // namespace vp8
|
|
|
|
} // namespace webrtc
|