diff options
42 files changed, 544 insertions, 237 deletions
@@ -317,7 +317,6 @@ CONFIG_LIST=" multi_res_encoding temporal_denoising experimental - decrypt ${EXPERIMENT_LIST} " CMDLINE_SELECT=" @@ -371,7 +370,6 @@ CMDLINE_SELECT=" multi_res_encoding temporal_denoising experimental - decrypt " process_cmdline() { diff --git a/test/decode_to_md5.sh b/test/decode_to_md5.sh new file mode 100755 index 000000000..da1a87062 --- /dev/null +++ b/test/decode_to_md5.sh @@ -0,0 +1,68 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM 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. +## +## This file tests the libvpx decode_to_md5 example. To add new tests to this +## file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to decode_to_md5_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: Make sure input is available: +# $VP8_IVF_FILE and $VP9_IVF_FILE are required. +decode_to_md5_verify_environment() { + if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs decode_to_md5 on $1 and echoes the MD5 sum for the final frame. $2 is +# interpreted as codec name and used solely to name the output file. +decode_to_md5() { + local decoder="${LIBVPX_BIN_PATH}/decode_to_md5${VPX_TEST_EXE_SUFFIX}" + local input_file="$1" + local codec="$2" + local output_file="${VPX_TEST_OUTPUT_DIR}/decode_to_md5_${codec}" + + [ -x "${decoder}" ] || return 1 + + "${decoder}" "${input_file}" "${output_file}" > /dev/null 2>&1 + + [ -e "${output_file}" ] || return 1 + + local md5_last_frame=$(tail -n1 "${output_file}") + echo "${md5_last_frame% *}" | tr -d [:space:] +} + +decode_to_md5_vp8() { + # expected MD5 sum for the last frame. + local expected_md5="56794d911b02190212bca92f88ad60c6" + + if [ "$(vp8_decode_available)" = "yes" ]; then + local actual_md5="$(decode_to_md5 "${VP8_IVF_FILE}" vp8)" || return 1 + [ "${actual_md5}" = "${expected_md5}" ] || return 1 + fi +} + +decode_to_md5_vp9() { + # expected MD5 sum for the last frame. + local expected_md5="2952c0eae93f3dadd1aa84c50d3fd6d2" + + if [ "$(vp9_decode_available)" = "yes" ]; then + local actual_md5="$(decode_to_md5 "${VP9_IVF_FILE}" vp9)" || return 1 + [ "${actual_md5}" = "${expected_md5}" ] || return 1 + fi +} + +decode_to_md5_tests="decode_to_md5_vp8 + decode_to_md5_vp9" + +run_tests decode_to_md5_verify_environment "${decode_to_md5_tests}" diff --git a/test/external_frame_buffer_test.cc b/test/external_frame_buffer_test.cc index 54c79e903..fb0449deb 100644 --- a/test/external_frame_buffer_test.cc +++ b/test/external_frame_buffer_test.cc @@ -10,13 +10,16 @@ #include <string> +#include "./vpx_config.h" #include "test/codec_factory.h" #include "test/decode_test_driver.h" #include "test/ivf_video_source.h" #include "test/md5_helper.h" #include "test/test_vectors.h" #include "test/util.h" +#if CONFIG_WEBM_IO #include "test/webm_video_source.h" +#endif namespace { @@ -267,6 +270,7 @@ class ExternalFrameBufferMD5Test ExternalFrameBufferList fb_list_; }; +#if CONFIG_WEBM_IO // Class for testing passing in external frame buffers to libvpx. class ExternalFrameBufferTest : public ::testing::Test { protected: @@ -340,6 +344,7 @@ class ExternalFrameBufferTest : public ::testing::Test { int num_buffers_; ExternalFrameBufferList fb_list_; }; +#endif // CONFIG_WEBM_IO // This test runs through the set of test vectors, and decodes them. // Libvpx will call into the application to allocate a frame buffer when @@ -366,7 +371,13 @@ TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) { if (filename.substr(filename.length() - 3, 3) == "ivf") { video = new libvpx_test::IVFVideoSource(filename); } else { +#if CONFIG_WEBM_IO video = new libvpx_test::WebMVideoSource(filename); +#else + fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n", + filename.c_str()); + return; +#endif } ASSERT_TRUE(video != NULL); video->Init(); @@ -380,6 +391,7 @@ TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) { delete video; } +#if CONFIG_WEBM_IO TEST_F(ExternalFrameBufferTest, MinFrameBuffers) { // Minimum number of external frame buffers for VP9 is // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. @@ -460,6 +472,7 @@ TEST_F(ExternalFrameBufferTest, SetAfterDecode) { SetFrameBufferFunctions( num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer)); } +#endif // CONFIG_WEBM_IO VP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test, ::testing::ValuesIn(libvpx_test::kVP9TestVectors, diff --git a/test/simple_decoder.sh b/test/simple_decoder.sh new file mode 100755 index 000000000..a0db58ff8 --- /dev/null +++ b/test/simple_decoder.sh @@ -0,0 +1,57 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM 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. +## +## This file tests the libvpx simple_decoder example code. To add new tests to +## this file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to simple_decoder_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: Make sure input is available: +# $VP8_IVF_FILE and $VP9_IVF_FILE are required. +simple_decoder_verify_environment() { + if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs simple_decoder using $1 as input file. $2 is the codec name, and is used +# solely to name the output file. +simple_decoder() { + local decoder="${LIBVPX_BIN_PATH}/simple_decoder${VPX_TEST_EXE_SUFFIX}" + local input_file="$1" + local codec="$2" + local output_file="${VPX_TEST_OUTPUT_DIR}/simple_decoder_${codec}.raw" + + [ -x "${decoder}" ] || return 1 + + "${decoder}" "${input_file}" "${output_file}" > /dev/null 2>&1 + + [ -e "${output_file}" ] || return 1 +} + +simple_decoder_vp8() { + if [ "$(vp8_decode_available)" = "yes" ]; then + simple_decoder "${VP8_IVF_FILE}" vp8 || return 1 + fi +} + +simple_decoder_vp9() { + if [ "$(vp9_decode_available)" = "yes" ]; then + simple_decoder "${VP9_IVF_FILE}" vp9 || return 1 + fi +} + +simple_decoder_tests="simple_decoder_vp8 + simple_decoder_vp9" + +run_tests simple_decoder_verify_environment "${simple_decoder_tests}" diff --git a/test/test.mk b/test/test.mk index f1a8ed9a0..da56b00ec 100644 --- a/test/test.mk +++ b/test/test.mk @@ -42,6 +42,7 @@ LIBVPX_TEST_SRCS-yes += encode_test_driver.cc LIBVPX_TEST_SRCS-yes += encode_test_driver.h ## WebM Parsing +ifeq ($(CONFIG_WEBM_IO), yes) NESTEGG_SRCS += ../third_party/nestegg/halloc/halloc.h NESTEGG_SRCS += ../third_party/nestegg/halloc/src/align.h NESTEGG_SRCS += ../third_party/nestegg/halloc/src/halloc.c @@ -53,11 +54,14 @@ LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../tools_common.h LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../webmdec.c LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../webmdec.h LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += webm_video_source.h +endif LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += test_vector_test.cc -# Currently we only support decoder perf tests for vp9 -ifeq ($(CONFIG_DECODE_PERF_TESTS)$(CONFIG_VP9_DECODER), yesyes) +# Currently we only support decoder perf tests for vp9. Also they read from WebM +# files, so WebM IO is required. +ifeq ($(CONFIG_DECODE_PERF_TESTS)$(CONFIG_VP9_DECODER)$(CONFIG_WEBM_IO), \ + yesyesyes) LIBVPX_TEST_SRCS-yes += decode_perf_test.cc endif @@ -106,6 +110,7 @@ endif LIBVPX_TEST_SRCS-$(CONFIG_VP9) += convolve_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_thread_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_decrypt_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct4x4_test.cc diff --git a/test/test_vector_test.cc b/test/test_vector_test.cc index 9ba18daef..1f294f20b 100644 --- a/test/test_vector_test.cc +++ b/test/test_vector_test.cc @@ -12,13 +12,16 @@ #include <cstdlib> #include <string> #include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" #include "test/codec_factory.h" #include "test/decode_test_driver.h" #include "test/ivf_video_source.h" #include "test/md5_helper.h" #include "test/test_vectors.h" #include "test/util.h" +#if CONFIG_WEBM_IO #include "test/webm_video_source.h" +#endif #include "vpx_mem/vpx_mem.h" namespace { @@ -75,7 +78,13 @@ TEST_P(TestVectorTest, MD5Match) { if (filename.substr(filename.length() - 3, 3) == "ivf") { video = new libvpx_test::IVFVideoSource(filename); } else if (filename.substr(filename.length() - 4, 4) == "webm") { +#if CONFIG_WEBM_IO video = new libvpx_test::WebMVideoSource(filename); +#else + fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n", + filename.c_str()); + return; +#endif } video->Init(); diff --git a/test/tools_common.sh b/test/tools_common.sh index aa446c9c2..45b777178 100755 --- a/test/tools_common.sh +++ b/test/tools_common.sh @@ -416,6 +416,17 @@ if [ "$(is_windows_target)" = "yes" ]; then VPX_TEST_EXE_SUFFIX=".exe" fi +# Variables shared by tests. +VP8_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp80-00-comprehensive-001.ivf" +VP9_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-09-subpixel-00.ivf" + +VP9_WEBM_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-00-quantizer-00.webm" + +YUV_RAW_INPUT="${LIBVPX_TEST_DATA_PATH}/hantro_collage_w352h288.yuv" +YUV_RAW_INPUT_WIDTH=352 +YUV_RAW_INPUT_HEIGHT=288 + +# Setup a trap function to clean up after tests complete. trap cleanup EXIT if [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ]; then diff --git a/test/vp8_boolcoder_test.cc b/test/vp8_boolcoder_test.cc index 9cd198787..99b5f0c86 100644 --- a/test/vp8_boolcoder_test.cc +++ b/test/vp8_boolcoder_test.cc @@ -94,14 +94,10 @@ TEST(VP8, TestBitIO) { vp8_stop_encode(&bw); BOOL_DECODER br; -#if CONFIG_DECRYPT - encrypt_buffer(bw_buffer, buffer_size); - vp8dx_start_decode(&br, bw_buffer, buffer_size, + encrypt_buffer(bw_buffer, kBufferSize); + vp8dx_start_decode(&br, bw_buffer, kBufferSize, test_decrypt_cb, reinterpret_cast<void *>(bw_buffer)); -#else - vp8dx_start_decode(&br, bw_buffer, kBufferSize, NULL, NULL); -#endif bit_rnd.Reset(random_seed); for (int i = 0; i < kBitsToTest; ++i) { if (bit_method == 2) { diff --git a/test/vp8_decrypt_test.cc b/test/vp8_decrypt_test.cc index 1b5b08344..470fdf10d 100644 --- a/test/vp8_decrypt_test.cc +++ b/test/vp8_decrypt_test.cc @@ -43,7 +43,7 @@ void test_decrypt_cb(void *decrypt_state, const uint8_t *input, namespace libvpx_test { -TEST(TestDecrypt, DecryptWorks) { +TEST(TestDecrypt, DecryptWorksVp8) { libvpx_test::IVFVideoSource video("vp80-00-comprehensive-001.ivf"); video.Init(); @@ -59,14 +59,12 @@ TEST(TestDecrypt, DecryptWorks) { // decrypt frame video.Next(); -#if CONFIG_DECRYPT std::vector<uint8_t> encrypted(video.frame_size()); encrypt_buffer(video.cxdata(), &encrypted[0], video.frame_size(), 0); - vp8_decrypt_init di = { test_decrypt_cb, &encrypted[0] }; - decoder.Control(VP8D_SET_DECRYPTOR, &di); -#endif // CONFIG_DECRYPT + vpx_decrypt_init di = { test_decrypt_cb, &encrypted[0] }; + decoder.Control(VPXD_SET_DECRYPTOR, &di); - res = decoder.DecodeFrame(video.cxdata(), video.frame_size()); + res = decoder.DecodeFrame(&encrypted[0], encrypted.size()); ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); } diff --git a/test/vp9_boolcoder_test.cc b/test/vp9_boolcoder_test.cc index c579adeac..c7f0cd80f 100644 --- a/test/vp9_boolcoder_test.cc +++ b/test/vp9_boolcoder_test.cc @@ -70,7 +70,7 @@ TEST(VP9, TestBitIO) { GTEST_ASSERT_EQ(bw_buffer[0] & 0x80, 0); vp9_reader br; - vp9_reader_init(&br, bw_buffer, kBufferSize); + vp9_reader_init(&br, bw_buffer, kBufferSize, NULL, NULL); bit_rnd.Reset(random_seed); for (int i = 0; i < kBitsToTest; ++i) { if (bit_method == 2) { diff --git a/test/vp9_decrypt_test.cc b/test/vp9_decrypt_test.cc new file mode 100644 index 000000000..88a3c14f5 --- /dev/null +++ b/test/vp9_decrypt_test.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 The WebM 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 <cstdio> +#include <cstdlib> +#include <string> +#include <vector> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/ivf_video_source.h" + +namespace { +// In a real use the 'decrypt_state' parameter will be a pointer to a struct +// with whatever internal state the decryptor uses. For testing we'll just +// xor with a constant key, and decrypt_state will point to the start of +// the original buffer. +const uint8_t test_key[16] = { + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0 +}; + +void encrypt_buffer(const uint8_t *src, uint8_t *dst, size_t size, + ptrdiff_t offset) { + for (size_t i = 0; i < size; ++i) { + dst[i] = src[i] ^ test_key[(offset + i) & 15]; + } +} + +void test_decrypt_cb(void *decrypt_state, const uint8_t *input, + uint8_t *output, int count) { + encrypt_buffer(input, output, count, + input - reinterpret_cast<uint8_t *>(decrypt_state)); +} + +} // namespace + +namespace libvpx_test { + +TEST(TestDecrypt, DecryptWorksVp9) { + libvpx_test::IVFVideoSource video("vp90-2-05-resize.ivf"); + video.Init(); + + vpx_codec_dec_cfg_t dec_cfg = {0}; + VP9Decoder decoder(dec_cfg, 0); + + video.Begin(); + + // no decryption + vpx_codec_err_t res = decoder.DecodeFrame(video.cxdata(), video.frame_size()); + ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); + + // decrypt frame + video.Next(); + + std::vector<uint8_t> encrypted(video.frame_size()); + encrypt_buffer(video.cxdata(), &encrypted[0], video.frame_size(), 0); + vpx_decrypt_init di = { test_decrypt_cb, &encrypted[0] }; + decoder.Control(VPXD_SET_DECRYPTOR, &di); + + res = decoder.DecodeFrame(&encrypted[0], encrypted.size()); + ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); +} + +} // namespace libvpx_test diff --git a/test/vp9_thread_test.cc b/test/vp9_thread_test.cc index 5523f2024..0c9f71bc5 100644 --- a/test/vp9_thread_test.cc +++ b/test/vp9_thread_test.cc @@ -11,10 +11,13 @@ #include <string> #include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" #include "test/codec_factory.h" #include "test/decode_test_driver.h" #include "test/md5_helper.h" +#if CONFIG_WEBM_IO #include "test/webm_video_source.h" +#endif #include "vp9/decoder/vp9_thread.h" namespace { @@ -97,6 +100,7 @@ TEST_P(VP9WorkerThreadTest, HookFailure) { // ----------------------------------------------------------------------------- // Multi-threaded decode tests +#if CONFIG_WEBM_IO // Decodes |filename| with |num_threads|. Returns the md5 of the decoded frames. string DecodeFile(const string& filename, int num_threads) { libvpx_test::WebMVideoSource video(filename); @@ -212,6 +216,7 @@ TEST(VP9DecodeMTTest, MTDecode3) { } } } +#endif // CONFIG_WEBM_IO INSTANTIATE_TEST_CASE_P(Synchronous, VP9WorkerThreadTest, ::testing::Bool()); diff --git a/test/vpxdec.sh b/test/vpxdec.sh index d236f973b..093230b69 100755 --- a/test/vpxdec.sh +++ b/test/vpxdec.sh @@ -14,9 +14,6 @@ ## . $(dirname $0)/tools_common.sh -VP8_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp80-00-comprehensive-001.ivf" -VP9_WEBM_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-00-quantizer-00.webm" - # Environment check: Make sure input is available. vpxdec_verify_environment() { if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_WEBM_FILE}" ]; then diff --git a/test/vpxenc.sh b/test/vpxenc.sh index 89e4eb39c..f08c04878 100755 --- a/test/vpxenc.sh +++ b/test/vpxenc.sh @@ -15,9 +15,6 @@ ## . $(dirname $0)/tools_common.sh -YUV_RAW_INPUT="${LIBVPX_TEST_DATA_PATH}/hantro_collage_w352h288.yuv" -YUV_RAW_INPUT_WIDTH=352 -YUV_RAW_INPUT_HEIGHT=288 TEST_FRAMES=10 # Environment check: Make sure input is available. diff --git a/vp8/common/common.h b/vp8/common/common.h index ee5b58c75..17262d698 100644 --- a/vp8/common/common.h +++ b/vp8/common/common.h @@ -22,6 +22,9 @@ extern "C" { #endif +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + /* Only need this for fixed-size arrays, for structs just assign. */ #define vp8_copy( Dest, Src) { \ diff --git a/vp8/decoder/dboolhuff.c b/vp8/decoder/dboolhuff.c index 0007d7a7a..b874d4c46 100644 --- a/vp8/decoder/dboolhuff.c +++ b/vp8/decoder/dboolhuff.c @@ -10,11 +10,12 @@ #include "dboolhuff.h" +#include "vp8/common/common.h" int vp8dx_start_decode(BOOL_DECODER *br, const unsigned char *source, unsigned int source_sz, - vp8_decrypt_cb *decrypt_cb, + vpx_decrypt_cb decrypt_cb, void *decrypt_state) { br->user_buffer_end = source+source_sz; @@ -39,7 +40,7 @@ void vp8dx_bool_decoder_fill(BOOL_DECODER *br) const unsigned char *bufptr = br->user_buffer; VP8_BD_VALUE value = br->value; int count = br->count; - int shift = VP8_BD_VALUE_SIZE - 8 - (count + 8); + int shift = VP8_BD_VALUE_SIZE - CHAR_BIT - (count + CHAR_BIT); size_t bytes_left = br->user_buffer_end - bufptr; size_t bits_left = bytes_left * CHAR_BIT; int x = (int)(shift + CHAR_BIT - bits_left); @@ -47,7 +48,7 @@ void vp8dx_bool_decoder_fill(BOOL_DECODER *br) unsigned char decrypted[sizeof(VP8_BD_VALUE) + 1]; if (br->decrypt_cb) { - size_t n = bytes_left > sizeof(decrypted) ? sizeof(decrypted) : bytes_left; + size_t n = MIN(sizeof(decrypted), bytes_left); br->decrypt_cb(br->decrypt_state, bufptr, decrypted, (int)n); bufptr = decrypted; } diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h index 36af7eed5..51c5adc28 100644 --- a/vp8/decoder/dboolhuff.h +++ b/vp8/decoder/dboolhuff.h @@ -17,6 +17,7 @@ #include "vpx_config.h" #include "vpx_ports/mem.h" +#include "vpx/vp8dx.h" #include "vpx/vpx_integer.h" #ifdef __cplusplus @@ -32,12 +33,6 @@ typedef size_t VP8_BD_VALUE; Even relatively modest values like 100 would work fine.*/ #define VP8_LOTS_OF_BITS (0x40000000) -/*Decrypt n bytes of data from input -> output, using the decrypt_state - passed in VP8D_SET_DECRYPTOR. -*/ -typedef void (vp8_decrypt_cb)(void *decrypt_state, const unsigned char *input, - unsigned char *output, int count); - typedef struct { const unsigned char *user_buffer_end; @@ -45,7 +40,7 @@ typedef struct VP8_BD_VALUE value; int count; unsigned int range; - vp8_decrypt_cb *decrypt_cb; + vpx_decrypt_cb decrypt_cb; void *decrypt_state; } BOOL_DECODER; @@ -54,7 +49,7 @@ DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]); int vp8dx_start_decode(BOOL_DECODER *br, const unsigned char *source, unsigned int source_sz, - vp8_decrypt_cb *decrypt_cb, + vpx_decrypt_cb decrypt_cb, void *decrypt_state); void vp8dx_bool_decoder_fill(BOOL_DECODER *br); diff --git a/vp8/decoder/decodeframe.c b/vp8/decoder/decodeframe.c index 14f611ad9..e7cf0d9b9 100644 --- a/vp8/decoder/decodeframe.c +++ b/vp8/decoder/decodeframe.c @@ -17,6 +17,7 @@ #include "vp8/common/reconintra4x4.h" #include "vp8/common/reconinter.h" #include "detokenize.h" +#include "vp8/common/common.h" #include "vp8/common/invtrans.h" #include "vp8/common/alloccommon.h" #include "vp8/common/entropymode.h" @@ -1018,8 +1019,7 @@ int vp8_decode_frame(VP8D_COMP *pbi) const unsigned char *clear = data; if (pbi->decrypt_cb) { - int n = (int)(data_end - data); - if (n > 10) n = 10; + int n = (int)MIN(sizeof(clear_buffer), data_end - data); pbi->decrypt_cb(pbi->decrypt_state, data, clear_buffer, n); clear = clear_buffer; } diff --git a/vp8/decoder/error_concealment.c b/vp8/decoder/error_concealment.c index 0b58c98fd..4b304c83c 100644 --- a/vp8/decoder/error_concealment.c +++ b/vp8/decoder/error_concealment.c @@ -15,9 +15,7 @@ #include "decodemv.h" #include "vpx_mem/vpx_mem.h" #include "vp8/common/findnearmv.h" - -#define MIN(x,y) (((x)<(y))?(x):(y)) -#define MAX(x,y) (((x)>(y))?(x):(y)) +#include "vp8/common/common.h" #define FLOOR(x,q) ((x) & -(1 << (q))) diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h index 8ef489403..aa2cc57f7 100644 --- a/vp8/decoder/onyxd_int.h +++ b/vp8/decoder/onyxd_int.h @@ -126,7 +126,7 @@ typedef struct VP8D_COMP int independent_partitions; int frame_corrupt_residual; - vp8_decrypt_cb *decrypt_cb; + vpx_decrypt_cb decrypt_cb; void *decrypt_state; } VP8D_COMP; diff --git a/vp8/encoder/mcomp.c b/vp8/encoder/mcomp.c index 0b11ea64a..54abe76ac 100644 --- a/vp8/encoder/mcomp.c +++ b/vp8/encoder/mcomp.c @@ -17,6 +17,7 @@ #include <limits.h> #include <math.h> #include "vp8/common/findnearmv.h" +#include "vp8/common/common.h" #ifdef VP8_ENTROPY_STATS static int mv_ref_ct [31] [4] [2]; diff --git a/vp8/encoder/mr_dissim.c b/vp8/encoder/mr_dissim.c index 71218cca1..8d96445f5 100644 --- a/vp8/encoder/mr_dissim.c +++ b/vp8/encoder/mr_dissim.c @@ -15,6 +15,7 @@ #include "mr_dissim.h" #include "vpx_mem/vpx_mem.h" #include "rdopt.h" +#include "vp8/common/common.h" void vp8_cal_low_res_mb_cols(VP8_COMP *cpi) { diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 6b371671d..df17dff34 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -61,9 +61,6 @@ extern "C" { #define VP8_TEMPORAL_ALT_REF 1 #endif -#define MAX(x,y) (((x)>(y))?(x):(y)) -#define MIN(x,y) (((x)<(y))?(x):(y)) - typedef struct { int kf_indicated; diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index c5279fed2..39a3baf10 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -14,6 +14,7 @@ #include "onyx_int.h" #include "modecosts.h" #include "encodeintra.h" +#include "vp8/common/common.h" #include "vp8/common/entropymode.h" #include "pickinter.h" #include "vp8/common/findnearmv.h" diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index d75d25859..10cbc6a58 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -16,9 +16,10 @@ #include "vpx/vp8dx.h" #include "vpx/internal/vpx_codec_internal.h" #include "vpx_version.h" +#include "common/alloccommon.h" +#include "common/common.h" #include "common/onyxd.h" #include "decoder/onyxd_int.h" -#include "common/alloccommon.h" #include "vpx_mem/vpx_mem.h" #if CONFIG_ERROR_CONCEALMENT #include "decoder/error_concealment.h" @@ -56,7 +57,7 @@ struct vpx_codec_alg_priv int dbg_color_b_modes_flag; int dbg_display_mv_flag; #endif - vp8_decrypt_cb *decrypt_cb; + vpx_decrypt_cb decrypt_cb; void *decrypt_state; vpx_image_t img; int img_setup; @@ -156,7 +157,7 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) static vpx_codec_err_t vp8_peek_si_internal(const uint8_t *data, unsigned int data_sz, vpx_codec_stream_info_t *si, - vp8_decrypt_cb *decrypt_cb, + vpx_decrypt_cb decrypt_cb, void *decrypt_state) { vpx_codec_err_t res = VPX_CODEC_OK; @@ -177,7 +178,7 @@ static vpx_codec_err_t vp8_peek_si_internal(const uint8_t *data, const uint8_t *clear = data; if (decrypt_cb) { - int n = data_sz > 10 ? 10 : data_sz; + int n = MIN(sizeof(clear_buffer), data_sz); decrypt_cb(decrypt_state, data, clear_buffer, n); clear = clear_buffer; } @@ -379,12 +380,15 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, } res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf); - ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb; - ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state; - ctx->decoder_init = 1; } + /* Set these even if already initialized. The caller may have changed the + * decrypt config between frames. + */ + ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb; + ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state; + if (!res) { VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0]; @@ -722,7 +726,7 @@ static vpx_codec_err_t vp8_set_decryptor(vpx_codec_alg_priv_t *ctx, int ctrl_id, va_list args) { - vp8_decrypt_init *init = va_arg(args, vp8_decrypt_init *); + vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *); if (init) { @@ -749,7 +753,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] = {VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates}, {VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted}, {VP8D_GET_LAST_REF_USED, vp8_get_last_ref_frame}, - {VP8D_SET_DECRYPTOR, vp8_set_decryptor}, + {VPXD_SET_DECRYPTOR, vp8_set_decryptor}, { -1, NULL}, }; diff --git a/vp9/common/vp9_rtcd_defs.pl b/vp9/common/vp9_rtcd_defs.pl index 8a8155410..295dd780e 100644 --- a/vp9/common/vp9_rtcd_defs.pl +++ b/vp9/common/vp9_rtcd_defs.pl @@ -678,9 +678,6 @@ specialize qw/vp9_sad4x8x4d sse/; add_proto qw/void vp9_sad4x4x4d/, "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array"; specialize qw/vp9_sad4x4x4d sse/; -#add_proto qw/unsigned int vp9_sub_pixel_mse16x16/, "const uint8_t *src_ptr, int src_pixels_per_line, int xoffset, int yoffset, const uint8_t *dst_ptr, int dst_pixels_per_line, unsigned int *sse"; -#specialize qw/vp9_sub_pixel_mse16x16 sse2 mmx/; - add_proto qw/unsigned int vp9_mse16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int recon_stride, unsigned int *sse"; specialize qw/vp9_mse16x16 mmx/, "$sse2_x86inc", "$avx2_x86inc"; @@ -693,12 +690,6 @@ specialize qw/vp9_mse16x8/; add_proto qw/unsigned int vp9_mse8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int recon_stride, unsigned int *sse"; specialize qw/vp9_mse8x8/; -add_proto qw/unsigned int vp9_sub_pixel_mse64x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"; -specialize qw/vp9_sub_pixel_mse64x64/; - -add_proto qw/unsigned int vp9_sub_pixel_mse32x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"; -specialize qw/vp9_sub_pixel_mse32x32/; - add_proto qw/unsigned int vp9_get_mb_ss/, "const int16_t *"; specialize qw/vp9_get_mb_ss mmx sse2/; # ENCODEMB INVOKE diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index b953452c5..1cc7ab727 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -40,6 +40,8 @@ #include "vp9/decoder/vp9_reader.h" #include "vp9/decoder/vp9_thread.h" +#define MAX_VP9_HEADER_SIZE 80 + static int is_compound_reference_allowed(const VP9_COMMON *cm) { int i; for (i = 1; i < REFS_PER_FRAME; ++i) @@ -451,7 +453,9 @@ static void setup_token_decoder(const uint8_t *data, const uint8_t *data_end, size_t read_size, struct vpx_internal_error_info *error_info, - vp9_reader *r) { + vp9_reader *r, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { // Validate the calculated partition length. If the buffer // described by the partition can't be fully read, then restrict // it to the portion that can be (for EC mode) or throw an error. @@ -459,7 +463,7 @@ static void setup_token_decoder(const uint8_t *data, vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME, "Truncated packet or corrupt tile length"); - if (vp9_reader_init(r, data, read_size)) + if (vp9_reader_init(r, data, read_size, decrypt_cb, decrypt_state)) vpx_internal_error(error_info, VPX_CODEC_MEM_ERROR, "Failed to allocate bool decoder %d", 1); } @@ -750,7 +754,9 @@ static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { static size_t get_tile(const uint8_t *const data_end, int is_last, struct vpx_internal_error_info *error_info, - const uint8_t **data) { + const uint8_t **data, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { size_t size; if (!is_last) { @@ -758,7 +764,13 @@ static size_t get_tile(const uint8_t *const data_end, vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME, "Truncated packet or corrupt tile length"); - size = mem_get_be32(*data); + if (decrypt_cb) { + uint8_t be_data[4]; + decrypt_cb(decrypt_state, *data, be_data, 4); + size = mem_get_be32(be_data); + } else { + size = mem_get_be32(*data); + } *data += 4; if (size > (size_t)(data_end - *data)) @@ -804,7 +816,8 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi, for (tile_col = 0; tile_col < tile_cols; ++tile_col) { const int last_tile = tile_row == tile_rows - 1 && tile_col == tile_cols - 1; - const size_t size = get_tile(data_end, last_tile, &cm->error, &data); + const size_t size = get_tile(data_end, last_tile, &cm->error, &data, + pbi->decrypt_cb, pbi->decrypt_state); TileBuffer *const buf = &tile_buffers[tile_row][tile_col]; buf->data = data; buf->size = size; @@ -823,7 +836,8 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi, TileInfo tile; vp9_tile_init(&tile, cm, tile_row, col); - setup_token_decoder(buf->data, data_end, buf->size, &cm->error, &r); + setup_token_decoder(buf->data, data_end, buf->size, &cm->error, &r, + pbi->decrypt_cb, pbi->decrypt_state); decode_tile(pbi, &tile, &r); if (last_tile) @@ -921,7 +935,8 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, // Load tile data into tile_buffers for (n = 0; n < tile_cols; ++n) { const size_t size = - get_tile(data_end, n == tile_cols - 1, &cm->error, &data); + get_tile(data_end, n == tile_cols - 1, &cm->error, &data, + pbi->decrypt_cb, pbi->decrypt_state); TileBuffer *const buf = &tile_buffers[n]; buf->data = data; buf->size = size; @@ -962,7 +977,8 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, tile_data->xd.corrupted = 0; vp9_tile_init(tile, tile_data->cm, 0, buf->col); setup_token_decoder(buf->data, data_end, buf->size, &cm->error, - &tile_data->bit_reader); + &tile_data->bit_reader, pbi->decrypt_cb, + pbi->decrypt_state); init_macroblockd(cm, &tile_data->xd); vp9_zero(tile_data->xd.dqcoeff); @@ -1163,7 +1179,8 @@ static int read_compressed_header(VP9Decoder *pbi, const uint8_t *data, vp9_reader r; int k; - if (vp9_reader_init(&r, data, partition_size)) + if (vp9_reader_init(&r, data, partition_size, pbi->decrypt_cb, + pbi->decrypt_state)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to allocate bool decoder 0"); @@ -1255,14 +1272,36 @@ static void debug_check_frame_counts(const VP9_COMMON *const cm) { } #endif // NDEBUG +static struct vp9_read_bit_buffer* init_read_bit_buffer( + VP9Decoder *pbi, + struct vp9_read_bit_buffer *rb, + const uint8_t *data, + const uint8_t *data_end, + uint8_t *clear_data /* buffer size MAX_VP9_HEADER_SIZE */) { + rb->bit_offset = 0; + rb->error_handler = error_handler; + rb->error_handler_data = &pbi->common; + if (pbi->decrypt_cb) { + const int n = (int)MIN(MAX_VP9_HEADER_SIZE, data_end - data); + pbi->decrypt_cb(pbi->decrypt_state, data, clear_data, n); + rb->bit_buffer = clear_data; + rb->bit_buffer_end = clear_data + n; + } else { + rb->bit_buffer = data; + rb->bit_buffer_end = data_end; + } + return rb; +} + int vp9_decode_frame(VP9Decoder *pbi, const uint8_t *data, const uint8_t *data_end, const uint8_t **p_data_end) { VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; - - struct vp9_read_bit_buffer rb = { data, data_end, 0, cm, error_handler }; - const size_t first_partition_size = read_uncompressed_header(pbi, &rb); + struct vp9_read_bit_buffer rb = { 0 }; + uint8_t clear_data[MAX_VP9_HEADER_SIZE]; + const size_t first_partition_size = read_uncompressed_header(pbi, + init_read_bit_buffer(pbi, &rb, data, data_end, clear_data)); const int keyframe = cm->frame_type == KEY_FRAME; const int tile_rows = 1 << cm->log2_tile_rows; const int tile_cols = 1 << cm->log2_tile_cols; @@ -1270,9 +1309,9 @@ int vp9_decode_frame(VP9Decoder *pbi, xd->cur_buf = new_fb; if (!first_partition_size) { - // showing a frame directly - *p_data_end = data + 1; - return 0; + // showing a frame directly + *p_data_end = data + 1; + return 0; } if (!pbi->decoded_key_frame && !keyframe) diff --git a/vp9/decoder/vp9_decoder.h b/vp9/decoder/vp9_decoder.h index 800f5d337..ebcbb9067 100644 --- a/vp9/decoder/vp9_decoder.h +++ b/vp9/decoder/vp9_decoder.h @@ -56,6 +56,9 @@ typedef struct VP9Decoder { int num_tile_workers; VP9LfSync lf_row_sync; + + vpx_decrypt_cb decrypt_cb; + void *decrypt_state; } VP9Decoder; void vp9_initialize_dec(); diff --git a/vp9/decoder/vp9_reader.c b/vp9/decoder/vp9_reader.c index fb44c8898..6bb4f9f73 100644 --- a/vp9/decoder/vp9_reader.c +++ b/vp9/decoder/vp9_reader.c @@ -18,7 +18,11 @@ // Even relatively modest values like 100 would work fine. #define LOTS_OF_BITS 0x40000000 -int vp9_reader_init(vp9_reader *r, const uint8_t *buffer, size_t size) { +int vp9_reader_init(vp9_reader *r, + const uint8_t *buffer, + size_t size, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { if (size && !buffer) { return 1; } else { @@ -27,6 +31,8 @@ int vp9_reader_init(vp9_reader *r, const uint8_t *buffer, size_t size) { r->value = 0; r->count = -8; r->range = 255; + r->decrypt_cb = decrypt_cb; + r->decrypt_state = decrypt_state; vp9_reader_fill(r); return vp9_read_bit(r) != 0; // marker bit } @@ -35,12 +41,21 @@ int vp9_reader_init(vp9_reader *r, const uint8_t *buffer, size_t size) { void vp9_reader_fill(vp9_reader *r) { const uint8_t *const buffer_end = r->buffer_end; const uint8_t *buffer = r->buffer; + const uint8_t *buffer_start = buffer; BD_VALUE value = r->value; int count = r->count; int shift = BD_VALUE_SIZE - CHAR_BIT - (count + CHAR_BIT); int loop_end = 0; - const int bits_left = (int)((buffer_end - buffer) * CHAR_BIT); - const int x = shift + CHAR_BIT - bits_left; + const size_t bytes_left = buffer_end - buffer; + const size_t bits_left = bytes_left * CHAR_BIT; + const int x = (int)(shift + CHAR_BIT - bits_left); + + if (r->decrypt_cb) { + size_t n = MIN(sizeof(r->clear_buffer), bytes_left); + r->decrypt_cb(r->decrypt_state, buffer, r->clear_buffer, (int)n); + buffer = r->clear_buffer; + buffer_start = r->clear_buffer; + } if (x >= 0) { count += LOTS_OF_BITS; @@ -55,7 +70,10 @@ void vp9_reader_fill(vp9_reader *r) { } } - r->buffer = buffer; + // NOTE: Variable 'buffer' may not relate to 'r->buffer' after decryption, + // so we increase 'r->buffer' by the amount that 'buffer' moved, rather than + // assign 'buffer' to 'r->buffer'. + r->buffer += buffer - buffer_start; r->value = value; r->count = count; } diff --git a/vp9/decoder/vp9_reader.h b/vp9/decoder/vp9_reader.h index 8fe6acbc2..32e200e2b 100644 --- a/vp9/decoder/vp9_reader.h +++ b/vp9/decoder/vp9_reader.h @@ -16,6 +16,7 @@ #include "./vpx_config.h" #include "vpx_ports/mem.h" +#include "vpx/vp8dx.h" #include "vpx/vpx_integer.h" #include "vp9/common/vp9_prob.h" @@ -31,12 +32,19 @@ typedef size_t BD_VALUE; typedef struct { const uint8_t *buffer_end; const uint8_t *buffer; + uint8_t clear_buffer[sizeof(BD_VALUE) + 1]; BD_VALUE value; int count; unsigned int range; + vpx_decrypt_cb decrypt_cb; + void *decrypt_state; } vp9_reader; -int vp9_reader_init(vp9_reader *r, const uint8_t *buffer, size_t size); +int vp9_reader_init(vp9_reader *r, + const uint8_t *buffer, + size_t size, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state); void vp9_reader_fill(vp9_reader *r); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 370825883..6816f555e 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -829,7 +829,6 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) { sizeof(*cpi->mbgraph_stats[i].mb_stats), 1)); } - cpi->key_frame_frequency = cpi->oxcf.key_freq; cpi->refresh_alt_ref_frame = 0; #if CONFIG_MULTIPLE_ARF diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index de8f3c914..8f3249407 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -337,8 +337,6 @@ typedef struct VP9_COMP { YV12_BUFFER_CONFIG *unscaled_last_source; YV12_BUFFER_CONFIG scaled_last_source; - int key_frame_frequency; - int gold_is_last; // gold same as last frame ( short circuit gold searches) int alt_is_last; // Alt same as last ( short circuit altref search) int gold_is_alt; // don't do both alt and gold search ( just do gold). diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 314f8ab84..3d4b96259 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -1935,7 +1935,8 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Find the next keyframe. i = 0; - while (twopass->stats_in < twopass->stats_in_end) { + while (twopass->stats_in < twopass->stats_in_end && + rc->frames_to_key < cpi->oxcf.key_freq) { // Accumulate kf group error. kf_group_err += calculate_modified_err(cpi, this_frame); @@ -1965,7 +1966,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Special check for transition or high motion followed by a // static scene. - if (detect_transition_to_still(twopass, i, cpi->key_frame_frequency - i, + if (detect_transition_to_still(twopass, i, cpi->oxcf.key_freq - i, loop_decay_rate, decay_accumulator)) break; @@ -1973,8 +1974,8 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ++rc->frames_to_key; // If we don't have a real key frame within the next two - // key_frame_frequency intervals then break out of the loop. - if (rc->frames_to_key >= 2 * (int)cpi->key_frame_frequency) + // key_freq intervals then break out of the loop. + if (rc->frames_to_key >= 2 * cpi->oxcf.key_freq) break; } else { ++rc->frames_to_key; @@ -1987,7 +1988,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // This code centers the extra kf if the actual natural interval // is between 1x and 2x. if (cpi->oxcf.auto_key && - rc->frames_to_key > (int)cpi->key_frame_frequency) { + rc->frames_to_key > cpi->oxcf.key_freq) { FIRSTPASS_STATS tmp_frame = first_frame; rc->frames_to_key /= 2; @@ -2003,7 +2004,8 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { input_stats(twopass, &tmp_frame); } rc->next_key_frame_forced = 1; - } else if (twopass->stats_in == twopass->stats_in_end) { + } else if (twopass->stats_in == twopass->stats_in_end || + rc->frames_to_key >= cpi->oxcf.key_freq) { rc->next_key_frame_forced = 1; } else { rc->next_key_frame_forced = 0; diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c index 89937f5a6..07a04cd4d 100644 --- a/vp9/encoder/vp9_mcomp.c +++ b/vp9/encoder/vp9_mcomp.c @@ -1290,84 +1290,65 @@ int vp9_full_search_sadx3(const MACROBLOCK *x, const MV *ref_mv, int sad_per_bit, int distance, const vp9_variance_fn_ptr_t *fn_ptr, const MV *center_mv, MV *best_mv) { + int r; const MACROBLOCKD *const xd = &x->e_mbd; - const uint8_t *const what = x->plane[0].src.buf; - const int what_stride = x->plane[0].src.stride; - const uint8_t *const in_what = xd->plane[0].pre[0].buf; - const int in_what_stride = xd->plane[0].pre[0].stride; - MV this_mv; - unsigned int bestsad = INT_MAX; - int r, c; - unsigned int thissad; - int ref_row = ref_mv->row; - int ref_col = ref_mv->col; - - // Apply further limits to prevent us looking using vectors that stretch - // beyond the UMV border - const int row_min = MAX(ref_row - distance, x->mv_row_min); - const int row_max = MIN(ref_row + distance, x->mv_row_max); - const int col_min = MAX(ref_col - distance, x->mv_col_min); - const int col_max = MIN(ref_col + distance, x->mv_col_max); - unsigned int sad_array[3]; + const struct buf_2d *const what = &x->plane[0].src; + const struct buf_2d *const in_what = &xd->plane[0].pre[0]; + const int row_min = MAX(ref_mv->row - distance, x->mv_row_min); + const int row_max = MIN(ref_mv->row + distance, x->mv_row_max); + const int col_min = MAX(ref_mv->col - distance, x->mv_col_min); + const int col_max = MIN(ref_mv->col + distance, x->mv_col_max); const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3}; + unsigned int best_sad = fn_ptr->sdf(what->buf, what->stride, + get_buf_from_mv(in_what, ref_mv), in_what->stride, 0x7fffffff) + + mvsad_err_cost(x, ref_mv, &fcenter_mv, sad_per_bit); + *best_mv = *ref_mv; - // Work out the mid point for the search - const uint8_t *bestaddress = &in_what[ref_row * in_what_stride + ref_col]; - - best_mv->row = ref_row; - best_mv->col = ref_col; - - // Baseline value at the centre - bestsad = fn_ptr->sdf(what, what_stride, - bestaddress, in_what_stride, 0x7fffffff) - + mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit); - - for (r = row_min; r < row_max; r++) { - const uint8_t *check_here = &in_what[r * in_what_stride + col_min]; - this_mv.row = r; - c = col_min; - - while ((c + 2) < col_max && fn_ptr->sdx3f != NULL) { - int i; + for (r = row_min; r < row_max; ++r) { + int c = col_min; + const uint8_t *check_here = &in_what->buf[r * in_what->stride + c]; - fn_ptr->sdx3f(what, what_stride, check_here, in_what_stride, sad_array); + if (fn_ptr->sdx3f != NULL) { + while ((c + 2) < col_max) { + int i; + unsigned int sads[3]; - for (i = 0; i < 3; i++) { - thissad = sad_array[i]; + fn_ptr->sdx3f(what->buf, what->stride, check_here, in_what->stride, + sads); - if (thissad < bestsad) { - this_mv.col = c; - thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit); - if (thissad < bestsad) { - bestsad = thissad; - best_mv->row = r; - best_mv->col = c; + for (i = 0; i < 3; ++i) { + unsigned int sad = sads[i]; + if (sad < best_sad) { + const MV mv = {r, c}; + sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit); + if (sad < best_sad) { + best_sad = sad; + *best_mv = mv; + } } + ++check_here; + ++c; } - check_here++; - c++; } } while (c < col_max) { - thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride, - bestsad); - - if (thissad < bestsad) { - this_mv.col = c; - thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit); - if (thissad < bestsad) { - bestsad = thissad; - best_mv->row = r; - best_mv->col = c; + unsigned int sad = fn_ptr->sdf(what->buf, what->stride, + check_here, in_what->stride, best_sad); + if (sad < best_sad) { + const MV mv = {r, c}; + sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit); + if (sad < best_sad) { + best_sad = sad; + *best_mv = mv; } } - - check_here++; - c++; + ++check_here; + ++c; } } - return bestsad; + + return best_sad; } int vp9_full_search_sadx8(const MACROBLOCK *x, const MV *ref_mv, diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index c1493e719..56eb9440c 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -418,7 +418,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, // Perform intra prediction search, if the best SAD is above a certain // threshold. - if (best_rd > inter_mode_thresh) { + if (best_rd > inter_mode_thresh && bsize < cpi->sf.max_intra_bsize) { for (this_mode = DC_PRED; this_mode <= DC_PRED; ++this_mode) { vp9_predict_intra_block(xd, 0, b_width_log2(bsize), mbmi->tx_size, this_mode, diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 2e35e5fbc..6ebd9f3fa 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1215,7 +1215,7 @@ void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) { cm->frame_type = KEY_FRAME; rc->this_key_frame_forced = cm->current_video_frame != 0 && rc->frames_to_key == 0; - rc->frames_to_key = cpi->key_frame_frequency; + rc->frames_to_key = cpi->oxcf.key_freq; rc->kf_boost = DEFAULT_KF_BOOST; rc->source_alt_ref_active = 0; } else { @@ -1302,7 +1302,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) { if ((cm->current_video_frame == 0) || (cpi->frame_flags & FRAMEFLAGS_KEY) || (cpi->oxcf.auto_key && (rc->frames_since_key % - cpi->key_frame_frequency == 0))) { + cpi->oxcf.key_freq == 0))) { cm->frame_type = KEY_FRAME; rc->source_alt_ref_active = 0; if (cpi->pass == 0 && cpi->oxcf.rc_mode == RC_MODE_CBR) { @@ -1330,7 +1330,7 @@ void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) { cm->frame_type = KEY_FRAME; rc->this_key_frame_forced = cm->current_video_frame != 0 && rc->frames_to_key == 0; - rc->frames_to_key = cpi->key_frame_frequency; + rc->frames_to_key = cpi->oxcf.key_freq; rc->kf_boost = DEFAULT_KF_BOOST; rc->source_alt_ref_active = 0; target = calc_iframe_target_size_one_pass_cbr(cpi); @@ -1415,7 +1415,7 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) { rc->max_gf_interval = 16; // Extended interval for genuinely static scenes - rc->static_scene_max_gf_interval = cpi->key_frame_frequency >> 1; + rc->static_scene_max_gf_interval = cpi->oxcf.key_freq >> 1; // Special conditions when alt ref frame enabled in lagged compress mode if (oxcf->play_alternate && oxcf->lag_in_frames) { diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index f59670d06..2379f35b5 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -153,7 +153,7 @@ void vp9_update_spatial_layer_framerate(VP9_COMP *const cpi, double framerate) { oxcf->two_pass_vbrmax_section) / 100); lrc->max_gf_interval = 16; - lrc->static_scene_max_gf_interval = cpi->key_frame_frequency >> 1; + lrc->static_scene_max_gf_interval = cpi->oxcf.key_freq >> 1; if (oxcf->play_alternate && oxcf->lag_in_frames) { if (lrc->max_gf_interval > oxcf->lag_in_frames - 1) diff --git a/vp9/encoder/vp9_variance.c b/vp9/encoder/vp9_variance.c index 1399bfb7e..520ee443a 100644 --- a/vp9/encoder/vp9_variance.c +++ b/vp9/encoder/vp9_variance.c @@ -357,45 +357,6 @@ unsigned int vp9_variance_halfpixvar64x64_hv_c(const uint8_t *src_ptr, ref_ptr, recon_stride, sse); } -unsigned int vp9_sub_pixel_mse16x16_c(const uint8_t *src_ptr, - int src_pixels_per_line, - int xoffset, - int yoffset, - const uint8_t *dst_ptr, - int dst_pixels_per_line, - unsigned int *sse) { - vp9_sub_pixel_variance16x16_c(src_ptr, src_pixels_per_line, - xoffset, yoffset, dst_ptr, - dst_pixels_per_line, sse); - return *sse; -} - -unsigned int vp9_sub_pixel_mse32x32_c(const uint8_t *src_ptr, - int src_pixels_per_line, - int xoffset, - int yoffset, - const uint8_t *dst_ptr, - int dst_pixels_per_line, - unsigned int *sse) { - vp9_sub_pixel_variance32x32_c(src_ptr, src_pixels_per_line, - xoffset, yoffset, dst_ptr, - dst_pixels_per_line, sse); - return *sse; -} - -unsigned int vp9_sub_pixel_mse64x64_c(const uint8_t *src_ptr, - int src_pixels_per_line, - int xoffset, - int yoffset, - const uint8_t *dst_ptr, - int dst_pixels_per_line, - unsigned int *sse) { - vp9_sub_pixel_variance64x64_c(src_ptr, src_pixels_per_line, - xoffset, yoffset, dst_ptr, - dst_pixels_per_line, sse); - return *sse; -} - void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width, int height, const uint8_t *ref, int ref_stride) { int i, j; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 1d82b1955..1ca9fb93a 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -185,7 +185,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, ERROR("ts_rate_decimator factors are not powers of 2"); } - // VP8 does not support a lower bound on the keyframe interval in + // VP9 does not support a lower bound on the keyframe interval in // automatic keyframe placement mode. if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist && diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index 1cd3b03d2..06b482305 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -43,6 +43,8 @@ struct vpx_codec_alg_priv { int dbg_color_b_modes_flag; int dbg_display_mv_flag; #endif + vpx_decrypt_cb decrypt_cb; + void *decrypt_state; vpx_image_t img; int img_setup; int img_avail; @@ -94,9 +96,13 @@ static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) { return VPX_CODEC_OK; } -static vpx_codec_err_t decoder_peek_si(const uint8_t *data, - unsigned int data_sz, - vpx_codec_stream_info_t *si) { +static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { + uint8_t clear_buffer[9]; + if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM; @@ -106,6 +112,12 @@ static vpx_codec_err_t decoder_peek_si(const uint8_t *data, si->is_kf = 0; si->w = si->h = 0; + if (decrypt_cb) { + data_sz = MIN(sizeof(clear_buffer), data_sz); + decrypt_cb(decrypt_state, data, clear_buffer, data_sz); + data = clear_buffer; + } + { struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL }; const int frame_marker = vp9_rb_read_literal(&rb, 2); @@ -159,6 +171,12 @@ static vpx_codec_err_t decoder_peek_si(const uint8_t *data, return VPX_CODEC_OK; } +static vpx_codec_err_t decoder_peek_si(const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si) { + return decoder_peek_si_internal(data, data_sz, si, NULL, NULL); +} + static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx, vpx_codec_stream_info_t *si) { const size_t sz = (si->sz >= sizeof(vp9_stream_info_t)) @@ -264,7 +282,8 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, // of the heap. if (!ctx->si.h) { const vpx_codec_err_t res = - ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si); + decoder_peek_si_internal(*data, data_sz, &ctx->si, ctx->decrypt_cb, + ctx->decrypt_state); if (res != VPX_CODEC_OK) return res; } @@ -278,6 +297,11 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, ctx->decoder_init = 1; } + // Set these even if already initialized. The caller may have changed the + // decrypt config between frames. + ctx->pbi->decrypt_cb = ctx->decrypt_cb; + ctx->pbi->decrypt_state = ctx->decrypt_state; + cm = &ctx->pbi->common; if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) @@ -296,12 +320,25 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, return VPX_CODEC_OK; } +static INLINE uint8_t read_marker(vpx_decrypt_cb decrypt_cb, + void *decrypt_state, + const uint8_t *data) { + if (decrypt_cb) { + uint8_t marker; + decrypt_cb(decrypt_state, data, &marker, 1); + return marker; + } + return *data; +} + static void parse_superframe_index(const uint8_t *data, size_t data_sz, - uint32_t sizes[8], int *count) { + uint32_t sizes[8], int *count, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { uint8_t marker; assert(data_sz); - marker = data[data_sz - 1]; + marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1); *count = 0; if ((marker & 0xe0) == 0xc0) { @@ -309,11 +346,22 @@ static void parse_superframe_index(const uint8_t *data, size_t data_sz, const uint32_t mag = ((marker >> 3) & 0x3) + 1; const size_t index_sz = 2 + mag * frames; - if (data_sz >= index_sz && data[data_sz - index_sz] == marker) { + uint8_t marker2 = read_marker(decrypt_cb, decrypt_state, + data + data_sz - index_sz); + + if (data_sz >= index_sz && marker2 == marker) { // found a valid superframe index uint32_t i, j; const uint8_t *x = &data[data_sz - index_sz + 1]; + // frames has a maximum of 8 and mag has a maximum of 4. + uint8_t clear_buffer[32]; + assert(sizeof(clear_buffer) >= frames * mag); + if (decrypt_cb) { + decrypt_cb(decrypt_state, x, clear_buffer, frames * mag); + x = clear_buffer; + } + for (i = 0; i < frames; i++) { uint32_t this_sz = 0; @@ -339,23 +387,31 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM; - parse_superframe_index(data, data_sz, sizes, &frames_this_pts); + parse_superframe_index(data, data_sz, sizes, &frames_this_pts, + ctx->decrypt_cb, ctx->decrypt_state); do { - // Skip over the superframe index, if present - if (data_sz && (*data_start & 0xe0) == 0xc0) { - const uint8_t marker = *data_start; - const uint32_t frames = (marker & 0x7) + 1; - const uint32_t mag = ((marker >> 3) & 0x3) + 1; - const uint32_t index_sz = 2 + mag * frames; - - if (data_sz >= index_sz && data_start[index_sz - 1] == marker) { - data_start += index_sz; - data_sz -= index_sz; - if (data_start < data_end) - continue; - else - break; + if (data_sz) { + uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + data_start); + // Skip over the superframe index, if present + if ((marker & 0xe0) == 0xc0) { + const uint32_t frames = (marker & 0x7) + 1; + const uint32_t mag = ((marker >> 3) & 0x3) + 1; + const uint32_t index_sz = 2 + mag * frames; + + if (data_sz >= index_sz) { + uint8_t marker2 = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + data_start + index_sz - 1); + if (marker2 == marker) { + data_start += index_sz; + data_sz -= index_sz; + if (data_start < data_end) + continue; + else + break; + } + } } } @@ -381,8 +437,13 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, break; // Account for suboptimal termination by the encoder. - while (data_start < data_end && *data_start == 0) + while (data_start < data_end) { + uint8_t marker3 = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + data_start); + if (marker3) + break; data_start++; + } data_sz = (unsigned int)(data_end - data_start); } while (data_start < data_end); @@ -565,6 +626,15 @@ static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx, return VPX_CODEC_OK; } +static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx, + int ctrl_id, + va_list args) { + vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *); + ctx->decrypt_cb = init ? init->decrypt_cb : NULL; + ctx->decrypt_state = init ? init->decrypt_state : NULL; + return VPX_CODEC_OK; +} + static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { {VP8_COPY_REFERENCE, ctrl_copy_reference}, @@ -576,6 +646,7 @@ static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { {VP8_SET_DBG_COLOR_B_MODES, ctrl_set_dbg_options}, {VP8_SET_DBG_DISPLAY_MV, ctrl_set_dbg_options}, {VP9_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order}, + {VPXD_SET_DECRYPTOR, ctrl_set_decryptor}, // Getters {VP8D_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates}, diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h index bde77c24d..bd7f19c43 100644 --- a/vpx/vp8dx.h +++ b/vpx/vp8dx.h @@ -66,10 +66,11 @@ enum vp8_dec_control_id { VP8D_GET_LAST_REF_USED, /** decryption function to decrypt encoded buffer data immediately - * before decoding. Takes a vp8_decrypt_init, which contains + * before decoding. Takes a vpx_decrypt_init, which contains * a callback function and opaque context pointer. */ - VP8D_SET_DECRYPTOR, + VPXD_SET_DECRYPTOR, + VP8D_SET_DECRYPTOR = VPXD_SET_DECRYPTOR, /** control function to get the display dimensions for the current frame. */ VP9D_GET_DISPLAY_SIZE, @@ -80,19 +81,28 @@ enum vp8_dec_control_id { VP8_DECODER_CTRL_ID_MAX }; +/** Decrypt n bytes of data from input -> output, using the decrypt_state + * passed in VPXD_SET_DECRYPTOR. + */ +typedef void (*vpx_decrypt_cb)(void *decrypt_state, const unsigned char *input, + unsigned char *output, int count); + /*!\brief Structure to hold decryption state * * Defines a structure to hold the decryption state and access function. */ -typedef struct vp8_decrypt_init { - /** Decrypt n bytes of data from input -> output, using the decrypt_state - * passed in VP8D_SET_DECRYPTOR. - */ - void (*decrypt_cb)(void *decrypt_state, const unsigned char *input, - unsigned char *output, int count); +typedef struct vpx_decrypt_init { + /*! Decrypt callback. */ + vpx_decrypt_cb decrypt_cb; + /*! Decryption state. */ void *decrypt_state; -} vp8_decrypt_init; +} vpx_decrypt_init; + +/*!\brief A deprecated alias for vpx_decrypt_init. + */ +typedef vpx_decrypt_init vp8_decrypt_init; + /*!\brief VP8 decoder control function parameter type * @@ -102,11 +112,12 @@ typedef struct vp8_decrypt_init { */ -VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *) -VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *) -VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *) -VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR, vp8_decrypt_init *) -VPX_CTRL_USE_TYPE(VP9D_GET_DISPLAY_SIZE, int *) +VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *) +VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *) +VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *) +VPX_CTRL_USE_TYPE(VPXD_SET_DECRYPTOR, vpx_decrypt_init *) +VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR, vpx_decrypt_init *) +VPX_CTRL_USE_TYPE(VP9D_GET_DISPLAY_SIZE, int *) VPX_CTRL_USE_TYPE(VP9_INVERT_TILE_DECODE_ORDER, int) /*! @} - end defgroup vp8_decoder */ diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c index 5e95d31e0..3eaf50ed7 100644 --- a/vpx_scale/generic/yv12config.c +++ b/vpx_scale/generic/yv12config.c @@ -183,8 +183,7 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, ybf->buffer_alloc = (uint8_t *)yv12_align_addr(fb->data, 32); } else if (frame_size > ybf->buffer_alloc_sz) { // Allocation to hold larger frame, or first allocation. - if (ybf->buffer_alloc) - vpx_free(ybf->buffer_alloc); + vpx_free(ybf->buffer_alloc); ybf->buffer_alloc = (uint8_t *)vpx_memalign(32, frame_size); if (!ybf->buffer_alloc) return -1; |