OSUOSL/Nero are experiencing Internet connectivity problems. This affects us as we're hosted with OSUOSL. We apologize for the inconvenience.

Commit 10fea49b authored by Tom Finegan's avatar Tom Finegan

Add LEB128 encode/decode/tests.

BUG=aomedia:1125

Change-Id: I383c752cdd010001e8226ca510097ef693e486bb
parent 696a7c80
......@@ -146,7 +146,8 @@ set(AOM_SOURCES
"${AOM_ROOT}/aom/src/aom_codec.c"
"${AOM_ROOT}/aom/src/aom_decoder.c"
"${AOM_ROOT}/aom/src/aom_encoder.c"
"${AOM_ROOT}/aom/src/aom_image.c")
"${AOM_ROOT}/aom/src/aom_image.c"
"${AOM_ROOT}/aom/src/aom_integer.c")
set(AOM_COMMON_APP_UTIL_SOURCES
"${AOM_ROOT}/args.c"
......
......@@ -39,4 +39,5 @@ API_SRCS-yes += aom_codec.h
API_SRCS-yes += aom_codec.mk
API_SRCS-yes += aom_frame_buffer.h
API_SRCS-yes += aom_image.h
API_SRCS-yes += src/aom_integer.c
API_SRCS-yes += aom_integer.h
......@@ -75,4 +75,28 @@ typedef size_t uintptr_t;
#define NELEMENTS(x) (int)(sizeof(x) / sizeof(x[0]))
#if defined(__cplusplus)
extern "C" {
#endif // __cplusplus
// Returns size of uint32_t when encoded using LEB128.
size_t aom_uleb_size_in_bytes(uint32_t value);
// Returns decoded LEB128 value.
void aom_uleb_decode(const uint8_t *buffer, size_t available, uint32_t *value);
// Encodes LEB128 integer. Returns 0 when successful, and -1 upon failure.
int aom_uleb_encode(uint32_t value, size_t available, uint8_t *coded_value,
size_t *coded_size);
// Encodes LEB128 integer to size specified. Returns 0 when successful, and -1
// upon failure.
int aom_uleb_encode_fixed_size(uint32_t value, size_t available,
size_t pad_to_size, uint8_t *coded_value,
size_t *coded_size);
#if defined(__cplusplus)
} // extern "C"
#endif // __cplusplus
#endif // AOM_AOM_INTEGER_H_
......@@ -16,3 +16,7 @@ text aom_img_plane_width
text aom_img_plane_height
text aom_img_set_rect
text aom_img_wrap
text aom_uleb_decode
text aom_uleb_encode
text aom_uleb_encode_fixed_size
text aom_uleb_size_in_bytes
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "aom/aom_integer.h"
static const size_t kMaximumLeb128Size = 4;
static const size_t kMaximumLeb128Value = 0xFFFFFFF; // 2^28 - 1
static const uint8_t kLeb128ByteMask = 0x7f; // Binary: 01111111
static const uint8_t kLeb128PadByte = 0x80; // Binary: 10000000
size_t aom_uleb_size_in_bytes(uint32_t value) {
size_t size = 0;
do {
++size;
} while ((value >>= 7) != 0);
return size;
}
void aom_uleb_decode(const uint8_t *buffer, size_t available, uint32_t *value) {
if (buffer && value) {
for (size_t i = 0; i < kMaximumLeb128Size && i < available; ++i) {
const uint8_t decoded_byte = *(buffer + i) & kLeb128ByteMask;
*value |= decoded_byte << (i * 7);
}
}
}
int aom_uleb_encode(uint32_t value, size_t available, uint8_t *coded_value,
size_t *coded_size) {
const size_t leb_size = aom_uleb_size_in_bytes(value);
if (value > kMaximumLeb128Value || leb_size > kMaximumLeb128Size ||
leb_size > available || !coded_value || !coded_size) {
return -1;
}
for (size_t i = 0; i < leb_size; ++i) {
uint8_t byte = value & 0x7f;
value >>= 7;
if (value != 0) byte |= 0x80; // Signal that more bytes follow.
*(coded_value + i) = byte;
}
*coded_size = leb_size;
return 0;
}
int aom_uleb_encode_fixed_size(uint32_t value, size_t available,
size_t pad_to_size, uint8_t *coded_value,
size_t *coded_size) {
if (!coded_value || !coded_size || available < pad_to_size ||
aom_uleb_encode(value, available, coded_value, coded_size) != 0) {
return -1;
}
if (pad_to_size != *coded_size) {
if (*coded_size < pad_to_size) {
const size_t num_pad_bytes = pad_to_size - *coded_size;
for (size_t i = 0; i < num_pad_bytes; ++i) {
const size_t offset = *coded_size + i;
*(coded_value + offset) = kLeb128PadByte;
}
*coded_size += num_pad_bytes;
}
}
return 0;
}
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <stdint.h>
#include "aom/aom_integer.h"
#include "gtest/gtest.h"
namespace {
const uint32_t kSizeTestNumValues = 6;
const uint32_t kSizeTestExpectedSizes[kSizeTestNumValues] = {
1, 1, 2, 3, 4, 5
};
const uint32_t kSizeTestInputs[kSizeTestNumValues] = {
0, 0x7f, 0x3fff, 0x1fffff, 0xffffff, 0x10000000
};
} // namespace
TEST(AomLeb128, DecodeTest) {
const size_t num_leb128_bytes = 3;
const uint8_t leb128_bytes[num_leb128_bytes] = { 0xE5, 0x8E, 0x26 };
const uint32_t expected_value = 0x98765; // 624485
uint32_t value = 0;
aom_uleb_decode(&leb128_bytes[0], num_leb128_bytes, &value);
ASSERT_EQ(expected_value, value);
}
TEST(AomLeb128, EncodeTest) {
const uint32_t test_value = 0x98765; // 624485
const uint32_t expected_value = 0x00E58E26;
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(aom_uleb_encode(test_value, kWriteBufferSize, &write_buffer[0],
&bytes_written),
0);
ASSERT_EQ(bytes_written, 3u);
uint32_t encoded_value = 0;
for (size_t i = 0; i < bytes_written; ++i) {
const int shift = (bytes_written - 1 - i) * 8;
encoded_value |= write_buffer[i] << shift;
}
ASSERT_EQ(expected_value, encoded_value);
}
TEST(AomLeb128, EncDecTest) {
const uint32_t value = 0x98765; // 624485
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(aom_uleb_encode(value, kWriteBufferSize, &write_buffer[0],
&bytes_written),
0);
ASSERT_EQ(bytes_written, 3u);
uint32_t decoded_value = 0;
aom_uleb_decode(&write_buffer[0], bytes_written, &decoded_value);
ASSERT_EQ(value, decoded_value);
}
TEST(AomLeb128, FixedSizeEncodeTest) {
const uint32_t test_value = 0x0;
const uint32_t expected_value = 0x00808080;
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(0, aom_uleb_encode_fixed_size(test_value, kWriteBufferSize,
kWriteBufferSize, &write_buffer[0],
&bytes_written));
ASSERT_EQ(kWriteBufferSize, bytes_written);
uint32_t encoded_value = 0;
for (size_t i = 0; i < bytes_written; ++i) {
const int shift = (bytes_written - 1 - i) * 8;
encoded_value |= write_buffer[i] << shift;
}
ASSERT_EQ(expected_value, encoded_value);
}
TEST(AomLeb128, FixedSizeEncDecTest) {
const uint32_t value = 0x1;
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(
aom_uleb_encode_fixed_size(value, kWriteBufferSize, kWriteBufferSize,
&write_buffer[0], &bytes_written),
0);
ASSERT_EQ(bytes_written, 4u);
uint32_t decoded_value = 0;
aom_uleb_decode(&write_buffer[0], bytes_written, &decoded_value);
ASSERT_EQ(value, decoded_value);
}
TEST(AomLeb128, SizeTest) {
for (size_t i = 0; i < kSizeTestNumValues; ++i) {
ASSERT_EQ(kSizeTestExpectedSizes[i],
aom_uleb_size_in_bytes(kSizeTestInputs[i]));
}
}
......@@ -24,6 +24,7 @@ set(AOM_UNIT_TEST_WRAPPER_SOURCES
set(AOM_UNIT_TEST_COMMON_SOURCES
"${AOM_ROOT}/test/acm_random.h"
"${AOM_ROOT}/test/aom_integer_test.cc"
"${AOM_ROOT}/test/clear_system_state.h"
"${AOM_ROOT}/test/codec_factory.h"
"${AOM_ROOT}/test/decode_test_driver.cc"
......
......@@ -10,6 +10,7 @@
##
LIBAOM_TEST_SRCS-yes += acm_random.h
LIBAOM_TEST_SRCS-yes += aom_integer_test.cc
LIBAOM_TEST_SRCS-yes += clear_system_state.h
LIBAOM_TEST_SRCS-yes += codec_factory.h
LIBAOM_TEST_SRCS-yes += md5_helper.h
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment