diff options
61 files changed, 1862 insertions, 914 deletions
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c index feed9d983..495e9d7fa 100644 --- a/build/make/obj_int_extract.c +++ b/build/make/obj_int_extract.c @@ -321,7 +321,7 @@ bail: return 1; } -char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) { +const char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) { if (elf->bits == 32) { Elf32_Shdr shdr; @@ -183,6 +183,7 @@ CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec INSTALL-LIBS-yes += include/vpx/vpx_codec.h INSTALL-LIBS-yes += include/vpx/vpx_image.h +INSTALL-LIBS-yes += include/vpx/vpx_external_frame_buffer.h INSTALL-LIBS-yes += include/vpx/vpx_integer.h INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h diff --git a/test/borders_test.cc b/test/borders_test.cc index dcdedcfab..5071541ab 100644 --- a/test/borders_test.cc +++ b/test/borders_test.cc @@ -67,7 +67,7 @@ TEST_P(BordersTest, TestLowBitrate) { cfg_.g_lag_in_frames = 25; cfg_.rc_2pass_vbr_minsection_pct = 5; - cfg_.rc_2pass_vbr_minsection_pct = 2000; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; cfg_.rc_target_bitrate = 200; cfg_.rc_min_quantizer = 40; diff --git a/test/codec_factory.h b/test/codec_factory.h index cc7b53f06..2ca6ff086 100644 --- a/test/codec_factory.h +++ b/test/codec_factory.h @@ -26,6 +26,8 @@ extern "C" { #include "test/encode_test_driver.h" namespace libvpx_test { +const int kCodecFactoryParam = 0; + class CodecFactory { public: CodecFactory() {} diff --git a/test/datarate_test.cc b/test/datarate_test.cc index 5785a0aac..2d4652271 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -248,9 +248,11 @@ TEST_P(DatarateTestVP9, BasicRateTargeting) { cfg_.rc_target_bitrate = i; ResetModel(); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.9) + ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate), + effective_datarate_ * 0.85) << " The datarate for the file exceeds the target by too much!"; - ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_ * 1.1) + ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate), + effective_datarate_ * 1.15) << " The datarate for the file missed the target!"; } } diff --git a/test/decode_test_driver.cc b/test/decode_test_driver.cc index 1f6d54064..7a93e50c2 100644 --- a/test/decode_test_driver.cc +++ b/test/decode_test_driver.cc @@ -30,6 +30,7 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) { // Decode frames. for (video->Begin(); video->cxdata(); video->Next()) { + PreDecodeFrameHook(*video, decoder); vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(), video->frame_size()); ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError(); diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h index 055c45e06..79db6e1bc 100644 --- a/test/decode_test_driver.h +++ b/test/decode_test_driver.h @@ -76,6 +76,16 @@ class Decoder { return detail ? detail : vpx_codec_error(&decoder_); } + // Passes the external frame buffer information to libvpx. + vpx_codec_err_t SetExternalFrameBuffers( + vpx_codec_frame_buffer_t *fb_list, int fb_count, + vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) { + InitOnce(); + return vpx_codec_set_frame_buffers(&decoder_, + fb_list, fb_count, + cb, user_priv); + } + protected: virtual const vpx_codec_iface_t* CodecInterface() const = 0; @@ -101,6 +111,10 @@ class DecoderTest { // Main decoding loop virtual void RunLoop(CompressedVideoSource *video); + // Hook to be called before decompressing every frame. + virtual void PreDecodeFrameHook(const CompressedVideoSource& video, + Decoder *decoder) {} + // Hook to be called on every decompressed frame. virtual void DecompressedFrameHook(const vpx_image_t& img, const unsigned int frame_number) {} diff --git a/test/error_resilience_test.cc b/test/error_resilience_test.cc index 16d250c76..30c20e91f 100644 --- a/test/error_resilience_test.cc +++ b/test/error_resilience_test.cc @@ -1,12 +1,12 @@ /* - Copyright (c) 2012 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. -*/ + * 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 "third_party/googletest/src/include/gtest/gtest.h" #include "test/codec_factory.h" diff --git a/test/external_frame_buffer_test.cc b/test/external_frame_buffer_test.cc new file mode 100644 index 000000000..874d1997c --- /dev/null +++ b/test/external_frame_buffer_test.cc @@ -0,0 +1,309 @@ +/* + * 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 <string> + +#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" +#include "test/webm_video_source.h" + +namespace { + +const int kVideoNameParam = 1; +const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm"; + +// Callback used by libvpx to request the application to allocate a frame +// buffer of at least |new_size| in bytes. +int realloc_vp9_frame_buffer(void *user_priv, size_t new_size, + vpx_codec_frame_buffer_t *fb) { + (void)user_priv; + if (fb == NULL) + return -1; + + delete [] fb->data; + fb->data = new uint8_t[new_size]; + fb->size = new_size; + return 0; +} + +// Callback will not allocate data for frame buffer. +int zero_realloc_vp9_frame_buffer(void *user_priv, size_t new_size, + vpx_codec_frame_buffer_t *fb) { + (void)user_priv; + if (fb == NULL) + return -1; + + delete [] fb->data; + fb->data = NULL; + fb->size = new_size; + return 0; +} + +// Callback will allocate one less byte. +int one_less_byte_realloc_vp9_frame_buffer(void *user_priv, size_t new_size, + vpx_codec_frame_buffer_t *fb) { + (void)user_priv; + if (fb == NULL) + return -1; + + delete [] fb->data; + + const size_t error_size = new_size - 1; + fb->data = new uint8_t[error_size]; + fb->size = error_size; + return 0; +} + +// Class for testing passing in external frame buffers to libvpx. +class ExternalFrameBufferMD5Test + : public ::libvpx_test::DecoderTest, + public ::libvpx_test::CodecTestWithParam<const char*> { + protected: + ExternalFrameBufferMD5Test() + : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)), + md5_file_(NULL), + num_buffers_(0), + frame_buffers_(NULL) {} + + virtual ~ExternalFrameBufferMD5Test() { + for (int i = 0; i < num_buffers_; ++i) { + delete [] frame_buffers_[i].data; + } + delete [] frame_buffers_; + + if (md5_file_ != NULL) + fclose(md5_file_); + } + + virtual void PreDecodeFrameHook( + const libvpx_test::CompressedVideoSource &video, + libvpx_test::Decoder *decoder) { + if (num_buffers_ > 0 && video.frame_number() == 0) { + // Have libvpx use frame buffers we create. + frame_buffers_ = new vpx_codec_frame_buffer_t[num_buffers_]; + memset(frame_buffers_, 0, sizeof(frame_buffers_[0]) * num_buffers_); + + ASSERT_EQ(VPX_CODEC_OK, + decoder->SetExternalFrameBuffers( + frame_buffers_, num_buffers_, + realloc_vp9_frame_buffer, NULL)); + } + } + + void OpenMD5File(const std::string &md5_file_name_) { + md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_); + ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: " + << md5_file_name_; + } + + virtual void DecompressedFrameHook(const vpx_image_t &img, + const unsigned int frame_number) { + ASSERT_TRUE(md5_file_ != NULL); + char expected_md5[33]; + char junk[128]; + + // Read correct md5 checksums. + const int res = fscanf(md5_file_, "%s %s", expected_md5, junk); + ASSERT_NE(EOF, res) << "Read md5 data failed"; + expected_md5[32] = '\0'; + + ::libvpx_test::MD5 md5_res; + md5_res.Add(&img); + const char *const actual_md5 = md5_res.Get(); + + // Check md5 match. + ASSERT_STREQ(expected_md5, actual_md5) + << "Md5 checksums don't match: frame number = " << frame_number; + } + + void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; } + int num_buffers() const { return num_buffers_; } + + private: + FILE *md5_file_; + int num_buffers_; + vpx_codec_frame_buffer_t *frame_buffers_; +}; + +class ExternalFrameBufferTest : public ::testing::Test { + protected: + ExternalFrameBufferTest() + : video_(NULL), + decoder_(NULL), + num_buffers_(0), + frame_buffers_(NULL) {} + + virtual void SetUp() { + video_ = new libvpx_test::WebMVideoSource(kVP9TestFile); + video_->Init(); + video_->Begin(); + + vpx_codec_dec_cfg_t cfg = {0}; + decoder_ = new libvpx_test::VP9Decoder(cfg, 0); + } + + virtual void TearDown() { + for (int i = 0; i < num_buffers_; ++i) { + delete [] frame_buffers_[i].data; + } + delete [] frame_buffers_; + delete decoder_; + delete video_; + } + + // Passes the external frame buffer information to libvpx. + vpx_codec_err_t SetExternalFrameBuffers( + int num_buffers, + vpx_realloc_frame_buffer_cb_fn_t cb) { + if (num_buffers > 0) { + num_buffers_ = num_buffers; + + // Have libvpx use frame buffers we create. + frame_buffers_ = new vpx_codec_frame_buffer_t[num_buffers_]; + memset(frame_buffers_, 0, sizeof(frame_buffers_[0]) * num_buffers_); + } + + return decoder_->SetExternalFrameBuffers(frame_buffers_, num_buffers_, + cb, NULL); + } + + // Pass Null frame buffer list to libvpx. + vpx_codec_err_t SetNullFrameBuffers( + int num_buffers, + vpx_realloc_frame_buffer_cb_fn_t cb) { + return decoder_->SetExternalFrameBuffers(NULL, num_buffers, + cb, NULL); + } + + vpx_codec_err_t DecodeOneFrame() { + const vpx_codec_err_t res = + decoder_->DecodeFrame(video_->cxdata(), video_->frame_size()); + if (res == VPX_CODEC_OK) + video_->Next(); + return res; + } + + vpx_codec_err_t DecodeRemainingFrames() { + for (; video_->cxdata(); video_->Next()) { + const vpx_codec_err_t res = + decoder_->DecodeFrame(video_->cxdata(), video_->frame_size()); + if (res != VPX_CODEC_OK) + return res; + + libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData(); + const vpx_image_t *img = NULL; + + // Get decompressed data + while ((img = dec_iter.Next())) { + } + } + return VPX_CODEC_OK; + } + + libvpx_test::WebMVideoSource *video_; + libvpx_test::VP9Decoder *decoder_; + int num_buffers_; + vpx_codec_frame_buffer_t *frame_buffers_; +}; + + +// This test runs through the set of test vectors, and decodes them. +// Libvpx will call into the application to allocate a frame buffer when +// needed. The md5 checksums are computed for each frame in the video file. +// If md5 checksums match the correct md5 data, then the test is passed. +// Otherwise, the test failed. +TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) { + const std::string filename = GET_PARAM(kVideoNameParam); + libvpx_test::CompressedVideoSource *video = NULL; + + // Number of buffers equals number of possible reference buffers(8), plus + // one working buffer, plus four jitter buffers. + const int num_buffers = 13; + set_num_buffers(num_buffers); + + // Tell compiler we are not using kVP8TestVectors. + (void)libvpx_test::kVP8TestVectors; + + // Open compressed video file. + if (filename.substr(filename.length() - 3, 3) == "ivf") { + video = new libvpx_test::IVFVideoSource(filename); + } else if (filename.substr(filename.length() - 4, 4) == "webm") { + video = new libvpx_test::WebMVideoSource(filename); + } + video->Init(); + + // Construct md5 file name. + const std::string md5_filename = filename + ".md5"; + OpenMD5File(md5_filename); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video)); + delete video; +} + +TEST_F(ExternalFrameBufferTest, EightFrameBuffers) { + // Minimum number of reference buffers for VP9 is 8. + const int num_buffers = 8; + ASSERT_EQ(VPX_CODEC_OK, + SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames()); +} + +TEST_F(ExternalFrameBufferTest, EightJitterBuffers) { + // Number of buffers equals number of possible reference buffers(8), plus + // one working buffer, plus eight jitter buffers. + const int num_buffers = 17; + ASSERT_EQ(VPX_CODEC_OK, + SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames()); +} + +TEST_F(ExternalFrameBufferTest, NotEnoughBuffers) { + // Minimum number of reference buffers for VP9 is 8. + const int num_buffers = 7; + ASSERT_EQ(VPX_CODEC_INVALID_PARAM, + SetExternalFrameBuffers(num_buffers, realloc_vp9_frame_buffer)); +} + +TEST_F(ExternalFrameBufferTest, NullFrameBufferList) { + // Number of buffers equals number of possible reference buffers(8), plus + // one working buffer, plus four jitter buffers. + const int num_buffers = 13; + ASSERT_EQ(VPX_CODEC_INVALID_PARAM, + SetNullFrameBuffers(num_buffers, realloc_vp9_frame_buffer)); +} + +TEST_F(ExternalFrameBufferTest, NullRealloc) { + // Number of buffers equals number of possible reference buffers(8), plus + // one working buffer, plus four jitter buffers. + const int num_buffers = 13; + ASSERT_EQ(VPX_CODEC_OK, + SetExternalFrameBuffers(num_buffers, + zero_realloc_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame()); +} + +TEST_F(ExternalFrameBufferTest, ReallocOneLessByte) { + // Number of buffers equals number of possible reference buffers(8), plus + // one working buffer, plus four jitter buffers. + const int num_buffers = 13; + ASSERT_EQ(VPX_CODEC_OK, + SetExternalFrameBuffers(num_buffers, + one_less_byte_realloc_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame()); +} + +VP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test, + ::testing::ValuesIn(libvpx_test::kVP9TestVectors)); +} // namespace diff --git a/test/lru_frame_buffer_test.cc b/test/lru_frame_buffer_test.cc new file mode 100644 index 000000000..cd6b432d8 --- /dev/null +++ b/test/lru_frame_buffer_test.cc @@ -0,0 +1,207 @@ +/* + * 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 <queue> +#include <string> + +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/ivf_video_source.h" +#include "test/md5_helper.h" +#include "test/util.h" +#include "test/webm_video_source.h" + +namespace { + +const int kVideoNameParam = 1; + +const char *kLRUTestVectors[] = { + "vp90-2-02-size-lf-1920x1080.webm", + "vp90-2-05-resize.ivf", +}; + +// Callback used by libvpx to request the application to allocate a frame +// buffer of at least |new_size| in bytes. +int realloc_vp9_frame_buffer(void *user_priv, size_t new_size, + vpx_codec_frame_buffer_t *fb) { + (void)user_priv; + if (fb == NULL) + return -1; + + delete [] fb->data; + fb->data = new uint8_t[new_size]; + fb->size = new_size; + + return 0; +} + +// Class for testing libvpx is using the least recently +// used frame buffer when a new buffer is requested. +class LRUFrameBufferTest + : public ::libvpx_test::DecoderTest, + public ::libvpx_test::CodecTestWithParam<const char*> { + protected: + struct FrameBufferMD5Sum { + int frame_buffer_index; + vpx_image_t img; + std::string md5; + }; + + LRUFrameBufferTest() + : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)), + num_buffers_(0), + num_jitter_buffers_(0), + frame_buffers_(NULL) {} + + virtual ~LRUFrameBufferTest() { + for (int i = 0; i < num_buffers_; ++i) { + delete [] frame_buffers_[i].data; + } + delete [] frame_buffers_; + } + + virtual void PreDecodeFrameHook( + const libvpx_test::CompressedVideoSource &video, + libvpx_test::Decoder *decoder) { + // Use external buffers for testing jitter buffers. + if (num_jitter_buffers_ > 0 && video.frame_number() == 0) { + const int max_reference_buffers = 8; + + // Add 1 for a work buffer. + num_buffers_ = max_reference_buffers + 1 + num_jitter_buffers_; + + // Have libvpx use frame buffers we create. + frame_buffers_ = new vpx_codec_frame_buffer_t[num_buffers_]; + memset(frame_buffers_, 0, sizeof(frame_buffers_[0]) * num_buffers_); + + decoder->SetExternalFrameBuffers(frame_buffers_, num_buffers_, + realloc_vp9_frame_buffer, NULL); + } + + // Turn on frame buffer LRU cache. + decoder->Control(VP9D_SET_FRAME_BUFFER_LRU_CACHE, 1); + } + + virtual void DecompressedFrameHook(const vpx_image_t &img, + const unsigned int frame_number) { + const uint32_t ximg_y_plane = 0; + const uint8_t *const y_buffer = img.planes[ximg_y_plane]; + + // Find which external buffer contains the y_buffer. + int i = 0; + for (i = 0; i < num_buffers_; ++i) { + if (y_buffer >= frame_buffers_[i].data && + y_buffer < (frame_buffers_[i].data + frame_buffers_[i].size)) { + break; + } + } + + FrameBufferMD5Sum fb_md5; + fb_md5.frame_buffer_index = i; + fb_md5.img = img; + + libvpx_test::MD5 md5; + md5.Add(&img); + fb_md5.md5 = md5.Get(); + jitter_buffer_md5_sums_.push(fb_md5); + + // Check to see if any of the reconstructed image changed. + if (jitter_buffer_md5_sums_.size() > + static_cast<size_t>(num_jitter_buffers_)) { + fb_md5 = jitter_buffer_md5_sums_.front(); + + libvpx_test::MD5 md5; + md5.Add(&fb_md5.img); + const std::string check_str = md5.Get(); + + ASSERT_EQ(fb_md5.md5, check_str); + jitter_buffer_md5_sums_.pop(); + } + } + + libvpx_test::CompressedVideoSource *OpenCompressedFile( + const std::string &filename) { + if (filename.substr(filename.length() - 3, 3) == "ivf") { + return new libvpx_test::IVFVideoSource(filename); + } else if (filename.substr(filename.length() - 4, 4) == "webm") { + return new libvpx_test::WebMVideoSource(filename); + } + return NULL; + } + + void set_num_jitter_buffers(int num_buffers) { + num_jitter_buffers_ = num_buffers; + } + + private: + // Total number of external frame buffers. + int num_buffers_; + int num_jitter_buffers_; + + // External frame buffers used by libvpx. + vpx_codec_frame_buffer_t *frame_buffers_; + + // Save the md5 checksums for later comparison. + std::queue<FrameBufferMD5Sum> jitter_buffer_md5_sums_; +}; + +// This test runs through a set of test vectors, and decodes them. +// Libvpx will call into the application to allocate a frame buffer when +// needed. The md5 checksums are computed for each frame after it is +// decoded and stored to be checked later. After a jitter frame buffer +// has expired, the md5 checksum is computed again for the expired jitter +// buffer frame and checked against the md5 checksum after the frame was +// decoded. If md5 checksums match, then the test is passed. Otherwise, +// the test failed. +TEST_P(LRUFrameBufferTest, CheckLRUOneJitterBuffer) { + const std::string filename = GET_PARAM(kVideoNameParam); + + set_num_jitter_buffers(1); + + libvpx_test::CompressedVideoSource *const video = + OpenCompressedFile(filename); + video->Init(); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video)); + delete video; +} + +TEST_P(LRUFrameBufferTest, CheckLRUFourJitterBuffers) { + const std::string filename = GET_PARAM(kVideoNameParam); + + set_num_jitter_buffers(4); + + libvpx_test::CompressedVideoSource *const video = + OpenCompressedFile(filename); + video->Init(); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video)); + delete video; +} + +TEST_P(LRUFrameBufferTest, CheckLRUEightJitterBuffers) { + const std::string filename = GET_PARAM(kVideoNameParam); + + set_num_jitter_buffers(8); + + libvpx_test::CompressedVideoSource *const video = + OpenCompressedFile(filename); + video->Init(); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video)); + delete video; +} + +VP9_INSTANTIATE_TEST_CASE(LRUFrameBufferTest, + ::testing::ValuesIn(kLRUTestVectors)); +} // namespace diff --git a/test/sixtap_predict_test.cc b/test/sixtap_predict_test.cc index 655146dbf..0f5c0a5e8 100644 --- a/test/sixtap_predict_test.cc +++ b/test/sixtap_predict_test.cc @@ -1,12 +1,12 @@ /* -* Copyright (c) 2012 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. -*/ + * 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 <math.h> #include <stdlib.h> diff --git a/test/test-data.sha1 b/test/test-data.sha1 index 445147986..442bfd23f 100644 --- a/test/test-data.sha1 +++ b/test/test-data.sha1 @@ -567,3 +567,5 @@ c64b03b5c090e6888cb39685c31f00a6b79fa45c vp90-2-tos_854x356_tile_1x2_656kbps.we c9b6850af28579b031791066457f4cb40df6e1c7 vp90-2-08-tile_1x8_frame_parallel.webm.md5 e448b6e83490bca0f8d58b4f4b1126a17baf4b0c vp90-2-08-tile_1x8.webm 5e524165f0397e6141d914f4f0a66267d7658376 vp90-2-08-tile_1x8.webm.md5 +a34e14923d6d17b1144254d8187d7f85b700a63c vp90-2-02-size-lf-1920x1080.webm +e3b28ddcfaeb37fb4d132b93f92642a9ad17c22d vp90-2-02-size-lf-1920x1080.webm.md5 diff --git a/test/test.mk b/test/test.mk index 98e5c7b72..361a34fa4 100644 --- a/test/test.mk +++ b/test/test.mk @@ -7,6 +7,8 @@ LIBVPX_TEST_SRCS-yes += codec_factory.h LIBVPX_TEST_SRCS-yes += test_libvpx.cc LIBVPX_TEST_SRCS-yes += util.h LIBVPX_TEST_SRCS-yes += video_source.h +LIBVPX_TEST_SRCS-yes += test_vectors.h +LIBVPX_TEST_SRCS-yes += test_vectors.cc ## ## BLACK BOX TESTS @@ -32,6 +34,8 @@ LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../md5_utils.h ../md5_utils.c LIBVPX_TEST_SRCS-yes += decode_test_driver.cc LIBVPX_TEST_SRCS-yes += decode_test_driver.h LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ivf_video_source.h +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += lru_frame_buffer_test.cc ## WebM Parsing NESTEGG_SRCS += ../nestegg/halloc/halloc.h diff --git a/test/test_vector_test.cc b/test/test_vector_test.cc index ee610fa90..6d93bb88f 100644 --- a/test/test_vector_test.cc +++ b/test/test_vector_test.cc @@ -1,11 +1,11 @@ /* - Copyright (c) 2012 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. + * 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> @@ -15,165 +15,15 @@ #include "test/codec_factory.h" #include "test/decode_test_driver.h" #include "test/ivf_video_source.h" -#include "test/webm_video_source.h" -#include "test/util.h" #include "test/md5_helper.h" +#include "test/test_vectors.h" +#include "test/util.h" +#include "test/webm_video_source.h" extern "C" { #include "vpx_mem/vpx_mem.h" } namespace { -#if CONFIG_VP8_DECODER -const char *kVP8TestVectors[] = { - "vp80-00-comprehensive-001.ivf", - "vp80-00-comprehensive-002.ivf", "vp80-00-comprehensive-003.ivf", - "vp80-00-comprehensive-004.ivf", "vp80-00-comprehensive-005.ivf", - "vp80-00-comprehensive-006.ivf", "vp80-00-comprehensive-007.ivf", - "vp80-00-comprehensive-008.ivf", "vp80-00-comprehensive-009.ivf", - "vp80-00-comprehensive-010.ivf", "vp80-00-comprehensive-011.ivf", - "vp80-00-comprehensive-012.ivf", "vp80-00-comprehensive-013.ivf", - "vp80-00-comprehensive-014.ivf", "vp80-00-comprehensive-015.ivf", - "vp80-00-comprehensive-016.ivf", "vp80-00-comprehensive-017.ivf", - "vp80-00-comprehensive-018.ivf", "vp80-01-intra-1400.ivf", - "vp80-01-intra-1411.ivf", "vp80-01-intra-1416.ivf", - "vp80-01-intra-1417.ivf", "vp80-02-inter-1402.ivf", - "vp80-02-inter-1412.ivf", "vp80-02-inter-1418.ivf", - "vp80-02-inter-1424.ivf", "vp80-03-segmentation-01.ivf", - "vp80-03-segmentation-02.ivf", "vp80-03-segmentation-03.ivf", - "vp80-03-segmentation-04.ivf", "vp80-03-segmentation-1401.ivf", - "vp80-03-segmentation-1403.ivf", "vp80-03-segmentation-1407.ivf", - "vp80-03-segmentation-1408.ivf", "vp80-03-segmentation-1409.ivf", - "vp80-03-segmentation-1410.ivf", "vp80-03-segmentation-1413.ivf", - "vp80-03-segmentation-1414.ivf", "vp80-03-segmentation-1415.ivf", - "vp80-03-segmentation-1425.ivf", "vp80-03-segmentation-1426.ivf", - "vp80-03-segmentation-1427.ivf", "vp80-03-segmentation-1432.ivf", - "vp80-03-segmentation-1435.ivf", "vp80-03-segmentation-1436.ivf", - "vp80-03-segmentation-1437.ivf", "vp80-03-segmentation-1441.ivf", - "vp80-03-segmentation-1442.ivf", "vp80-04-partitions-1404.ivf", - "vp80-04-partitions-1405.ivf", "vp80-04-partitions-1406.ivf", - "vp80-05-sharpness-1428.ivf", "vp80-05-sharpness-1429.ivf", - "vp80-05-sharpness-1430.ivf", "vp80-05-sharpness-1431.ivf", - "vp80-05-sharpness-1433.ivf", "vp80-05-sharpness-1434.ivf", - "vp80-05-sharpness-1438.ivf", "vp80-05-sharpness-1439.ivf", - "vp80-05-sharpness-1440.ivf", "vp80-05-sharpness-1443.ivf", - "vp80-06-smallsize.ivf" -}; -#endif -#if CONFIG_VP9_DECODER -const char *kVP9TestVectors[] = { - "vp90-2-00-quantizer-00.webm", "vp90-2-00-quantizer-01.webm", - "vp90-2-00-quantizer-02.webm", "vp90-2-00-quantizer-03.webm", - "vp90-2-00-quantizer-04.webm", "vp90-2-00-quantizer-05.webm", - "vp90-2-00-quantizer-06.webm", "vp90-2-00-quantizer-07.webm", - "vp90-2-00-quantizer-08.webm", "vp90-2-00-quantizer-09.webm", - "vp90-2-00-quantizer-10.webm", "vp90-2-00-quantizer-11.webm", - "vp90-2-00-quantizer-12.webm", "vp90-2-00-quantizer-13.webm", - "vp90-2-00-quantizer-14.webm", "vp90-2-00-quantizer-15.webm", - "vp90-2-00-quantizer-16.webm", "vp90-2-00-quantizer-17.webm", - "vp90-2-00-quantizer-18.webm", "vp90-2-00-quantizer-19.webm", - "vp90-2-00-quantizer-20.webm", "vp90-2-00-quantizer-21.webm", - "vp90-2-00-quantizer-22.webm", "vp90-2-00-quantizer-23.webm", - "vp90-2-00-quantizer-24.webm", "vp90-2-00-quantizer-25.webm", - "vp90-2-00-quantizer-26.webm", "vp90-2-00-quantizer-27.webm", - "vp90-2-00-quantizer-28.webm", "vp90-2-00-quantizer-29.webm", - "vp90-2-00-quantizer-30.webm", "vp90-2-00-quantizer-31.webm", - "vp90-2-00-quantizer-32.webm", "vp90-2-00-quantizer-33.webm", - "vp90-2-00-quantizer-34.webm", "vp90-2-00-quantizer-35.webm", - "vp90-2-00-quantizer-36.webm", "vp90-2-00-quantizer-37.webm", - "vp90-2-00-quantizer-38.webm", "vp90-2-00-quantizer-39.webm", - "vp90-2-00-quantizer-40.webm", "vp90-2-00-quantizer-41.webm", - "vp90-2-00-quantizer-42.webm", "vp90-2-00-quantizer-43.webm", - "vp90-2-00-quantizer-44.webm", "vp90-2-00-quantizer-45.webm", - "vp90-2-00-quantizer-46.webm", "vp90-2-00-quantizer-47.webm", - "vp90-2-00-quantizer-48.webm", "vp90-2-00-quantizer-49.webm", - "vp90-2-00-quantizer-50.webm", "vp90-2-00-quantizer-51.webm", - "vp90-2-00-quantizer-52.webm", "vp90-2-00-quantizer-53.webm", - "vp90-2-00-quantizer-54.webm", "vp90-2-00-quantizer-55.webm", - "vp90-2-00-quantizer-56.webm", "vp90-2-00-quantizer-57.webm", - "vp90-2-00-quantizer-58.webm", "vp90-2-00-quantizer-59.webm", - "vp90-2-00-quantizer-60.webm", "vp90-2-00-quantizer-61.webm", - "vp90-2-00-quantizer-62.webm", "vp90-2-00-quantizer-63.webm", - "vp90-2-01-sharpness-1.webm", "vp90-2-01-sharpness-2.webm", - "vp90-2-01-sharpness-3.webm", "vp90-2-01-sharpness-4.webm", - "vp90-2-01-sharpness-5.webm", "vp90-2-01-sharpness-6.webm", - "vp90-2-01-sharpness-7.webm", "vp90-2-02-size-08x08.webm", - "vp90-2-02-size-08x10.webm", "vp90-2-02-size-08x16.webm", - "vp90-2-02-size-08x18.webm", "vp90-2-02-size-08x32.webm", - "vp90-2-02-size-08x34.webm", "vp90-2-02-size-08x64.webm", - "vp90-2-02-size-08x66.webm", "vp90-2-02-size-10x08.webm", - "vp90-2-02-size-10x10.webm", "vp90-2-02-size-10x16.webm", - "vp90-2-02-size-10x18.webm", "vp90-2-02-size-10x32.webm", - "vp90-2-02-size-10x34.webm", "vp90-2-02-size-10x64.webm", - "vp90-2-02-size-10x66.webm", "vp90-2-02-size-16x08.webm", - "vp90-2-02-size-16x10.webm", "vp90-2-02-size-16x16.webm", - "vp90-2-02-size-16x18.webm", "vp90-2-02-size-16x32.webm", - "vp90-2-02-size-16x34.webm", "vp90-2-02-size-16x64.webm", - "vp90-2-02-size-16x66.webm", "vp90-2-02-size-18x08.webm", - "vp90-2-02-size-18x10.webm", "vp90-2-02-size-18x16.webm", - "vp90-2-02-size-18x18.webm", "vp90-2-02-size-18x32.webm", - "vp90-2-02-size-18x34.webm", "vp90-2-02-size-18x64.webm", - "vp90-2-02-size-18x66.webm", "vp90-2-02-size-32x08.webm", - "vp90-2-02-size-32x10.webm", "vp90-2-02-size-32x16.webm", - "vp90-2-02-size-32x18.webm", "vp90-2-02-size-32x32.webm", - "vp90-2-02-size-32x34.webm", "vp90-2-02-size-32x64.webm", - "vp90-2-02-size-32x66.webm", "vp90-2-02-size-34x08.webm", - "vp90-2-02-size-34x10.webm", "vp90-2-02-size-34x16.webm", - "vp90-2-02-size-34x18.webm", "vp90-2-02-size-34x32.webm", - "vp90-2-02-size-34x34.webm", "vp90-2-02-size-34x64.webm", - "vp90-2-02-size-34x66.webm", "vp90-2-02-size-64x08.webm", - "vp90-2-02-size-64x10.webm", "vp90-2-02-size-64x16.webm", - "vp90-2-02-size-64x18.webm", "vp90-2-02-size-64x32.webm", - "vp90-2-02-size-64x34.webm", "vp90-2-02-size-64x64.webm", - "vp90-2-02-size-64x66.webm", "vp90-2-02-size-66x08.webm", - "vp90-2-02-size-66x10.webm", "vp90-2-02-size-66x16.webm", - "vp90-2-02-size-66x18.webm", "vp90-2-02-size-66x32.webm", - "vp90-2-02-size-66x34.webm", "vp90-2-02-size-66x64.webm", - "vp90-2-02-size-66x66.webm", "vp90-2-03-size-196x196.webm", - "vp90-2-03-size-196x198.webm", "vp90-2-03-size-196x200.webm", - "vp90-2-03-size-196x202.webm", "vp90-2-03-size-196x208.webm", - "vp90-2-03-size-196x210.webm", "vp90-2-03-size-196x224.webm", - "vp90-2-03-size-196x226.webm", "vp90-2-03-size-198x196.webm", - "vp90-2-03-size-198x198.webm", "vp90-2-03-size-198x200.webm", - "vp90-2-03-size-198x202.webm", "vp90-2-03-size-198x208.webm", - "vp90-2-03-size-198x210.webm", "vp90-2-03-size-198x224.webm", - "vp90-2-03-size-198x226.webm", "vp90-2-03-size-200x196.webm", - "vp90-2-03-size-200x198.webm", "vp90-2-03-size-200x200.webm", - "vp90-2-03-size-200x202.webm", "vp90-2-03-size-200x208.webm", - "vp90-2-03-size-200x210.webm", "vp90-2-03-size-200x224.webm", - "vp90-2-03-size-200x226.webm", "vp90-2-03-size-202x196.webm", - "vp90-2-03-size-202x198.webm", "vp90-2-03-size-202x200.webm", - "vp90-2-03-size-202x202.webm", "vp90-2-03-size-202x208.webm", - "vp90-2-03-size-202x210.webm", "vp90-2-03-size-202x224.webm", - "vp90-2-03-size-202x226.webm", "vp90-2-03-size-208x196.webm", - "vp90-2-03-size-208x198.webm", "vp90-2-03-size-208x200.webm", - "vp90-2-03-size-208x202.webm", "vp90-2-03-size-208x208.webm", - "vp90-2-03-size-208x210.webm", "vp90-2-03-size-208x224.webm", - "vp90-2-03-size-208x226.webm", "vp90-2-03-size-210x196.webm", - "vp90-2-03-size-210x198.webm", "vp90-2-03-size-210x200.webm", - "vp90-2-03-size-210x202.webm", "vp90-2-03-size-210x208.webm", - "vp90-2-03-size-210x210.webm", "vp90-2-03-size-210x224.webm", - "vp90-2-03-size-210x226.webm", "vp90-2-03-size-224x196.webm", - "vp90-2-03-size-224x198.webm", "vp90-2-03-size-224x200.webm", - "vp90-2-03-size-224x202.webm", "vp90-2-03-size-224x208.webm", - "vp90-2-03-size-224x210.webm", "vp90-2-03-size-224x224.webm", - "vp90-2-03-size-224x226.webm", "vp90-2-03-size-226x196.webm", - "vp90-2-03-size-226x198.webm", "vp90-2-03-size-226x200.webm", - "vp90-2-03-size-226x202.webm", "vp90-2-03-size-226x208.webm", - "vp90-2-03-size-226x210.webm", "vp90-2-03-size-226x224.webm", - "vp90-2-03-size-226x226.webm", "vp90-2-03-deltaq.webm", - "vp90-2-05-resize.ivf", "vp90-2-06-bilinear.webm", - "vp90-2-07-frame_parallel.webm", - "vp90-2-08-tile_1x2_frame_parallel.webm", "vp90-2-08-tile_1x2.webm", - "vp90-2-08-tile_1x4_frame_parallel.webm", "vp90-2-08-tile_1x4.webm", - "vp90-2-08-tile_1x8_frame_parallel.webm", "vp90-2-08-tile_1x8.webm", - "vp90-2-08-tile-4x4.webm", "vp90-2-08-tile-4x1.webm", - "vp90-2-09-subpixel-00.ivf", - "vp90-2-02-size-lf-1920x1080.webm", -#if CONFIG_NON420 - "vp91-2-04-yv444.webm" -#endif -}; -#endif class TestVectorTest : public ::libvpx_test::DecoderTest, public ::libvpx_test::CodecTestWithParam<const char*> { @@ -241,8 +91,8 @@ TEST_P(TestVectorTest, MD5Match) { } VP8_INSTANTIATE_TEST_CASE(TestVectorTest, - ::testing::ValuesIn(kVP8TestVectors)); + ::testing::ValuesIn(libvpx_test::kVP8TestVectors)); VP9_INSTANTIATE_TEST_CASE(TestVectorTest, - ::testing::ValuesIn(kVP9TestVectors)); + ::testing::ValuesIn(libvpx_test::kVP9TestVectors)); } // namespace diff --git a/test/test_vectors.cc b/test/test_vectors.cc new file mode 100644 index 000000000..7ffecf087 --- /dev/null +++ b/test/test_vectors.cc @@ -0,0 +1,167 @@ +/* + * 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 "test/test_vectors.h" + +namespace libvpx_test { + +#if CONFIG_VP8_DECODER +const char *kVP8TestVectors[kNumVp8TestVectors] = { + "vp80-00-comprehensive-001.ivf", + "vp80-00-comprehensive-002.ivf", "vp80-00-comprehensive-003.ivf", + "vp80-00-comprehensive-004.ivf", "vp80-00-comprehensive-005.ivf", + "vp80-00-comprehensive-006.ivf", "vp80-00-comprehensive-007.ivf", + "vp80-00-comprehensive-008.ivf", "vp80-00-comprehensive-009.ivf", + "vp80-00-comprehensive-010.ivf", "vp80-00-comprehensive-011.ivf", + "vp80-00-comprehensive-012.ivf", "vp80-00-comprehensive-013.ivf", + "vp80-00-comprehensive-014.ivf", "vp80-00-comprehensive-015.ivf", + "vp80-00-comprehensive-016.ivf", "vp80-00-comprehensive-017.ivf", + "vp80-00-comprehensive-018.ivf", "vp80-01-intra-1400.ivf", + "vp80-01-intra-1411.ivf", "vp80-01-intra-1416.ivf", + "vp80-01-intra-1417.ivf", "vp80-02-inter-1402.ivf", + "vp80-02-inter-1412.ivf", "vp80-02-inter-1418.ivf", + "vp80-02-inter-1424.ivf", "vp80-03-segmentation-01.ivf", + "vp80-03-segmentation-02.ivf", "vp80-03-segmentation-03.ivf", + "vp80-03-segmentation-04.ivf", "vp80-03-segmentation-1401.ivf", + "vp80-03-segmentation-1403.ivf", "vp80-03-segmentation-1407.ivf", + "vp80-03-segmentation-1408.ivf", "vp80-03-segmentation-1409.ivf", + "vp80-03-segmentation-1410.ivf", "vp80-03-segmentation-1413.ivf", + "vp80-03-segmentation-1414.ivf", "vp80-03-segmentation-1415.ivf", + "vp80-03-segmentation-1425.ivf", "vp80-03-segmentation-1426.ivf", + "vp80-03-segmentation-1427.ivf", "vp80-03-segmentation-1432.ivf", + "vp80-03-segmentation-1435.ivf", "vp80-03-segmentation-1436.ivf", + "vp80-03-segmentation-1437.ivf", "vp80-03-segmentation-1441.ivf", + "vp80-03-segmentation-1442.ivf", "vp80-04-partitions-1404.ivf", + "vp80-04-partitions-1405.ivf", "vp80-04-partitions-1406.ivf", + "vp80-05-sharpness-1428.ivf", "vp80-05-sharpness-1429.ivf", + "vp80-05-sharpness-1430.ivf", "vp80-05-sharpness-1431.ivf", + "vp80-05-sharpness-1433.ivf", "vp80-05-sharpness-1434.ivf", + "vp80-05-sharpness-1438.ivf", "vp80-05-sharpness-1439.ivf", + "vp80-05-sharpness-1440.ivf", "vp80-05-sharpness-1443.ivf", + "vp80-06-smallsize.ivf" +}; +#endif // CONFIG_VP8_DECODER +#if CONFIG_VP9_DECODER +const char *kVP9TestVectors[kNumVp9TestVectors] = { + "vp90-2-00-quantizer-00.webm", "vp90-2-00-quantizer-01.webm", + "vp90-2-00-quantizer-02.webm", "vp90-2-00-quantizer-03.webm", + "vp90-2-00-quantizer-04.webm", "vp90-2-00-quantizer-05.webm", + "vp90-2-00-quantizer-06.webm", "vp90-2-00-quantizer-07.webm", + "vp90-2-00-quantizer-08.webm", "vp90-2-00-quantizer-09.webm", + "vp90-2-00-quantizer-10.webm", "vp90-2-00-quantizer-11.webm", + "vp90-2-00-quantizer-12.webm", "vp90-2-00-quantizer-13.webm", + "vp90-2-00-quantizer-14.webm", "vp90-2-00-quantizer-15.webm", + "vp90-2-00-quantizer-16.webm", "vp90-2-00-quantizer-17.webm", + "vp90-2-00-quantizer-18.webm", "vp90-2-00-quantizer-19.webm", + "vp90-2-00-quantizer-20.webm", "vp90-2-00-quantizer-21.webm", + "vp90-2-00-quantizer-22.webm", "vp90-2-00-quantizer-23.webm", + "vp90-2-00-quantizer-24.webm", "vp90-2-00-quantizer-25.webm", + "vp90-2-00-quantizer-26.webm", "vp90-2-00-quantizer-27.webm", + "vp90-2-00-quantizer-28.webm", "vp90-2-00-quantizer-29.webm", + "vp90-2-00-quantizer-30.webm", "vp90-2-00-quantizer-31.webm", + "vp90-2-00-quantizer-32.webm", "vp90-2-00-quantizer-33.webm", + "vp90-2-00-quantizer-34.webm", "vp90-2-00-quantizer-35.webm", + "vp90-2-00-quantizer-36.webm", "vp90-2-00-quantizer-37.webm", + "vp90-2-00-quantizer-38.webm", "vp90-2-00-quantizer-39.webm", + "vp90-2-00-quantizer-40.webm", "vp90-2-00-quantizer-41.webm", + "vp90-2-00-quantizer-42.webm", "vp90-2-00-quantizer-43.webm", + "vp90-2-00-quantizer-44.webm", "vp90-2-00-quantizer-45.webm", + "vp90-2-00-quantizer-46.webm", "vp90-2-00-quantizer-47.webm", + "vp90-2-00-quantizer-48.webm", "vp90-2-00-quantizer-49.webm", + "vp90-2-00-quantizer-50.webm", "vp90-2-00-quantizer-51.webm", + "vp90-2-00-quantizer-52.webm", "vp90-2-00-quantizer-53.webm", + "vp90-2-00-quantizer-54.webm", "vp90-2-00-quantizer-55.webm", + "vp90-2-00-quantizer-56.webm", "vp90-2-00-quantizer-57.webm", + "vp90-2-00-quantizer-58.webm", "vp90-2-00-quantizer-59.webm", + "vp90-2-00-quantizer-60.webm", "vp90-2-00-quantizer-61.webm", + "vp90-2-00-quantizer-62.webm", "vp90-2-00-quantizer-63.webm", + "vp90-2-01-sharpness-1.webm", "vp90-2-01-sharpness-2.webm", + "vp90-2-01-sharpness-3.webm", "vp90-2-01-sharpness-4.webm", + "vp90-2-01-sharpness-5.webm", "vp90-2-01-sharpness-6.webm", + "vp90-2-01-sharpness-7.webm", "vp90-2-02-size-08x08.webm", + "vp90-2-02-size-08x10.webm", "vp90-2-02-size-08x16.webm", + "vp90-2-02-size-08x18.webm", "vp90-2-02-size-08x32.webm", + "vp90-2-02-size-08x34.webm", "vp90-2-02-size-08x64.webm", + "vp90-2-02-size-08x66.webm", "vp90-2-02-size-10x08.webm", + "vp90-2-02-size-10x10.webm", "vp90-2-02-size-10x16.webm", + "vp90-2-02-size-10x18.webm", "vp90-2-02-size-10x32.webm", + "vp90-2-02-size-10x34.webm", "vp90-2-02-size-10x64.webm", + "vp90-2-02-size-10x66.webm", "vp90-2-02-size-16x08.webm", + "vp90-2-02-size-16x10.webm", "vp90-2-02-size-16x16.webm", + "vp90-2-02-size-16x18.webm", "vp90-2-02-size-16x32.webm", + "vp90-2-02-size-16x34.webm", "vp90-2-02-size-16x64.webm", + "vp90-2-02-size-16x66.webm", "vp90-2-02-size-18x08.webm", + "vp90-2-02-size-18x10.webm", "vp90-2-02-size-18x16.webm", + "vp90-2-02-size-18x18.webm", "vp90-2-02-size-18x32.webm", + "vp90-2-02-size-18x34.webm", "vp90-2-02-size-18x64.webm", + "vp90-2-02-size-18x66.webm", "vp90-2-02-size-32x08.webm", + "vp90-2-02-size-32x10.webm", "vp90-2-02-size-32x16.webm", + "vp90-2-02-size-32x18.webm", "vp90-2-02-size-32x32.webm", + "vp90-2-02-size-32x34.webm", "vp90-2-02-size-32x64.webm", + "vp90-2-02-size-32x66.webm", "vp90-2-02-size-34x08.webm", + "vp90-2-02-size-34x10.webm", "vp90-2-02-size-34x16.webm", + "vp90-2-02-size-34x18.webm", "vp90-2-02-size-34x32.webm", + "vp90-2-02-size-34x34.webm", "vp90-2-02-size-34x64.webm", + "vp90-2-02-size-34x66.webm", "vp90-2-02-size-64x08.webm", + "vp90-2-02-size-64x10.webm", "vp90-2-02-size-64x16.webm", + "vp90-2-02-size-64x18.webm", "vp90-2-02-size-64x32.webm", + "vp90-2-02-size-64x34.webm", "vp90-2-02-size-64x64.webm", + "vp90-2-02-size-64x66.webm", "vp90-2-02-size-66x08.webm", + "vp90-2-02-size-66x10.webm", "vp90-2-02-size-66x16.webm", + "vp90-2-02-size-66x18.webm", "vp90-2-02-size-66x32.webm", + "vp90-2-02-size-66x34.webm", "vp90-2-02-size-66x64.webm", + "vp90-2-02-size-66x66.webm", "vp90-2-03-size-196x196.webm", + "vp90-2-03-size-196x198.webm", "vp90-2-03-size-196x200.webm", + "vp90-2-03-size-196x202.webm", "vp90-2-03-size-196x208.webm", + "vp90-2-03-size-196x210.webm", "vp90-2-03-size-196x224.webm", + "vp90-2-03-size-196x226.webm", "vp90-2-03-size-198x196.webm", + "vp90-2-03-size-198x198.webm", "vp90-2-03-size-198x200.webm", + "vp90-2-03-size-198x202.webm", "vp90-2-03-size-198x208.webm", + "vp90-2-03-size-198x210.webm", "vp90-2-03-size-198x224.webm", + "vp90-2-03-size-198x226.webm", "vp90-2-03-size-200x196.webm", + "vp90-2-03-size-200x198.webm", "vp90-2-03-size-200x200.webm", + "vp90-2-03-size-200x202.webm", "vp90-2-03-size-200x208.webm", + "vp90-2-03-size-200x210.webm", "vp90-2-03-size-200x224.webm", + "vp90-2-03-size-200x226.webm", "vp90-2-03-size-202x196.webm", + "vp90-2-03-size-202x198.webm", "vp90-2-03-size-202x200.webm", + "vp90-2-03-size-202x202.webm", "vp90-2-03-size-202x208.webm", + "vp90-2-03-size-202x210.webm", "vp90-2-03-size-202x224.webm", + "vp90-2-03-size-202x226.webm", "vp90-2-03-size-208x196.webm", + "vp90-2-03-size-208x198.webm", "vp90-2-03-size-208x200.webm", + "vp90-2-03-size-208x202.webm", "vp90-2-03-size-208x208.webm", + "vp90-2-03-size-208x210.webm", "vp90-2-03-size-208x224.webm", + "vp90-2-03-size-208x226.webm", "vp90-2-03-size-210x196.webm", + "vp90-2-03-size-210x198.webm", "vp90-2-03-size-210x200.webm", + "vp90-2-03-size-210x202.webm", "vp90-2-03-size-210x208.webm", + "vp90-2-03-size-210x210.webm", "vp90-2-03-size-210x224.webm", + "vp90-2-03-size-210x226.webm", "vp90-2-03-size-224x196.webm", + "vp90-2-03-size-224x198.webm", "vp90-2-03-size-224x200.webm", + "vp90-2-03-size-224x202.webm", "vp90-2-03-size-224x208.webm", + "vp90-2-03-size-224x210.webm", "vp90-2-03-size-224x224.webm", + "vp90-2-03-size-224x226.webm", "vp90-2-03-size-226x196.webm", + "vp90-2-03-size-226x198.webm", "vp90-2-03-size-226x200.webm", + "vp90-2-03-size-226x202.webm", "vp90-2-03-size-226x208.webm", + "vp90-2-03-size-226x210.webm", "vp90-2-03-size-226x224.webm", + "vp90-2-03-size-226x226.webm", "vp90-2-03-deltaq.webm", + "vp90-2-05-resize.ivf", "vp90-2-06-bilinear.webm", + "vp90-2-07-frame_parallel.webm", + "vp90-2-08-tile_1x2_frame_parallel.webm", "vp90-2-08-tile_1x2.webm", + "vp90-2-08-tile_1x4_frame_parallel.webm", "vp90-2-08-tile_1x4.webm", + "vp90-2-08-tile_1x8_frame_parallel.webm", "vp90-2-08-tile_1x8.webm", + "vp90-2-08-tile-4x4.webm", "vp90-2-08-tile-4x1.webm", + "vp90-2-09-subpixel-00.ivf", + "vp90-2-02-size-lf-1920x1080.webm", +#if CONFIG_NON420 + "vp91-2-04-yv444.webm" +#endif +}; +#endif // CONFIG_VP9_DECODER + +} // namespace libvpx_test diff --git a/test/test_vectors.h b/test/test_vectors.h new file mode 100644 index 000000000..942175aa2 --- /dev/null +++ b/test/test_vectors.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#ifndef TEST_TEST_VECTORS_H_ +#define TEST_TEST_VECTORS_H_ + +#include "./vpx_config.h" + +namespace libvpx_test { + +#if CONFIG_VP8_DECODER +const int kNumVp8TestVectors = 62; +extern const char *kVP8TestVectors[kNumVp8TestVectors]; +#endif + +#if CONFIG_VP9_DECODER +#if CONFIG_NON420 +const int kNumVp9TestVectors = 214; +#else +const int kNumVp9TestVectors = 213; +#endif + +extern const char *kVP9TestVectors[kNumVp9TestVectors]; +#endif // CONFIG_VP9_DECODER + +} // namespace libvpx_test + +#endif // TEST_TEST_VECTORS_H_ diff --git a/test/tile_independence_test.cc b/test/tile_independence_test.cc index 403dbb6c0..863a3669a 100644 --- a/test/tile_independence_test.cc +++ b/test/tile_independence_test.cc @@ -1,11 +1,11 @@ /* - Copyright (c) 2012 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. + * 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> diff --git a/test/vp8_fdct4x4_test.cc b/test/vp8_fdct4x4_test.cc index c82343668..25465c53c 100644 --- a/test/vp8_fdct4x4_test.cc +++ b/test/vp8_fdct4x4_test.cc @@ -1,13 +1,12 @@ /* -* Copyright (c) 2012 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. -*/ - + * 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 <math.h> #include <stddef.h> @@ -16,7 +15,6 @@ #include <string.h> #include <sys/types.h> - extern "C" { #include "./vp8_rtcd.h" } @@ -25,7 +23,6 @@ extern "C" { #include "third_party/googletest/src/include/gtest/gtest.h" #include "vpx/vpx_integer.h" - namespace { const int cospi8sqrt2minus1 = 20091; diff --git a/test/vp9_lossless_test.cc b/test/vp9_lossless_test.cc index e8c32b41c..03b89f8df 100644 --- a/test/vp9_lossless_test.cc +++ b/test/vp9_lossless_test.cc @@ -1,12 +1,12 @@ /* - Copyright (c) 2012 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. -*/ + * 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 "third_party/googletest/src/include/gtest/gtest.h" #include "test/codec_factory.h" diff --git a/test/webm_video_source.h b/test/webm_video_source.h index 9fc854593..53b0ba2b4 100644 --- a/test/webm_video_source.h +++ b/test/webm_video_source.h @@ -90,8 +90,12 @@ class WebMVideoSource : public CompressedVideoSource { virtual ~WebMVideoSource() { if (input_file_) fclose(input_file_); - if (nestegg_ctx_) + if (nestegg_ctx_ != NULL) { + if (pkt_ != NULL) { + nestegg_free_packet(pkt_); + } nestegg_destroy(nestegg_ctx_); + } } virtual void Init() { @@ -136,8 +140,10 @@ class WebMVideoSource : public CompressedVideoSource { do { /* End of this packet, get another. */ - if (pkt_) + if (pkt_ != NULL) { nestegg_free_packet(pkt_); + pkt_ = NULL; + } int again = nestegg_read_packet(nestegg_ctx_, &pkt_); ASSERT_GE(again, 0) << "nestegg_read_packet failed"; diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index 871b8d385..0b4c4cbbf 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -929,6 +929,7 @@ CODEC_INTERFACE(vpx_codec_vp8_dx) = vp8_get_si, /* vpx_codec_get_si_fn_t get_si; */ vp8_decode, /* vpx_codec_decode_fn_t decode; */ vp8_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */ + NOT_IMPLEMENTED, }, { /* encoder functions */ NOT_IMPLEMENTED, diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index f56784071..80c48d13c 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -34,7 +34,7 @@ void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi) { void vp9_free_frame_buffers(VP9_COMMON *cm) { int i; - for (i = 0; i < FRAME_BUFFERS; i++) + for (i = 0; i < cm->fb_count; i++) vp9_free_frame_buffer(&cm->yv12_fb[i]); vp9_free_frame_buffer(&cm->post_proc_buffer); @@ -86,7 +86,7 @@ int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) { int mi_size; if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, - VP9BORDERINPIXELS) < 0) + VP9BORDERINPIXELS, NULL, NULL, NULL) < 0) goto fail; set_mb_mi(cm, aligned_width, aligned_height); @@ -138,16 +138,28 @@ int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) { const int ss_y = cm->subsampling_y; int mi_size; + if (cm->fb_count == 0) { + cm->fb_count = FRAME_BUFFERS; + CHECK_MEM_ERROR(cm, cm->yv12_fb, + vpx_calloc(cm->fb_count, sizeof(*cm->yv12_fb))); + CHECK_MEM_ERROR(cm, cm->fb_idx_ref_cnt, + vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_cnt))); + if (cm->fb_lru) { + CHECK_MEM_ERROR(cm, cm->fb_idx_ref_lru, + vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_lru))); + } + } + vp9_free_frame_buffers(cm); - for (i = 0; i < FRAME_BUFFERS; i++) { + for (i = 0; i < cm->fb_count; i++) { cm->fb_idx_ref_cnt[i] = 0; if (vp9_alloc_frame_buffer(&cm->yv12_fb[i], width, height, ss_x, ss_y, VP9BORDERINPIXELS) < 0) goto fail; } - cm->new_fb_idx = FRAME_BUFFERS - 1; + cm->new_fb_idx = cm->fb_count - 1; cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1; for (i = 0; i < REFS_PER_FRAME; i++) @@ -203,6 +215,14 @@ void vp9_create_common(VP9_COMMON *cm) { void vp9_remove_common(VP9_COMMON *cm) { vp9_free_frame_buffers(cm); + + vpx_free(cm->yv12_fb); + vpx_free(cm->fb_idx_ref_cnt); + vpx_free(cm->fb_idx_ref_lru); + + cm->yv12_fb = NULL; + cm->fb_idx_ref_cnt = NULL; + cm->fb_idx_ref_lru = NULL; } void vp9_initialize_common() { diff --git a/vp9/common/vp9_convolve.c b/vp9/common/vp9_convolve.c index a2d864c72..6edf7eaca 100644 --- a/vp9/common/vp9_convolve.c +++ b/vp9/common/vp9_convolve.c @@ -18,40 +18,21 @@ #include "vpx/vpx_integer.h" #include "vpx_ports/mem.h" -static void convolve_horiz_c(const uint8_t *src, ptrdiff_t src_stride, - uint8_t *dst, ptrdiff_t dst_stride, - const int16_t *filter_x0, int x_step_q4, - const int16_t *filter_y, int y_step_q4, - int w, int h, int taps) { - int x, y, k; - - /* NOTE: This assumes that the filter table is 256-byte aligned. */ - /* TODO(agrange) Modify to make independent of table alignment. */ - const int16_t *const filter_x_base = - (const int16_t *)(((intptr_t)filter_x0) & ~(intptr_t)0xff); - - /* Adjust base pointer address for this source line */ - src -= taps / 2 - 1; - +static void convolve_horiz(const uint8_t *src, ptrdiff_t src_stride, + uint8_t *dst, ptrdiff_t dst_stride, + const subpel_kernel *x_filters, + int x0_q4, int x_step_q4, int w, int h) { + int x, y; + src -= SUBPEL_TAPS / 2 - 1; for (y = 0; y < h; ++y) { - /* Initial phase offset */ - int x_q4 = (int)(filter_x0 - filter_x_base) / taps; - + int x_q4 = x0_q4; for (x = 0; x < w; ++x) { - /* Per-pixel src offset */ - const int src_x = x_q4 >> SUBPEL_BITS; - int sum = 0; - - /* Pointer to filter to use */ - const int16_t *const filter_x = filter_x_base + - (x_q4 & SUBPEL_MASK) * taps; - - for (k = 0; k < taps; ++k) - sum += src[src_x + k] * filter_x[k]; - + const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS]; + const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK]; + int k, sum = 0; + for (k = 0; k < SUBPEL_TAPS; ++k) + sum += src_x[k] * x_filter[k]; dst[x] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); - - /* Move to the next source pixel */ x_q4 += x_step_q4; } src += src_stride; @@ -59,41 +40,22 @@ static void convolve_horiz_c(const uint8_t *src, ptrdiff_t src_stride, } } -static void convolve_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride, - uint8_t *dst, ptrdiff_t dst_stride, - const int16_t *filter_x0, int x_step_q4, - const int16_t *filter_y, int y_step_q4, - int w, int h, int taps) { - int x, y, k; - - /* NOTE: This assumes that the filter table is 256-byte aligned. */ - /* TODO(agrange) Modify to make independent of table alignment. */ - const int16_t *const filter_x_base = - (const int16_t *)(((intptr_t)filter_x0) & ~(intptr_t)0xff); - - /* Adjust base pointer address for this source line */ - src -= taps / 2 - 1; - +static void convolve_avg_horiz(const uint8_t *src, ptrdiff_t src_stride, + uint8_t *dst, ptrdiff_t dst_stride, + const subpel_kernel *x_filters, + int x0_q4, int x_step_q4, int w, int h) { + int x, y; + src -= SUBPEL_TAPS / 2 - 1; for (y = 0; y < h; ++y) { - /* Initial phase offset */ - int x_q4 = (int)(filter_x0 - filter_x_base) / taps; - + int x_q4 = x0_q4; for (x = 0; x < w; ++x) { - /* Per-pixel src offset */ - const int src_x = x_q4 >> SUBPEL_BITS; - int sum = 0; - - /* Pointer to filter to use */ - const int16_t *const filter_x = filter_x_base + - (x_q4 & SUBPEL_MASK) * taps; - - for (k = 0; k < taps; ++k) - sum += src[src_x + k] * filter_x[k]; - + const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS]; + const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK]; + int k, sum = 0; + for (k = 0; k < SUBPEL_TAPS; ++k) + sum += src_x[k] * x_filter[k]; dst[x] = ROUND_POWER_OF_TWO(dst[x] + - clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1); - - /* Move to the next source pixel */ + clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1); x_q4 += x_step_q4; } src += src_stride; @@ -101,41 +63,22 @@ static void convolve_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride, } } -static void convolve_vert_c(const uint8_t *src, ptrdiff_t src_stride, - uint8_t *dst, ptrdiff_t dst_stride, - const int16_t *filter_x, int x_step_q4, - const int16_t *filter_y0, int y_step_q4, - int w, int h, int taps) { - int x, y, k; - - /* NOTE: This assumes that the filter table is 256-byte aligned. */ - /* TODO(agrange) Modify to make independent of table alignment. */ - const int16_t *const filter_y_base = - (const int16_t *)(((intptr_t)filter_y0) & ~(intptr_t)0xff); - - /* Adjust base pointer address for this source column */ - src -= src_stride * (taps / 2 - 1); +static void convolve_vert(const uint8_t *src, ptrdiff_t src_stride, + uint8_t *dst, ptrdiff_t dst_stride, + const subpel_kernel *y_filters, + int y0_q4, int y_step_q4, int w, int h) { + int x, y; + src -= src_stride * (SUBPEL_TAPS / 2 - 1); for (x = 0; x < w; ++x) { - /* Initial phase offset */ - int y_q4 = (int)(filter_y0 - filter_y_base) / taps; - + int y_q4 = y0_q4; for (y = 0; y < h; ++y) { - /* Per-pixel src offset */ - const int src_y = y_q4 >> SUBPEL_BITS; - int sum = 0; - - /* Pointer to filter to use */ - const int16_t *const filter_y = filter_y_base + - (y_q4 & SUBPEL_MASK) * taps; - - for (k = 0; k < taps; ++k) - sum += src[(src_y + k) * src_stride] * filter_y[k]; - - dst[y * dst_stride] = - clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); - - /* Move to the next source pixel */ + const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride]; + const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK]; + int k, sum = 0; + for (k = 0; k < SUBPEL_TAPS; ++k) + sum += src_y[k * src_stride] * y_filter[k]; + dst[y * dst_stride] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); y_q4 += y_step_q4; } ++src; @@ -143,41 +86,23 @@ static void convolve_vert_c(const uint8_t *src, ptrdiff_t src_stride, } } -static void convolve_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride, - uint8_t *dst, ptrdiff_t dst_stride, - const int16_t *filter_x, int x_step_q4, - const int16_t *filter_y0, int y_step_q4, - int w, int h, int taps) { - int x, y, k; - - /* NOTE: This assumes that the filter table is 256-byte aligned. */ - /* TODO(agrange) Modify to make independent of table alignment. */ - const int16_t *const filter_y_base = - (const int16_t *)(((intptr_t)filter_y0) & ~(intptr_t)0xff); - - /* Adjust base pointer address for this source column */ - src -= src_stride * (taps / 2 - 1); +static void convolve_avg_vert(const uint8_t *src, ptrdiff_t src_stride, + uint8_t *dst, ptrdiff_t dst_stride, + const subpel_kernel *y_filters, + int y0_q4, int y_step_q4, int w, int h) { + int x, y; + src -= src_stride * (SUBPEL_TAPS / 2 - 1); for (x = 0; x < w; ++x) { - /* Initial phase offset */ - int y_q4 = (int)(filter_y0 - filter_y_base) / taps; - + int y_q4 = y0_q4; for (y = 0; y < h; ++y) { - /* Per-pixel src offset */ - const int src_y = y_q4 >> SUBPEL_BITS; - int sum = 0; - - /* Pointer to filter to use */ - const int16_t *const filter_y = filter_y_base + - (y_q4 & SUBPEL_MASK) * taps; - - for (k = 0; k < taps; ++k) - sum += src[(src_y + k) * src_stride] * filter_y[k]; - + const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride]; + const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK]; + int k, sum = 0; + for (k = 0; k < SUBPEL_TAPS; ++k) + sum += src_y[k * src_stride] * y_filter[k]; dst[y * dst_stride] = ROUND_POWER_OF_TWO(dst[y * dst_stride] + - clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1); - - /* Move to the next source pixel */ + clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1); y_q4 += y_step_q4; } ++src; @@ -185,33 +110,42 @@ static void convolve_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride, } } -static void convolve_c(const uint8_t *src, ptrdiff_t src_stride, - uint8_t *dst, ptrdiff_t dst_stride, - const int16_t *filter_x, int x_step_q4, - const int16_t *filter_y, int y_step_q4, - int w, int h, int taps) { - /* Fixed size intermediate buffer places limits on parameters. - * Maximum intermediate_height is 324, for y_step_q4 == 80, - * h == 64, taps == 8. - * y_step_q4 of 80 allows for 1/10 scale for 5 layer svc - */ +static void convolve(const uint8_t *src, ptrdiff_t src_stride, + uint8_t *dst, ptrdiff_t dst_stride, + const subpel_kernel *const x_filters, + int x0_q4, int x_step_q4, + const subpel_kernel *const y_filters, + int y0_q4, int y_step_q4, + int w, int h) { + // Fixed size intermediate buffer places limits on parameters. + // Maximum intermediate_height is 324, for y_step_q4 == 80, + // h == 64, taps == 8. + // y_step_q4 of 80 allows for 1/10 scale for 5 layer svc uint8_t temp[64 * 324]; - int intermediate_height = (((h - 1) * y_step_q4 + 15) >> 4) + taps; + int intermediate_height = (((h - 1) * y_step_q4 + 15) >> 4) + SUBPEL_TAPS; assert(w <= 64); assert(h <= 64); - assert(taps <= 8); assert(y_step_q4 <= 80); assert(x_step_q4 <= 80); if (intermediate_height < h) intermediate_height = h; - convolve_horiz_c(src - src_stride * (taps / 2 - 1), src_stride, temp, 64, - filter_x, x_step_q4, filter_y, y_step_q4, w, - intermediate_height, taps); - convolve_vert_c(temp + 64 * (taps / 2 - 1), 64, dst, dst_stride, filter_x, - x_step_q4, filter_y, y_step_q4, w, h, taps); + convolve_horiz(src - src_stride * (SUBPEL_TAPS / 2 - 1), src_stride, temp, 64, + x_filters, x0_q4, x_step_q4, w, intermediate_height); + convolve_vert(temp + 64 * (SUBPEL_TAPS / 2 - 1), 64, dst, dst_stride, + y_filters, y0_q4, y_step_q4, w, h); +} + +static const subpel_kernel *get_filter_base(const int16_t *filter) { + // NOTE: This assumes that the filter table is 256-byte aligned. + // TODO(agrange) Modify to make independent of table alignment. + return (const subpel_kernel *)(((intptr_t)filter) & ~((intptr_t)0xFF)); +} + +static int get_filter_offset(const int16_t *f, const subpel_kernel *base) { + return (const subpel_kernel *)(intptr_t)f - base; } void vp9_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride, @@ -219,8 +153,11 @@ void vp9_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h) { - convolve_horiz_c(src, src_stride, dst, dst_stride, - filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8); + const subpel_kernel *const filters_x = get_filter_base(filter_x); + const int x0_q4 = get_filter_offset(filter_x, filters_x); + + convolve_horiz(src, src_stride, dst, dst_stride, filters_x, + x0_q4, x_step_q4, w, h); } void vp9_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride, @@ -228,8 +165,11 @@ void vp9_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h) { - convolve_avg_horiz_c(src, src_stride, dst, dst_stride, - filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8); + const subpel_kernel *const filters_x = get_filter_base(filter_x); + const int x0_q4 = get_filter_offset(filter_x, filters_x); + + convolve_avg_horiz(src, src_stride, dst, dst_stride, filters_x, + x0_q4, x_step_q4, w, h); } void vp9_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride, @@ -237,8 +177,10 @@ void vp9_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h) { - convolve_vert_c(src, src_stride, dst, dst_stride, - filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8); + const subpel_kernel *const filters_y = get_filter_base(filter_y); + const int y0_q4 = get_filter_offset(filter_y, filters_y); + convolve_vert(src, src_stride, dst, dst_stride, filters_y, + y0_q4, y_step_q4, w, h); } void vp9_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride, @@ -246,8 +188,10 @@ void vp9_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h) { - convolve_avg_vert_c(src, src_stride, dst, dst_stride, - filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8); + const subpel_kernel *const filters_y = get_filter_base(filter_y); + const int y0_q4 = get_filter_offset(filter_y, filters_y); + convolve_avg_vert(src, src_stride, dst, dst_stride, filters_y, + y0_q4, y_step_q4, w, h); } void vp9_convolve8_c(const uint8_t *src, ptrdiff_t src_stride, @@ -255,8 +199,15 @@ void vp9_convolve8_c(const uint8_t *src, ptrdiff_t src_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h) { - convolve_c(src, src_stride, dst, dst_stride, - filter_x, x_step_q4, filter_y, y_step_q4, w, h, 8); + const subpel_kernel *const filters_x = get_filter_base(filter_x); + const int x0_q4 = get_filter_offset(filter_x, filters_x); + + const subpel_kernel *const filters_y = get_filter_base(filter_y); + const int y0_q4 = get_filter_offset(filter_y, filters_y); + + convolve(src, src_stride, dst, dst_stride, + filters_x, x0_q4, x_step_q4, + filters_y, y0_q4, y_step_q4, w, h); } void vp9_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride, @@ -269,9 +220,9 @@ void vp9_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride, assert(w <= 64); assert(h <= 64); - vp9_convolve8(src, src_stride, temp, 64, - filter_x, x_step_q4, filter_y, y_step_q4, w, h); - vp9_convolve_avg(temp, 64, dst, dst_stride, NULL, 0, NULL, 0, w, h); + vp9_convolve8_c(src, src_stride, temp, 64, + filter_x, x_step_q4, filter_y, y_step_q4, w, h); + vp9_convolve_avg_c(temp, 64, dst, dst_stride, NULL, 0, NULL, 0, w, h); } void vp9_convolve_copy_c(const uint8_t *src, ptrdiff_t src_stride, diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h index 721917f05..65b679ad2 100644 --- a/vp9/common/vp9_entropy.h +++ b/vp9/common/vp9_entropy.h @@ -166,7 +166,7 @@ static int get_entropy_context(TX_SIZE tx_size, const ENTROPY_CONTEXT *a, left_ec = !!*(const uint64_t *)l; break; default: - assert(!"Invalid transform size."); + assert(0 && "Invalid transform size."); } return combine_entropy_contexts(above_ec, left_ec); diff --git a/vp9/common/vp9_findnearmv.c b/vp9/common/vp9_findnearmv.c index ad97c0277..7cdf2c1c7 100644 --- a/vp9/common/vp9_findnearmv.c +++ b/vp9/common/vp9_findnearmv.c @@ -36,46 +36,49 @@ void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp, void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd, const TileInfo *const tile, - int_mv *dst_nearest, int_mv *dst_near, - int block_idx, int ref_idx, - int mi_row, int mi_col) { + int block, int ref, int mi_row, int mi_col, + int_mv *nearest, int_mv *near) { int_mv mv_list[MAX_MV_REF_CANDIDATES]; MODE_INFO *const mi = xd->mi_8x8[0]; b_mode_info *bmi = mi->bmi; int n; - assert(ref_idx == 0 || ref_idx == 1); assert(MAX_MV_REF_CANDIDATES == 2); - vp9_find_mv_refs_idx(cm, xd, tile, mi, xd->last_mi, - mi->mbmi.ref_frame[ref_idx], - mv_list, block_idx, mi_row, mi_col); + vp9_find_mv_refs_idx(cm, xd, tile, mi, xd->last_mi, mi->mbmi.ref_frame[ref], + mv_list, block, mi_row, mi_col); - dst_near->as_int = 0; - if (block_idx == 0) { - dst_nearest->as_int = mv_list[0].as_int; - dst_near->as_int = mv_list[1].as_int; - } else if (block_idx == 1 || block_idx == 2) { - dst_nearest->as_int = bmi[0].as_mv[ref_idx].as_int; - for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n) - if (dst_nearest->as_int != mv_list[n].as_int) { - dst_near->as_int = mv_list[n].as_int; - break; - } - } else { - int_mv candidates[2 + MAX_MV_REF_CANDIDATES]; - candidates[0] = bmi[1].as_mv[ref_idx]; - candidates[1] = bmi[0].as_mv[ref_idx]; - candidates[2] = mv_list[0]; - candidates[3] = mv_list[1]; + near->as_int = 0; + switch (block) { + case 0: + nearest->as_int = mv_list[0].as_int; + near->as_int = mv_list[1].as_int; + break; + case 1: + case 2: + nearest->as_int = bmi[0].as_mv[ref].as_int; + for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n) + if (nearest->as_int != mv_list[n].as_int) { + near->as_int = mv_list[n].as_int; + break; + } + break; + case 3: { + int_mv candidates[2 + MAX_MV_REF_CANDIDATES]; + candidates[0] = bmi[1].as_mv[ref]; + candidates[1] = bmi[0].as_mv[ref]; + candidates[2] = mv_list[0]; + candidates[3] = mv_list[1]; - assert(block_idx == 3); - dst_nearest->as_int = bmi[2].as_mv[ref_idx].as_int; - for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n) { - if (dst_nearest->as_int != candidates[n].as_int) { - dst_near->as_int = candidates[n].as_int; - break; - } + nearest->as_int = bmi[2].as_mv[ref].as_int; + for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n) + if (nearest->as_int != candidates[n].as_int) { + near->as_int = candidates[n].as_int; + break; + } + break; } + default: + assert("Invalid block index."); } } diff --git a/vp9/common/vp9_findnearmv.h b/vp9/common/vp9_findnearmv.h index e9d4e1171..5028af77c 100644 --- a/vp9/common/vp9_findnearmv.h +++ b/vp9/common/vp9_findnearmv.h @@ -36,9 +36,7 @@ static void clamp_mv2(MV *mv, const MACROBLOCKD *xd) { void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd, const TileInfo *const tile, - int_mv *dst_nearest, - int_mv *dst_near, - int block_idx, int ref_idx, - int mi_row, int mi_col); + int block, int ref, int mi_row, int mi_col, + int_mv *nearest, int_mv *near); #endif // VP9_COMMON_VP9_FINDNEARMV_H_ diff --git a/vp9/common/vp9_mv.h b/vp9/common/vp9_mv.h index 31a79b984..155c3f12e 100644 --- a/vp9/common/vp9_mv.h +++ b/vp9/common/vp9_mv.h @@ -15,7 +15,7 @@ #include "vp9/common/vp9_common.h" -typedef struct { +typedef struct mv { int16_t row; int16_t col; } MV; @@ -25,7 +25,7 @@ typedef union int_mv { MV as_mv; } int_mv; /* facilitates faster equality tests and copies */ -typedef struct { +typedef struct mv32 { int32_t row; int32_t col; } MV32; diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h index c5faf88f8..65a2a5ed1 100644 --- a/vp9/common/vp9_onyx.h +++ b/vp9/common/vp9_onyx.h @@ -193,7 +193,7 @@ extern "C" int64_t end_time_stamp); int vp9_get_compressed_data(VP9_PTR comp, unsigned int *frame_flags, - unsigned long *size, unsigned char *dest, + size_t *size, uint8_t *dest, int64_t *time_stamp, int64_t *time_end, int flush); diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index a6e5b27e3..bfb94e44c 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -113,8 +113,8 @@ typedef struct VP9Common { YV12_BUFFER_CONFIG *frame_to_show; - YV12_BUFFER_CONFIG yv12_fb[FRAME_BUFFERS]; - int fb_idx_ref_cnt[FRAME_BUFFERS]; /* reference counts */ + YV12_BUFFER_CONFIG *yv12_fb; + int *fb_idx_ref_cnt; /* reference counts */ int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */ // TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and @@ -213,6 +213,15 @@ typedef struct VP9Common { int frame_parallel_decoding_mode; int log2_tile_cols, log2_tile_rows; + + vpx_codec_frame_buffer_t *fb_list; // External frame buffers + int fb_count; // Total number of frame buffers + vpx_realloc_frame_buffer_cb_fn_t realloc_fb_cb; + void *user_priv; // Private data associated with the external frame buffers. + + int fb_lru; // Flag telling if lru is on/off + uint32_t *fb_idx_ref_lru; // Frame buffer lru cache + uint32_t fb_idx_ref_lru_count; } VP9_COMMON; // ref == 0 => LAST_FRAME @@ -228,13 +237,27 @@ static YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) { static int get_free_fb(VP9_COMMON *cm) { int i; - for (i = 0; i < FRAME_BUFFERS; i++) - if (cm->fb_idx_ref_cnt[i] == 0) - break; + uint32_t lru_count = cm->fb_idx_ref_lru_count + 1; + int free_buffer_idx = cm->fb_count; + for (i = 0; i < cm->fb_count; i++) { + if (!cm->fb_lru) { + if (cm->fb_idx_ref_cnt[i] == 0) { + free_buffer_idx = i; + break; + } + } else { + if (cm->fb_idx_ref_cnt[i] == 0 && cm->fb_idx_ref_lru[i] < lru_count) { + free_buffer_idx = i; + lru_count = cm->fb_idx_ref_lru[i]; + } + } + } - assert(i < FRAME_BUFFERS); - cm->fb_idx_ref_cnt[i] = 1; - return i; + assert(free_buffer_idx < cm->fb_count); + cm->fb_idx_ref_cnt[free_buffer_idx] = 1; + if (cm->fb_lru) + cm->fb_idx_ref_lru[free_buffer_idx] = ++cm->fb_idx_ref_lru_count; + return free_buffer_idx; } static void ref_cnt_fb(int *buf, int *idx, int new_idx) { diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h index 66cd15143..23722ba72 100644 --- a/vp9/common/vp9_pred_common.h +++ b/vp9/common/vp9_pred_common.h @@ -104,7 +104,7 @@ static const vp9_prob *get_tx_probs(TX_SIZE max_tx_size, int ctx, case TX_32X32: return tx_probs->p32x32[ctx]; default: - assert(!"Invalid max_tx_size."); + assert(0 && "Invalid max_tx_size."); return NULL; } } @@ -124,7 +124,7 @@ static unsigned int *get_tx_counts(TX_SIZE max_tx_size, int ctx, case TX_32X32: return tx_counts->p32x32[ctx]; default: - assert(!"Invalid max_tx_size."); + assert(0 && "Invalid max_tx_size."); return NULL; } } diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c index a6e51d792..b17725243 100644 --- a/vp9/common/vp9_reconinter.c +++ b/vp9/common/vp9_reconinter.c @@ -397,7 +397,7 @@ void vp9_setup_scale_factors(VP9_COMMON *cm, int i) { const int ref = cm->active_ref_idx[i]; struct scale_factors *const sf = &cm->active_ref_scale[i]; struct scale_factors_common *const sfc = &cm->active_ref_scale_comm[i]; - if (ref >= FRAME_BUFFERS) { + if (ref >= cm->fb_count) { vp9_zero(*sf); vp9_zero(*sfc); } else { diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh index 19d5fc37d..727f5c437 100644 --- a/vp9/common/vp9_rtcd_defs.sh +++ b/vp9/common/vp9_rtcd_defs.sh @@ -14,6 +14,7 @@ struct macroblock; struct vp9_variance_vtable; #define DEC_MVCOSTS int *mvjcost, int *mvcost[2] +struct mv; union int_mv; struct yv12_buffer_config; EOF @@ -736,20 +737,20 @@ specialize vp9_fdct32x32_rd sse2 avx2 # # Motion search # -prototype int vp9_full_search_sad "struct macroblock *x, union int_mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv, int n" +prototype int vp9_full_search_sad "struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv, int n" specialize vp9_full_search_sad sse3 sse4_1 vp9_full_search_sad_sse3=vp9_full_search_sadx3 vp9_full_search_sad_sse4_1=vp9_full_search_sadx8 -prototype int vp9_refining_search_sad "struct macroblock *x, union int_mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv" +prototype int vp9_refining_search_sad "struct macroblock *x, struct mv *ref_mv, int sad_per_bit, int distance, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv" specialize vp9_refining_search_sad sse3 vp9_refining_search_sad_sse3=vp9_refining_search_sadx4 -prototype int vp9_diamond_search_sad "struct macroblock *x, union int_mv *ref_mv, union int_mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv" +prototype int vp9_diamond_search_sad "struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv" specialize vp9_diamond_search_sad sse3 vp9_diamond_search_sad_sse3=vp9_diamond_search_sadx4 -prototype int vp9_full_range_search "struct macroblock *x, union int_mv *ref_mv, union int_mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, union int_mv *center_mv" +prototype int vp9_full_range_search "struct macroblock *x, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, struct vp9_variance_vtable *fn_ptr, DEC_MVCOSTS, const struct mv *center_mv" specialize vp9_full_range_search prototype void vp9_temporal_filter_apply "uint8_t *frame1, unsigned int stride, uint8_t *frame2, unsigned int block_size, int strength, int filter_weight, unsigned int *accumulator, uint16_t *count" diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 56b05cee1..79f0835a7 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -266,7 +266,7 @@ static void inverse_transform_block(MACROBLOCKD* xd, int plane, int block, vp9_idct32x32_add(dqcoeff, dst, stride, eob); break; default: - assert(!"Invalid transform size"); + assert(0 && "Invalid transform size"); } if (eob == 1) { @@ -348,23 +348,27 @@ static void reconstruct_inter_block(int plane, int block, static void set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd, const TileInfo *const tile, BLOCK_SIZE bsize, int mi_row, int mi_col) { - const int bh = num_8x8_blocks_high_lookup[bsize]; const int bw = num_8x8_blocks_wide_lookup[bsize]; + const int bh = num_8x8_blocks_high_lookup[bsize]; + const int x_mis = MIN(bw, cm->mi_cols - mi_col); + const int y_mis = MIN(bh, cm->mi_rows - mi_row); const int offset = mi_row * cm->mode_info_stride + mi_col; const int tile_offset = tile->mi_row_start * cm->mode_info_stride + tile->mi_col_start; + int x, y; xd->mi_8x8 = cm->mi_grid_visible + offset; xd->prev_mi_8x8 = cm->prev_mi_grid_visible + offset; - - // we are using the mode info context stream here - xd->mi_8x8[0] = xd->mi_stream + offset - tile_offset; - xd->mi_8x8[0]->mbmi.sb_type = bsize; - // Special case: if prev_mi is NULL, the previous mode info context // cannot be used. xd->last_mi = cm->prev_mi ? xd->prev_mi_8x8[0] : NULL; + xd->mi_8x8[0] = xd->mi_stream + offset - tile_offset; + xd->mi_8x8[0]->mbmi.sb_type = bsize; + for (y = 0; y < y_mis; ++y) + for (x = !y; x < x_mis; ++x) + xd->mi_8x8[y * cm->mode_info_stride + x] = xd->mi_8x8[0]; + set_skip_context(xd, xd->above_context, xd->left_context, mi_row, mi_col); // Distance of Mb to the various image edges. These are specified to 8th pel @@ -507,7 +511,7 @@ static void decode_modes_sb(VP9_COMMON *const cm, MACROBLOCKD *const xd, decode_modes_sb(cm, xd, tile, mi_row + hbs, mi_col + hbs, r, subsize); break; default: - assert(!"Invalid partition type"); + assert(0 && "Invalid partition type"); } } @@ -703,9 +707,21 @@ static void apply_frame_size(VP9D_COMP *pbi, int width, int height) { vp9_update_frame_size(cm); } - vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height, - cm->subsampling_x, cm->subsampling_y, - VP9BORDERINPIXELS); + if (cm->fb_list != NULL) { + vpx_codec_frame_buffer_t *const ext_fb = &cm->fb_list[cm->new_fb_idx]; + if (vp9_realloc_frame_buffer(get_frame_new_buffer(cm), + cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, + VP9BORDERINPIXELS, ext_fb, + cm->realloc_fb_cb, cm->user_priv)) { + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate external frame buffer"); + } + } else { + vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, + VP9BORDERINPIXELS, NULL, NULL, NULL); + } } static void setup_frame_size(VP9D_COMP *pbi, diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 164576d0c..4e2bc3560 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -162,12 +162,12 @@ static int read_skip_coeff(VP9_COMMON *cm, const MACROBLOCKD *xd, static void read_intra_frame_mode_info(VP9_COMMON *const cm, MACROBLOCKD *const xd, - MODE_INFO *const m, int mi_row, int mi_col, vp9_reader *r) { - MB_MODE_INFO *const mbmi = &m->mbmi; - const BLOCK_SIZE bsize = mbmi->sb_type; + MODE_INFO *const mi = xd->mi_8x8[0]; + MB_MODE_INFO *const mbmi = &mi->mbmi; const MODE_INFO *above_mi = xd->mi_8x8[-cm->mode_info_stride]; const MODE_INFO *left_mi = xd->left_available ? xd->mi_8x8[-1] : NULL; + const BLOCK_SIZE bsize = mbmi->sb_type; mbmi->segment_id = read_intra_segment_id(cm, xd, mi_row, mi_col, r); mbmi->skip_coeff = read_skip_coeff(cm, xd, mbmi->segment_id, r); @@ -176,8 +176,8 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm, mbmi->ref_frame[1] = NONE; if (bsize >= BLOCK_8X8) { - const MB_PREDICTION_MODE A = above_block_mode(m, above_mi, 0); - const MB_PREDICTION_MODE L = left_block_mode(m, left_mi, 0); + const MB_PREDICTION_MODE A = above_block_mode(mi, above_mi, 0); + const MB_PREDICTION_MODE L = left_block_mode(mi, left_mi, 0); mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]); } else { // Only 4x4, 4x8, 8x4 blocks @@ -188,19 +188,19 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm, for (idy = 0; idy < 2; idy += num_4x4_h) { for (idx = 0; idx < 2; idx += num_4x4_w) { const int ib = idy * 2 + idx; - const MB_PREDICTION_MODE A = above_block_mode(m, above_mi, ib); - const MB_PREDICTION_MODE L = left_block_mode(m, left_mi, ib); + const MB_PREDICTION_MODE A = above_block_mode(mi, above_mi, ib); + const MB_PREDICTION_MODE L = left_block_mode(mi, left_mi, ib); const MB_PREDICTION_MODE b_mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]); - m->bmi[ib].as_mode = b_mode; + mi->bmi[ib].as_mode = b_mode; if (num_4x4_h == 2) - m->bmi[ib + 2].as_mode = b_mode; + mi->bmi[ib + 2].as_mode = b_mode; if (num_4x4_w == 2) - m->bmi[ib + 1].as_mode = b_mode; + mi->bmi[ib + 1].as_mode = b_mode; } } - mbmi->mode = m->bmi[3].as_mode; + mbmi->mode = mi->bmi[3].as_mode; } mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]); @@ -308,7 +308,7 @@ static void read_ref_frames(VP9_COMMON *const cm, MACROBLOCKD *const xd, ref_frame[1] = NONE; } else { - assert(!"Invalid prediction mode."); + assert(0 && "Invalid prediction mode."); } } } @@ -475,8 +475,8 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm, if (b_mode == NEARESTMV || b_mode == NEARMV) for (ref = 0; ref < 1 + is_compound; ++ref) - vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, &nearest[ref], - &nearmv[ref], j, ref, mi_row, mi_col); + vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col, + &nearest[ref], &nearmv[ref]); if (!assign_mv(cm, b_mode, block, best, nearest, nearmv, is_compound, allow_hp, r)) { @@ -509,8 +509,8 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm, static void read_inter_frame_mode_info(VP9_COMMON *const cm, MACROBLOCKD *const xd, const TileInfo *const tile, - MODE_INFO *const mi, int mi_row, int mi_col, vp9_reader *r) { + MODE_INFO *const mi = xd->mi_8x8[0]; MB_MODE_INFO *const mbmi = &mi->mbmi; int inter_block; @@ -528,25 +528,10 @@ static void read_inter_frame_mode_info(VP9_COMMON *const cm, read_intra_block_mode_info(cm, mi, r); } -void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd, - const TileInfo *const tile, +void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd, const TileInfo *tile, int mi_row, int mi_col, vp9_reader *r) { - MODE_INFO *const mi = xd->mi_8x8[0]; - const BLOCK_SIZE bsize = mi->mbmi.sb_type; - const int bw = num_8x8_blocks_wide_lookup[bsize]; - const int bh = num_8x8_blocks_high_lookup[bsize]; - const int y_mis = MIN(bh, cm->mi_rows - mi_row); - const int x_mis = MIN(bw, cm->mi_cols - mi_col); - int x, y, z; - if (frame_is_intra_only(cm)) - read_intra_frame_mode_info(cm, xd, mi, mi_row, mi_col, r); + read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r); else - read_inter_frame_mode_info(cm, xd, tile, mi, mi_row, mi_col, r); - - for (y = 0, z = 0; y < y_mis; y++, z += cm->mode_info_stride) { - for (x = !y; x < x_mis; x++) { - xd->mi_8x8[z + x] = mi; - } - } + read_inter_frame_mode_info(cm, xd, tile, mi_row, mi_col, r); } diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 1bbb12c7c..88e25ebf2 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -63,14 +63,14 @@ void vp9_entropy_mode_init() { static void write_intra_mode(vp9_writer *w, MB_PREDICTION_MODE mode, const vp9_prob *probs) { - write_token(w, vp9_intra_mode_tree, probs, &intra_mode_encodings[mode]); + vp9_write_token(w, vp9_intra_mode_tree, probs, &intra_mode_encodings[mode]); } static void write_inter_mode(vp9_writer *w, MB_PREDICTION_MODE mode, const vp9_prob *probs) { assert(is_inter_mode(mode)); - write_token(w, vp9_inter_mode_tree, probs, - &inter_mode_encodings[INTER_OFFSET(mode)]); + vp9_write_token(w, vp9_inter_mode_tree, probs, + &inter_mode_encodings[INTER_OFFSET(mode)]); } static INLINE void write_be32(uint8_t *p, int value) { @@ -179,12 +179,12 @@ static void pack_mb_tokens(vp9_writer* const w, if (t >= TWO_TOKEN && t < EOB_TOKEN) { int len = UNCONSTRAINED_NODES - p->skip_eob_node; int bits = v >> (n - len); - treed_write(w, vp9_coef_tree, p->context_tree, bits, len, i); - treed_write(w, vp9_coef_con_tree, - vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1], v, n - len, - 0); + vp9_write_tree(w, vp9_coef_tree, p->context_tree, bits, len, i); + vp9_write_tree(w, vp9_coef_con_tree, + vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1], + v, n - len, 0); } else { - treed_write(w, vp9_coef_tree, p->context_tree, v, n, i); + vp9_write_tree(w, vp9_coef_tree, p->context_tree, v, n, i); } if (b->base_val) { @@ -214,7 +214,7 @@ static void pack_mb_tokens(vp9_writer* const w, static void write_segment_id(vp9_writer *w, const struct segmentation *seg, int segment_id) { if (seg->enabled && seg->update_map) - treed_write(w, vp9_segment_tree, seg->tree_probs, segment_id, 3, 0); + vp9_write_tree(w, vp9_segment_tree, seg->tree_probs, segment_id, 3, 0); } // This function encodes the reference frame @@ -332,16 +332,15 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc) { if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (bsize >= BLOCK_8X8) { write_inter_mode(bc, mode, mv_ref_p); - ++cm->counts.inter_mode[mi->mode_context[rf]] - [INTER_OFFSET(mode)]; + ++cm->counts.inter_mode[mi->mode_context[rf]][INTER_OFFSET(mode)]; } } if (cm->mcomp_filter_type == SWITCHABLE) { const int ctx = vp9_get_pred_context_switchable_interp(xd); - write_token(bc, vp9_switchable_interp_tree, - cm->fc.switchable_interp_prob[ctx], - &switchable_interp_encodings[mi->interp_filter]); + vp9_write_token(bc, vp9_switchable_interp_tree, + cm->fc.switchable_interp_prob[ctx], + &switchable_interp_encodings[mi->interp_filter]); } else { assert(mi->interp_filter == cm->mcomp_filter_type); } @@ -470,7 +469,7 @@ static void write_partition(VP9_COMP *cpi, int hbs, int mi_row, int mi_col, const int has_cols = (mi_col + hbs) < cm->mi_cols; if (has_rows && has_cols) { - write_token(w, vp9_partition_tree, probs, &partition_encodings[p]); + vp9_write_token(w, vp9_partition_tree, probs, &partition_encodings[p]); } else if (!has_rows && has_cols) { assert(p == PARTITION_SPLIT || p == PARTITION_HORZ); vp9_write(w, p == PARTITION_SPLIT, probs[1]); @@ -778,38 +777,27 @@ static void encode_loopfilter(struct loopfilter *lf, vp9_wb_write_bit(wb, lf->mode_ref_delta_enabled); if (lf->mode_ref_delta_enabled) { - // Do the deltas need to be updated vp9_wb_write_bit(wb, lf->mode_ref_delta_update); if (lf->mode_ref_delta_update) { - // Send update for (i = 0; i < MAX_REF_LF_DELTAS; i++) { const int delta = lf->ref_deltas[i]; - - // Frame level data - if (delta != lf->last_ref_deltas[i]) { + const int changed = delta != lf->last_ref_deltas[i]; + vp9_wb_write_bit(wb, changed); + if (changed) { lf->last_ref_deltas[i] = delta; - vp9_wb_write_bit(wb, 1); - - assert(delta != 0); vp9_wb_write_literal(wb, abs(delta) & 0x3F, 6); vp9_wb_write_bit(wb, delta < 0); - } else { - vp9_wb_write_bit(wb, 0); } } - // Send update for (i = 0; i < MAX_MODE_LF_DELTAS; i++) { const int delta = lf->mode_deltas[i]; - if (delta != lf->last_mode_deltas[i]) { + const int changed = delta != lf->last_mode_deltas[i]; + vp9_wb_write_bit(wb, changed); + if (changed) { lf->last_mode_deltas[i] = delta; - vp9_wb_write_bit(wb, 1); - - assert(delta != 0); vp9_wb_write_literal(wb, abs(delta) & 0x3F, 6); vp9_wb_write_bit(wb, delta < 0); - } else { - vp9_wb_write_bit(wb, 0); } } } @@ -1304,7 +1292,7 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) { return header_bc.pos; } -void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { +void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size) { uint8_t *data = dest; size_t first_part_size; struct vp9_write_bit_buffer wb = {data, 0}; diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h index 00883385e..737fad4c2 100644 --- a/vp9/encoder/vp9_block.h +++ b/vp9/encoder/vp9_block.h @@ -59,6 +59,7 @@ typedef struct { // motion vector cache for adaptive motion search control in partition // search loop int_mv pred_mv[MAX_REF_FRAMES]; + int pred_filter_type; // Bit flag for each mode whether it has high error in comparison to others. unsigned int modes_with_high_error; diff --git a/vp9/encoder/vp9_boolhuff.h b/vp9/encoder/vp9_boolhuff.h index c3f340d1b..a0fff3861 100644 --- a/vp9/encoder/vp9_boolhuff.h +++ b/vp9/encoder/vp9_boolhuff.h @@ -111,5 +111,6 @@ static void vp9_write_literal(vp9_writer *w, int data, int bits) { vp9_write_bit(w, 1 & (data >> bit)); } +#define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8) #endif // VP9_ENCODER_VP9_BOOLHUFF_H_ diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 20c4e42e7..b845bc4f1 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -857,16 +857,9 @@ static void save_context(VP9_COMP *cpi, int mi_row, int mi_col, static void encode_b(VP9_COMP *cpi, const TileInfo *const tile, TOKENEXTRA **tp, int mi_row, int mi_col, - int output_enabled, BLOCK_SIZE bsize, int sub_index) { - VP9_COMMON *const cm = &cpi->common; + int output_enabled, BLOCK_SIZE bsize) { MACROBLOCK *const x = &cpi->mb; - if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) - return; - - if (sub_index != -1) - *get_sb_index(x, bsize) = sub_index; - if (bsize < BLOCK_8X8) { // When ab_index = 0 all sub-blocks are handled, so for ab_index != 0 // there is nothing to be done. @@ -890,64 +883,73 @@ static void encode_sb(VP9_COMP *cpi, const TileInfo *const tile, int output_enabled, BLOCK_SIZE bsize) { VP9_COMMON *const cm = &cpi->common; MACROBLOCK *const x = &cpi->mb; - BLOCK_SIZE c1 = BLOCK_8X8; - const int bsl = b_width_log2(bsize), bs = (1 << bsl) / 4; - int pl = 0; + const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4; + int ctx; PARTITION_TYPE partition; BLOCK_SIZE subsize; - int i; if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return; - c1 = BLOCK_4X4; if (bsize >= BLOCK_8X8) { - pl = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context, + ctx = partition_plane_context(cpi->above_seg_context, cpi->left_seg_context, mi_row, mi_col, bsize); - c1 = *(get_sb_partitioning(x, bsize)); + subsize = *get_sb_partitioning(x, bsize); + } else { + ctx = 0; + subsize = BLOCK_4X4; } - partition = partition_lookup[bsl][c1]; + + partition = partition_lookup[bsl][subsize]; switch (partition) { case PARTITION_NONE: if (output_enabled && bsize >= BLOCK_8X8) - cm->counts.partition[pl][PARTITION_NONE]++; - encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, c1, -1); + cm->counts.partition[ctx][PARTITION_NONE]++; + encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize); break; case PARTITION_VERT: if (output_enabled) - cm->counts.partition[pl][PARTITION_VERT]++; - encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, c1, 0); - encode_b(cpi, tile, tp, mi_row, mi_col + bs, output_enabled, c1, 1); + cm->counts.partition[ctx][PARTITION_VERT]++; + *get_sb_index(x, subsize) = 0; + encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize); + if (mi_col + hbs < cm->mi_cols) { + *get_sb_index(x, subsize) = 1; + encode_b(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize); + } break; case PARTITION_HORZ: if (output_enabled) - cm->counts.partition[pl][PARTITION_HORZ]++; - encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, c1, 0); - encode_b(cpi, tile, tp, mi_row + bs, mi_col, output_enabled, c1, 1); + cm->counts.partition[ctx][PARTITION_HORZ]++; + *get_sb_index(x, subsize) = 0; + encode_b(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize); + if (mi_row + hbs < cm->mi_rows) { + *get_sb_index(x, subsize) = 1; + encode_b(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize); + } break; case PARTITION_SPLIT: subsize = get_subsize(bsize, PARTITION_SPLIT); - if (output_enabled) - cm->counts.partition[pl][PARTITION_SPLIT]++; + cm->counts.partition[ctx][PARTITION_SPLIT]++; - for (i = 0; i < 4; i++) { - const int x_idx = i & 1, y_idx = i >> 1; - - *get_sb_index(x, subsize) = i; - encode_sb(cpi, tile, tp, mi_row + y_idx * bs, mi_col + x_idx * bs, - output_enabled, subsize); - } + *get_sb_index(x, subsize) = 0; + encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, subsize); + *get_sb_index(x, subsize) = 1; + encode_sb(cpi, tile, tp, mi_row, mi_col + hbs, output_enabled, subsize); + *get_sb_index(x, subsize) = 2; + encode_sb(cpi, tile, tp, mi_row + hbs, mi_col, output_enabled, subsize); + *get_sb_index(x, subsize) = 3; + encode_sb(cpi, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled, + subsize); break; default: - assert(0); - break; + assert("Invalid partition type."); } if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8) update_partition_context(cpi->above_seg_context, cpi->left_seg_context, - mi_row, mi_col, c1, bsize); + mi_row, mi_col, subsize, bsize); } // Check to see if the given partition size is allowed for a specified number @@ -1686,6 +1688,10 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, *get_sb_index(x, subsize) = i; if (cpi->sf.adaptive_motion_search) load_pred_mv(x, get_block_context(x, bsize)); + if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 && + partition_none_allowed) + get_block_context(x, subsize)->pred_filter_type = + get_block_context(x, bsize)->mic.mbmi.interp_filter; rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, subsize, &this_rate, &this_dist, i != 3, best_rd - sum_rd); @@ -1733,6 +1739,10 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, *get_sb_index(x, subsize) = 0; if (cpi->sf.adaptive_motion_search) load_pred_mv(x, get_block_context(x, bsize)); + if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 && + partition_none_allowed) + get_block_context(x, subsize)->pred_filter_type = + get_block_context(x, bsize)->mic.mbmi.interp_filter; pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize, get_block_context(x, subsize), best_rd); sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); @@ -1744,6 +1754,10 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, *get_sb_index(x, subsize) = 1; if (cpi->sf.adaptive_motion_search) load_pred_mv(x, get_block_context(x, bsize)); + if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 && + partition_none_allowed) + get_block_context(x, subsize)->pred_filter_type = + get_block_context(x, bsize)->mic.mbmi.interp_filter; pick_sb_modes(cpi, tile, mi_row + ms, mi_col, &this_rate, &this_dist, subsize, get_block_context(x, subsize), best_rd - sum_rd); @@ -1778,6 +1792,10 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, *get_sb_index(x, subsize) = 0; if (cpi->sf.adaptive_motion_search) load_pred_mv(x, get_block_context(x, bsize)); + if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 && + partition_none_allowed) + get_block_context(x, subsize)->pred_filter_type = + get_block_context(x, bsize)->mic.mbmi.interp_filter; pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize, get_block_context(x, subsize), best_rd); sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); @@ -1788,6 +1806,10 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, *get_sb_index(x, subsize) = 1; if (cpi->sf.adaptive_motion_search) load_pred_mv(x, get_block_context(x, bsize)); + if (cpi->sf.adaptive_pred_filter_type && bsize == BLOCK_8X8 && + partition_none_allowed) + get_block_context(x, subsize)->pred_filter_type = + get_block_context(x, bsize)->mic.mbmi.interp_filter; pick_sb_modes(cpi, tile, mi_row, mi_col + ms, &this_rate, &this_dist, subsize, get_block_context(x, subsize), best_rd - sum_rd); @@ -1889,6 +1911,18 @@ static void encode_sb_row(VP9_COMP *cpi, const TileInfo *const tile, int dummy_rate; int64_t dummy_dist; + BLOCK_SIZE i; + MACROBLOCK *x = &cpi->mb; + for (i = BLOCK_4X4; i < BLOCK_8X8; ++i) { + const int num_4x4_w = num_4x4_blocks_wide_lookup[i]; + const int num_4x4_h = num_4x4_blocks_high_lookup[i]; + const int num_4x4_blk = MAX(4, num_4x4_w * num_4x4_h); + for (x->sb_index = 0; x->sb_index < 4; ++x->sb_index) + for (x->mb_index = 0; x->mb_index < 4; ++x->mb_index) + for (x->b_index = 0; x->b_index < 16 / num_4x4_blk; ++x->b_index) + get_block_context(x, i)->pred_filter_type = SWITCHABLE; + } + vp9_zero(cpi->mb.pred_mv); if (cpi->sf.reference_masking) diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c index 0821c263a..e05ba1b76 100644 --- a/vp9/encoder/vp9_encodemb.c +++ b/vp9/encoder/vp9_encodemb.c @@ -369,7 +369,7 @@ void vp9_xform_quant(int plane, int block, BLOCK_SIZE plane_bsize, int16_t *coeff = BLOCK_OFFSET(p->coeff, block); int16_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block); int16_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block); - const scan_order *so; + const scan_order *scan_order; uint16_t *eob = &p->eobs[block]; const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize]; int i, j; @@ -379,36 +379,39 @@ void vp9_xform_quant(int plane, int block, BLOCK_SIZE plane_bsize, switch (tx_size) { case TX_32X32: - so = &vp9_default_scan_orders[TX_32X32]; + scan_order = &vp9_default_scan_orders[TX_32X32]; if (x->use_lp32x32fdct) vp9_fdct32x32_rd(src_diff, coeff, diff_stride); else vp9_fdct32x32(src_diff, coeff, diff_stride); vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, - so->iscan); + pd->dequant, p->zbin_extra, eob, scan_order->scan, + scan_order->iscan); break; case TX_16X16: - so = &vp9_default_scan_orders[TX_16X16]; + scan_order = &vp9_default_scan_orders[TX_16X16]; vp9_fdct16x16(src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, so->iscan); + pd->dequant, p->zbin_extra, eob, + scan_order->scan, scan_order->iscan); break; case TX_8X8: - so = &vp9_default_scan_orders[TX_8X8]; + scan_order = &vp9_default_scan_orders[TX_8X8]; vp9_fdct8x8(src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, so->iscan); + pd->dequant, p->zbin_extra, eob, + scan_order->scan, scan_order->iscan); break; case TX_4X4: - so = &vp9_default_scan_orders[TX_4X4]; + scan_order = &vp9_default_scan_orders[TX_4X4]; x->fwd_txm4x4(src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, so->iscan); + pd->dequant, p->zbin_extra, eob, + scan_order->scan, scan_order->iscan); break; default: assert(0); @@ -468,7 +471,7 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize, xd->itxm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]); break; default: - assert(!"Invalid transform size"); + assert(0 && "Invalid transform size"); } } @@ -533,7 +536,7 @@ void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, int16_t *coeff = BLOCK_OFFSET(p->coeff, block); int16_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block); int16_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block); - const scan_order *so; + const scan_order *scan_order; TX_TYPE tx_type; MB_PREDICTION_MODE mode; const int bwl = b_width_log2(plane_bsize); @@ -555,10 +558,9 @@ void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, switch (tx_size) { case TX_32X32: - so = &vp9_default_scan_orders[TX_32X32]; + scan_order = &vp9_default_scan_orders[TX_32X32]; mode = plane == 0 ? mbmi->mode : mbmi->uv_mode; - block >>= 6; - vp9_predict_intra_block(xd, block, bwl, TX_32X32, mode, + vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode, x->skip_encode ? src : dst, x->skip_encode ? p->src.stride : pd->dst.stride, dst, pd->dst.stride); @@ -571,18 +573,17 @@ void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, vp9_fdct32x32(src_diff, coeff, diff_stride); vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, - so->iscan); + pd->dequant, p->zbin_extra, eob, scan_order->scan, + scan_order->iscan); } if (!x->skip_encode && *eob) vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, *eob); break; case TX_16X16: tx_type = get_tx_type_16x16(pd->plane_type, xd); - so = &vp9_scan_orders[TX_16X16][tx_type]; + scan_order = &vp9_scan_orders[TX_16X16][tx_type]; mode = plane == 0 ? mbmi->mode : mbmi->uv_mode; - block >>= 4; - vp9_predict_intra_block(xd, block, bwl, TX_16X16, mode, + vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode, x->skip_encode ? src : dst, x->skip_encode ? p->src.stride : pd->dst.stride, dst, pd->dst.stride); @@ -592,17 +593,17 @@ void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, vp9_fht16x16(tx_type, src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, so->iscan); + pd->dequant, p->zbin_extra, eob, scan_order->scan, + scan_order->iscan); } if (!x->skip_encode && *eob) vp9_iht16x16_add(tx_type, dqcoeff, dst, pd->dst.stride, *eob); break; case TX_8X8: tx_type = get_tx_type_8x8(pd->plane_type, xd); - so = &vp9_scan_orders[TX_8X8][tx_type]; + scan_order = &vp9_scan_orders[TX_8X8][tx_type]; mode = plane == 0 ? mbmi->mode : mbmi->uv_mode; - block >>= 2; - vp9_predict_intra_block(xd, block, bwl, TX_8X8, mode, + vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode, x->skip_encode ? src : dst, x->skip_encode ? p->src.stride : pd->dst.stride, dst, pd->dst.stride); @@ -612,14 +613,15 @@ void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, vp9_fht8x8(tx_type, src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, so->iscan); + pd->dequant, p->zbin_extra, eob, scan_order->scan, + scan_order->iscan); } if (!x->skip_encode && *eob) vp9_iht8x8_add(tx_type, dqcoeff, dst, pd->dst.stride, *eob); break; case TX_4X4: tx_type = get_tx_type_4x4(pd->plane_type, xd, block); - so = &vp9_scan_orders[TX_4X4][tx_type]; + scan_order = &vp9_scan_orders[TX_4X4][tx_type]; if (mbmi->sb_type < BLOCK_8X8 && plane == 0) mode = xd->mi_8x8[0]->bmi[block].as_mode; else @@ -639,7 +641,8 @@ void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize, x->fwd_txm4x4(src_diff, coeff, diff_stride); vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant, p->quant_shift, qcoeff, dqcoeff, - pd->dequant, p->zbin_extra, eob, so->scan, so->iscan); + pd->dequant, p->zbin_extra, eob, scan_order->scan, + scan_order->iscan); } if (!x->skip_encode && *eob) { diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c index fad1ee032..dae89ad1d 100644 --- a/vp9/encoder/vp9_encodemv.c +++ b/vp9/encoder/vp9_encodemv.c @@ -47,13 +47,13 @@ static void encode_mv_component(vp9_writer* w, int comp, vp9_write(w, sign, mvcomp->sign); // Class - write_token(w, vp9_mv_class_tree, mvcomp->classes, - &mv_class_encodings[mv_class]); + vp9_write_token(w, vp9_mv_class_tree, mvcomp->classes, + &mv_class_encodings[mv_class]); // Integer bits if (mv_class == MV_CLASS_0) { - write_token(w, vp9_mv_class0_tree, mvcomp->class0, - &mv_class0_encodings[d]); + vp9_write_token(w, vp9_mv_class0_tree, mvcomp->class0, + &mv_class0_encodings[d]); } else { int i; const int n = mv_class + CLASS0_BITS - 1; // number of bits @@ -62,9 +62,9 @@ static void encode_mv_component(vp9_writer* w, int comp, } // Fractional bits - write_token(w, vp9_mv_fp_tree, - mv_class == MV_CLASS_0 ? mvcomp->class0_fp[d] : mvcomp->fp, - &mv_fp_encodings[fr]); + vp9_write_token(w, vp9_mv_fp_tree, + mv_class == MV_CLASS_0 ? mvcomp->class0_fp[d] : mvcomp->fp, + &mv_fp_encodings[fr]); // High precision bit if (usehp) @@ -209,7 +209,7 @@ void vp9_encode_mv(VP9_COMP* cpi, vp9_writer* w, const MV_JOINT_TYPE j = vp9_get_mv_joint(&diff); usehp = usehp && vp9_use_mv_hp(ref); - write_token(w, vp9_mv_joint_tree, mvctx->joints, &mv_joint_encodings[j]); + vp9_write_token(w, vp9_mv_joint_tree, mvctx->joints, &mv_joint_encodings[j]); if (mv_joint_vertical(j)) encode_mv_component(w, diff.row, &mvctx->comps[0], usehp); diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 5f42d0e76..cd6831af2 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -364,36 +364,32 @@ void vp9_end_first_pass(VP9_COMP *cpi) { output_stats(cpi, cpi->output_pkt_list, &cpi->twopass.total_stats); } -static void zz_motion_search(VP9_COMP *cpi, MACROBLOCK *x, - YV12_BUFFER_CONFIG *recon_buffer, - int *best_motion_err, int recon_yoffset) { +static unsigned int zz_motion_search(VP9_COMP *cpi, MACROBLOCK *x, + YV12_BUFFER_CONFIG *recon_buffer, + int recon_yoffset) { MACROBLOCKD *const xd = &x->e_mbd; + const uint8_t *const src = x->plane[0].src.buf; + const int src_stride = x->plane[0].src.stride; + const uint8_t *const ref = xd->plane[0].pre[0].buf + = recon_buffer->y_buffer + recon_yoffset; + const int ref_stride = xd->plane[0].pre[0].stride; - // Set up pointers for this macro block recon buffer - xd->plane[0].pre[0].buf = recon_buffer->y_buffer + recon_yoffset; - + unsigned int sse; switch (xd->mi_8x8[0]->mbmi.sb_type) { case BLOCK_8X8: - vp9_mse8x8(x->plane[0].src.buf, x->plane[0].src.stride, - xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride, - (unsigned int *)(best_motion_err)); + vp9_mse8x8(src, src_stride, ref, ref_stride, &sse); break; case BLOCK_16X8: - vp9_mse16x8(x->plane[0].src.buf, x->plane[0].src.stride, - xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride, - (unsigned int *)(best_motion_err)); + vp9_mse16x8(src, src_stride, ref, ref_stride, &sse); break; case BLOCK_8X16: - vp9_mse8x16(x->plane[0].src.buf, x->plane[0].src.stride, - xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride, - (unsigned int *)(best_motion_err)); + vp9_mse8x16(src, src_stride, ref, ref_stride, &sse); break; default: - vp9_mse16x16(x->plane[0].src.buf, x->plane[0].src.stride, - xd->plane[0].pre[0].buf, xd->plane[0].pre[0].stride, - (unsigned int *)(best_motion_err)); + vp9_mse16x16(src, src_stride, ref, ref_stride, &sse); break; } + return sse; } static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, @@ -410,8 +406,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, int step_param = 3; int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param; int n; - vp9_variance_fn_ptr_t v_fn_ptr = - cpi->fn_ptr[xd->mi_8x8[0]->mbmi.sb_type]; + vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[xd->mi_8x8[0]->mbmi.sb_type]; int new_mv_mode_penalty = 256; int sr = 0; @@ -448,10 +443,11 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, tmp_mv.as_int = 0; ref_mv_full.as_mv.col = ref_mv->as_mv.col >> 3; ref_mv_full.as_mv.row = ref_mv->as_mv.row >> 3; - tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv, step_param, + tmp_err = cpi->diamond_search_sad(x, &ref_mv_full.as_mv, &tmp_mv.as_mv, + step_param, x->sadperbit16, &num00, &v_fn_ptr, x->nmvjointcost, - x->mvcost, ref_mv); + x->mvcost, &ref_mv->as_mv); if (tmp_err < INT_MAX - new_mv_mode_penalty) tmp_err += new_mv_mode_penalty; @@ -471,11 +467,11 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, if (num00) { num00--; } else { - tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv, + tmp_err = cpi->diamond_search_sad(x, &ref_mv_full.as_mv, &tmp_mv.as_mv, step_param + n, x->sadperbit16, &num00, &v_fn_ptr, x->nmvjointcost, - x->mvcost, ref_mv); + x->mvcost, &ref_mv->as_mv); if (tmp_err < INT_MAX - new_mv_mode_penalty) tmp_err += new_mv_mode_penalty; @@ -583,10 +579,9 @@ void vp9_first_pass(VP9_COMP *cpi) { int this_error; int gf_motion_error = INT_MAX; int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row); - double error_weight; + double error_weight = 1.0; vp9_clear_system_state(); // __asm emms; - error_weight = 1.0; // avoid uninitialized warnings xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset; xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset; @@ -647,11 +642,9 @@ void vp9_first_pass(VP9_COMP *cpi) { // Other than for the first frame do a motion search if (cm->current_video_frame > 0) { int tmp_err; - int motion_error = INT_MAX; + int motion_error = zz_motion_search(cpi, x, lst_yv12, recon_yoffset); int_mv mv, tmp_mv; - // Simple 0,0 motion with no mv overhead - zz_motion_search(cpi, x, lst_yv12, &motion_error, recon_yoffset); mv.as_int = tmp_mv.as_int = 0; // Test last reference frame using the previous best mv as the @@ -684,8 +677,7 @@ void vp9_first_pass(VP9_COMP *cpi) { // Experimental search in an older reference frame if (cm->current_video_frame > 1) { // Simple 0,0 motion with no mv overhead - zz_motion_search(cpi, x, gld_yv12, - &gf_motion_error, recon_yoffset); + gf_motion_error = zz_motion_search(cpi, x, gld_yv12, recon_yoffset); first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv.as_mv, gld_yv12, @@ -724,11 +716,9 @@ void vp9_first_pass(VP9_COMP *cpi) { // very close and very low. This helps with scene cut // detection for example in cropped clips with black bars // at the sides or top and bottom. - if ((((this_error - intrapenalty) * 9) <= - (motion_error * 10)) && - (this_error < (2 * intrapenalty))) { + if (((this_error - intrapenalty) * 9 <= motion_error * 10) && + this_error < 2 * intrapenalty) neutral_count++; - } mv.as_mv.row *= 8; mv.as_mv.col *= 8; @@ -737,8 +727,7 @@ void vp9_first_pass(VP9_COMP *cpi) { xd->mi_8x8[0]->mbmi.tx_size = TX_4X4; xd->mi_8x8[0]->mbmi.ref_frame[0] = LAST_FRAME; xd->mi_8x8[0]->mbmi.ref_frame[1] = NONE; - vp9_build_inter_predictors_sby(xd, mb_row << 1, - mb_col << 1, + vp9_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, xd->mi_8x8[0]->mbmi.sb_type); vp9_encode_sby(x, xd->mi_8x8[0]->mbmi.sb_type); sum_mvr += mv.as_mv.row; diff --git a/vp9/encoder/vp9_mbgraph.c b/vp9/encoder/vp9_mbgraph.c index 544f1304d..e2ef256dd 100644 --- a/vp9/encoder/vp9_mbgraph.c +++ b/vp9/encoder/vp9_mbgraph.c @@ -42,7 +42,7 @@ static unsigned int do_16x16_motion_iteration(VP9_COMP *cpi, (cpi->speed < 8 ? (cpi->speed > 5 ? 1 : 0) : 2); step_param = MIN(step_param, (cpi->sf.max_step_search_steps - 2)); - vp9_clamp_mv_min_max(x, &ref_mv->as_mv); + vp9_set_mv_search_range(x, &ref_mv->as_mv); ref_full.as_mv.col = ref_mv->as_mv.col >> 3; ref_full.as_mv.row = ref_mv->as_mv.row >> 3; diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c index fee11fd2b..87b5988c2 100644 --- a/vp9/encoder/vp9_mcomp.c +++ b/vp9/encoder/vp9_mcomp.c @@ -24,7 +24,7 @@ // #define NEW_DIAMOND_SEARCH -void vp9_clamp_mv_min_max(MACROBLOCK *x, MV *mv) { +void vp9_set_mv_search_range(MACROBLOCK *x, MV *mv) { const int col_min = (mv->col >> 3) - MAX_FULL_PEL_VAL + (mv->col & 7 ? 1 : 0); const int row_min = (mv->row >> 3) - MAX_FULL_PEL_VAL + (mv->row & 7 ? 1 : 0); const int col_max = (mv->col >> 3) + MAX_FULL_PEL_VAL; @@ -1066,10 +1066,10 @@ int vp9_square_search(MACROBLOCK *x, #undef CHECK_POINT #undef CHECK_BETTER -int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, +int vp9_full_range_search_c(MACROBLOCK *x, MV *ref_mv, MV *best_mv, int search_param, int sad_per_bit, int *num00, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, - int *mvcost[2], int_mv *center_mv) { + int *mvcost[2], const MV *center_mv) { const MACROBLOCKD* const xd = &x->e_mbd; uint8_t *what = x->plane[0].src.buf; int what_stride = x->plane[0].src.stride; @@ -1077,14 +1077,14 @@ int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, int in_what_stride = xd->plane[0].pre[0].stride; uint8_t *best_address; - int_mv this_mv; + MV this_mv; int bestsad = INT_MAX; int ref_row, ref_col; uint8_t *check_here; int thissad; - int_mv fcenter_mv; + MV fcenter_mv; int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; @@ -1098,16 +1098,15 @@ int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, int start_row, end_row; int i; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.row = center_mv->row >> 3; + fcenter_mv.col = center_mv->col >> 3; - clamp_mv(&ref_mv->as_mv, - x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); - ref_row = ref_mv->as_mv.row; - ref_col = ref_mv->as_mv.col; + clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); + ref_row = ref_mv->row; + ref_col = ref_mv->col; *num00 = 11; - best_mv->as_mv.row = ref_row; - best_mv->as_mv.col = ref_col; + best_mv->row = ref_row; + best_mv->col = ref_col; // Work out the start point for the search in_what = (uint8_t *)(xd->plane[0].pre[0].buf + @@ -1116,7 +1115,7 @@ int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, // Check the starting position bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) - + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv, + + mvsad_err_cost(best_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); start_row = MAX(-range, x->mv_row_min - ref_row); @@ -1136,10 +1135,10 @@ int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, for (i = 0; i < 4; ++i) { if (sad_array[i] < bestsad) { - this_mv.as_mv.row = ref_row + tr; - this_mv.as_mv.col = ref_col + tc + i; + this_mv.row = ref_row + tr; + this_mv.col = ref_col + tc + i; thissad = sad_array[i] + - mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { bestsad = thissad; @@ -1155,9 +1154,9 @@ int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = ref_row + tr; - this_mv.as_mv.col = ref_col + tc + i; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = ref_row + tr; + this_mv.col = ref_col + tc + i; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1171,26 +1170,26 @@ int vp9_full_range_search_c(MACROBLOCK *x, int_mv *ref_mv, int_mv *best_mv, } } - best_mv->as_mv.row += best_tr; - best_mv->as_mv.col += best_tc; + best_mv->row += best_tr; + best_mv->col += best_tc; - this_mv.as_mv.row = best_mv->as_mv.row * 8; - this_mv.as_mv.col = best_mv->as_mv.col * 8; + this_mv.row = best_mv->row * 8; + this_mv.col = best_mv->col * 8; if (bestsad == INT_MAX) return INT_MAX; return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); } int vp9_diamond_search_sad_c(MACROBLOCK *x, - int_mv *ref_mv, int_mv *best_mv, + MV *ref_mv, MV *best_mv, int search_param, int sad_per_bit, int *num00, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, - int *mvcost[2], int_mv *center_mv) { + int *mvcost[2], const MV *center_mv) { int i, j, step; const MACROBLOCKD* const xd = &x->e_mbd; @@ -1201,7 +1200,7 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, uint8_t *best_address; int tot_steps; - int_mv this_mv; + MV this_mv; int bestsad = INT_MAX; int best_site = 0; @@ -1218,16 +1217,15 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.as_mv.row = center_mv->row >> 3; + fcenter_mv.as_mv.col = center_mv->col >> 3; - clamp_mv(&ref_mv->as_mv, - x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); - ref_row = ref_mv->as_mv.row; - ref_col = ref_mv->as_mv.col; + clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); + ref_row = ref_mv->row; + ref_col = ref_mv->col; *num00 = 0; - best_mv->as_mv.row = ref_row; - best_mv->as_mv.col = ref_col; + best_mv->row = ref_row; + best_mv->col = ref_col; // Work out the start point for the search in_what = (uint8_t *)(xd->plane[0].pre[0].buf + @@ -1236,7 +1234,7 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, // Check the starting position bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) - + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv, + + mvsad_err_cost(best_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); // search_param determines the length of the initial step and hence the number @@ -1251,8 +1249,8 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, for (step = 0; step < tot_steps; step++) { for (j = 0; j < x->searches_per_step; j++) { // Trap illegal vectors - this_row_offset = best_mv->as_mv.row + ss[i].mv.row; - this_col_offset = best_mv->as_mv.col + ss[i].mv.col; + this_row_offset = best_mv->row + ss[i].mv.row; + this_col_offset = best_mv->col + ss[i].mv.col; if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) && @@ -1263,9 +1261,9 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = this_row_offset; - this_mv.as_mv.col = this_col_offset; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = this_row_offset; + this_mv.col = this_col_offset; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1279,14 +1277,14 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, } if (best_site != last_site) { - best_mv->as_mv.row += ss[best_site].mv.row; - best_mv->as_mv.col += ss[best_site].mv.col; + best_mv->row += ss[best_site].mv.row; + best_mv->col += ss[best_site].mv.col; best_address += ss[best_site].offset; last_site = best_site; #if defined(NEW_DIAMOND_SEARCH) while (1) { - this_row_offset = best_mv->as_mv.row + ss[best_site].mv.row; - this_col_offset = best_mv->as_mv.col + ss[best_site].mv.col; + this_row_offset = best_mv->row + ss[best_site].mv.row; + this_col_offset = best_mv->col + ss[best_site].mv.col; if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) && (this_row_offset > x->mv_row_min) && @@ -1295,14 +1293,14 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = this_row_offset; - this_mv.as_mv.col = this_col_offset; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = this_row_offset; + this_mv.col = this_col_offset; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { bestsad = thissad; - best_mv->as_mv.row += ss[best_site].mv.row; - best_mv->as_mv.col += ss[best_site].mv.col; + best_mv->row += ss[best_site].mv.row; + best_mv->col += ss[best_site].mv.col; best_address += ss[best_site].offset; continue; } @@ -1316,23 +1314,24 @@ int vp9_diamond_search_sad_c(MACROBLOCK *x, } } - this_mv.as_mv.row = best_mv->as_mv.row * 8; - this_mv.as_mv.col = best_mv->as_mv.col * 8; + this_mv.row = best_mv->row * 8; + this_mv.col = best_mv->col * 8; if (bestsad == INT_MAX) return INT_MAX; return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); } int vp9_diamond_search_sadx4(MACROBLOCK *x, - int_mv *ref_mv, int_mv *best_mv, int search_param, + MV *ref_mv, MV *best_mv, int search_param, int sad_per_bit, int *num00, vp9_variance_fn_ptr_t *fn_ptr, - int *mvjcost, int *mvcost[2], int_mv *center_mv) { + int *mvjcost, int *mvcost[2], + const MV *center_mv) { int i, j, step; const MACROBLOCKD* const xd = &x->e_mbd; @@ -1343,7 +1342,7 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, uint8_t *best_address; int tot_steps; - int_mv this_mv; + MV this_mv; unsigned int bestsad = INT_MAX; int best_site = 0; @@ -1362,16 +1361,15 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.as_mv.row = center_mv->row >> 3; + fcenter_mv.as_mv.col = center_mv->col >> 3; - clamp_mv(&ref_mv->as_mv, - x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); - ref_row = ref_mv->as_mv.row; - ref_col = ref_mv->as_mv.col; + clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); + ref_row = ref_mv->row; + ref_col = ref_mv->col; *num00 = 0; - best_mv->as_mv.row = ref_row; - best_mv->as_mv.col = ref_col; + best_mv->row = ref_row; + best_mv->col = ref_col; // Work out the start point for the search in_what = (uint8_t *)(xd->plane[0].pre[0].buf + @@ -1380,7 +1378,7 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, // Check the starting position bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) - + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv, + + mvsad_err_cost(best_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); // search_param determines the length of the initial step and hence the number @@ -1398,10 +1396,10 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, // All_in is true if every one of the points we are checking are within // the bounds of the image. - all_in &= ((best_mv->as_mv.row + ss[i].mv.row) > x->mv_row_min); - all_in &= ((best_mv->as_mv.row + ss[i + 1].mv.row) < x->mv_row_max); - all_in &= ((best_mv->as_mv.col + ss[i + 2].mv.col) > x->mv_col_min); - all_in &= ((best_mv->as_mv.col + ss[i + 3].mv.col) < x->mv_col_max); + all_in &= ((best_mv->row + ss[i].mv.row) > x->mv_row_min); + all_in &= ((best_mv->row + ss[i + 1].mv.row) < x->mv_row_max); + all_in &= ((best_mv->col + ss[i + 2].mv.col) > x->mv_col_min); + all_in &= ((best_mv->col + ss[i + 3].mv.col) < x->mv_col_max); // If all the pixels are within the bounds we don't check whether the // search point is valid in this loop, otherwise we check each point @@ -1420,9 +1418,9 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, for (t = 0; t < 4; t++, i++) { if (sad_array[t] < bestsad) { - this_mv.as_mv.row = best_mv->as_mv.row + ss[i].mv.row; - this_mv.as_mv.col = best_mv->as_mv.col + ss[i].mv.col; - sad_array[t] += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = best_mv->row + ss[i].mv.row; + this_mv.col = best_mv->col + ss[i].mv.col; + sad_array[t] += mvsad_err_cost(&this_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); if (sad_array[t] < bestsad) { @@ -1435,8 +1433,8 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, } else { for (j = 0; j < x->searches_per_step; j++) { // Trap illegal vectors - this_row_offset = best_mv->as_mv.row + ss[i].mv.row; - this_col_offset = best_mv->as_mv.col + ss[i].mv.col; + this_row_offset = best_mv->row + ss[i].mv.row; + this_col_offset = best_mv->col + ss[i].mv.col; if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) && @@ -1447,9 +1445,9 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = this_row_offset; - this_mv.as_mv.col = this_col_offset; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = this_row_offset; + this_mv.col = this_col_offset; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1462,14 +1460,14 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, } } if (best_site != last_site) { - best_mv->as_mv.row += ss[best_site].mv.row; - best_mv->as_mv.col += ss[best_site].mv.col; + best_mv->row += ss[best_site].mv.row; + best_mv->col += ss[best_site].mv.col; best_address += ss[best_site].offset; last_site = best_site; #if defined(NEW_DIAMOND_SEARCH) while (1) { - this_row_offset = best_mv->as_mv.row + ss[best_site].mv.row; - this_col_offset = best_mv->as_mv.col + ss[best_site].mv.col; + this_row_offset = best_mv->row + ss[best_site].mv.row; + this_col_offset = best_mv->col + ss[best_site].mv.col; if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) && (this_row_offset > x->mv_row_min) && @@ -1478,14 +1476,14 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = this_row_offset; - this_mv.as_mv.col = this_col_offset; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = this_row_offset; + this_mv.col = this_col_offset; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv.as_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { bestsad = thissad; - best_mv->as_mv.row += ss[best_site].mv.row; - best_mv->as_mv.col += ss[best_site].mv.col; + best_mv->row += ss[best_site].mv.row; + best_mv->col += ss[best_site].mv.col; best_address += ss[best_site].offset; continue; } @@ -1499,15 +1497,15 @@ int vp9_diamond_search_sadx4(MACROBLOCK *x, } } - this_mv.as_mv.row = best_mv->as_mv.row * 8; - this_mv.as_mv.col = best_mv->as_mv.col * 8; + this_mv.row = best_mv->row * 8; + this_mv.col = best_mv->col * 8; if (bestsad == INT_MAX) return INT_MAX; return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); } @@ -1522,10 +1520,10 @@ int vp9_full_pixel_diamond(VP9_COMP *cpi, MACROBLOCK *x, int_mv *ref_mv, int_mv *dst_mv) { int_mv temp_mv; int thissme, n, num00; - int bestsme = cpi->diamond_search_sad(x, mvp_full, &temp_mv, + int bestsme = cpi->diamond_search_sad(x, &mvp_full->as_mv, &temp_mv.as_mv, step_param, sadpb, &num00, fn_ptr, x->nmvjointcost, - x->mvcost, ref_mv); + x->mvcost, &ref_mv->as_mv); dst_mv->as_int = temp_mv.as_int; n = num00; @@ -1542,10 +1540,10 @@ int vp9_full_pixel_diamond(VP9_COMP *cpi, MACROBLOCK *x, if (num00) { num00--; } else { - thissme = cpi->diamond_search_sad(x, mvp_full, &temp_mv, + thissme = cpi->diamond_search_sad(x, &mvp_full->as_mv, &temp_mv.as_mv, step_param + n, sadpb, &num00, fn_ptr, x->nmvjointcost, x->mvcost, - ref_mv); + &ref_mv->as_mv); /* check to see if refining search is needed. */ if (num00 > (further_steps - n)) @@ -1563,9 +1561,9 @@ int vp9_full_pixel_diamond(VP9_COMP *cpi, MACROBLOCK *x, int search_range = 8; int_mv best_mv; best_mv.as_int = dst_mv->as_int; - thissme = cpi->refining_search_sad(x, &best_mv, sadpb, search_range, + thissme = cpi->refining_search_sad(x, &best_mv.as_mv, sadpb, search_range, fn_ptr, x->nmvjointcost, x->mvcost, - ref_mv); + &ref_mv->as_mv); if (thissme < bestsme) { bestsme = thissme; @@ -1575,11 +1573,11 @@ int vp9_full_pixel_diamond(VP9_COMP *cpi, MACROBLOCK *x, return bestsme; } -int vp9_full_search_sad_c(MACROBLOCK *x, int_mv *ref_mv, +int vp9_full_search_sad_c(MACROBLOCK *x, MV *ref_mv, int sad_per_bit, int distance, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, int *mvcost[2], - int_mv *center_mv, int n) { + const MV *center_mv, int n) { const MACROBLOCKD* const xd = &x->e_mbd; uint8_t *what = x->plane[0].src.buf; int what_stride = x->plane[0].src.stride; @@ -1588,27 +1586,27 @@ int vp9_full_search_sad_c(MACROBLOCK *x, int_mv *ref_mv, int mv_stride = xd->plane[0].pre[0].stride; uint8_t *bestaddress; int_mv *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0]; - int_mv this_mv; + MV this_mv; int bestsad = INT_MAX; int r, c; uint8_t *check_here; int thissad; - int ref_row = ref_mv->as_mv.row; - int ref_col = ref_mv->as_mv.col; + int ref_row = ref_mv->row; + int ref_col = ref_mv->col; int row_min = ref_row - distance; int row_max = ref_row + distance; int col_min = ref_col - distance; int col_max = ref_col + distance; - int_mv fcenter_mv; + MV fcenter_mv; int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.row = center_mv->row >> 3; + fcenter_mv.col = center_mv->col >> 3; // Work out the mid point for the search in_what = xd->plane[0].pre[0].buf; @@ -1620,7 +1618,7 @@ int vp9_full_search_sad_c(MACROBLOCK *x, int_mv *ref_mv, // Baseline value at the centre bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) - + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv, + + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); // Apply further limits to prevent us looking using vectors that stretch @@ -1631,15 +1629,15 @@ int vp9_full_search_sad_c(MACROBLOCK *x, int_mv *ref_mv, row_max = MIN(row_max, x->mv_row_max); for (r = row_min; r < row_max; r++) { - this_mv.as_mv.row = r; + this_mv.row = r; check_here = r * mv_stride + in_what + col_min; for (c = col_min; c < col_max; c++) { thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride, bestsad); - this_mv.as_mv.col = c; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.col = c; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1653,22 +1651,22 @@ int vp9_full_search_sad_c(MACROBLOCK *x, int_mv *ref_mv, } } - this_mv.as_mv.row = best_mv->as_mv.row * 8; - this_mv.as_mv.col = best_mv->as_mv.col * 8; + this_mv.row = best_mv->as_mv.row * 8; + this_mv.col = best_mv->as_mv.col * 8; if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); else return INT_MAX; } -int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, +int vp9_full_search_sadx3(MACROBLOCK *x, MV *ref_mv, int sad_per_bit, int distance, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, - int *mvcost[2], int_mv *center_mv, int n) { + int *mvcost[2], const MV *center_mv, int n) { const MACROBLOCKD* const xd = &x->e_mbd; uint8_t *what = x->plane[0].src.buf; int what_stride = x->plane[0].src.stride; @@ -1677,15 +1675,15 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, int mv_stride = xd->plane[0].pre[0].stride; uint8_t *bestaddress; int_mv *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0]; - int_mv this_mv; + MV this_mv; unsigned int bestsad = INT_MAX; int r, c; uint8_t *check_here; unsigned int thissad; - int ref_row = ref_mv->as_mv.row; - int ref_col = ref_mv->as_mv.col; + int ref_row = ref_mv->row; + int ref_col = ref_mv->col; int row_min = ref_row - distance; int row_max = ref_row + distance; @@ -1693,13 +1691,13 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, int col_max = ref_col + distance; unsigned int sad_array[3]; - int_mv fcenter_mv; + MV fcenter_mv; int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.row = center_mv->row >> 3; + fcenter_mv.col = center_mv->col >> 3; // Work out the mid point for the search in_what = xd->plane[0].pre[0].buf; @@ -1711,7 +1709,7 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, // Baseline value at the centre bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) - + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv, + + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); // Apply further limits to prevent us looking using vectors that stretch @@ -1722,7 +1720,7 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, row_max = MIN(row_max, x->mv_row_max); for (r = row_min; r < row_max; r++) { - this_mv.as_mv.row = r; + this_mv.row = r; check_here = r * mv_stride + in_what + col_min; c = col_min; @@ -1735,8 +1733,8 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, thissad = sad_array[i]; if (thissad < bestsad) { - this_mv.as_mv.col = c; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.col = c; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1757,8 +1755,8 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, bestsad); if (thissad < bestsad) { - this_mv.as_mv.col = c; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.col = c; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1774,23 +1772,23 @@ int vp9_full_search_sadx3(MACROBLOCK *x, int_mv *ref_mv, } } - this_mv.as_mv.row = best_mv->as_mv.row * 8; - this_mv.as_mv.col = best_mv->as_mv.col * 8; + this_mv.row = best_mv->as_mv.row * 8; + this_mv.col = best_mv->as_mv.col * 8; if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); else return INT_MAX; } -int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, +int vp9_full_search_sadx8(MACROBLOCK *x, MV *ref_mv, int sad_per_bit, int distance, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, int *mvcost[2], - int_mv *center_mv, int n) { + const MV *center_mv, int n) { const MACROBLOCKD* const xd = &x->e_mbd; uint8_t *what = x->plane[0].src.buf; int what_stride = x->plane[0].src.stride; @@ -1799,15 +1797,15 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, int mv_stride = xd->plane[0].pre[0].stride; uint8_t *bestaddress; int_mv *best_mv = &x->e_mbd.mi_8x8[0]->bmi[n].as_mv[0]; - int_mv this_mv; + MV this_mv; unsigned int bestsad = INT_MAX; int r, c; uint8_t *check_here; unsigned int thissad; - int ref_row = ref_mv->as_mv.row; - int ref_col = ref_mv->as_mv.col; + int ref_row = ref_mv->row; + int ref_col = ref_mv->col; int row_min = ref_row - distance; int row_max = ref_row + distance; @@ -1816,13 +1814,13 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, DECLARE_ALIGNED_ARRAY(16, uint32_t, sad_array8, 8); unsigned int sad_array[3]; - int_mv fcenter_mv; + MV fcenter_mv; int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.row = center_mv->row >> 3; + fcenter_mv.col = center_mv->col >> 3; // Work out the mid point for the search in_what = xd->plane[0].pre[0].buf; @@ -1834,7 +1832,7 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, // Baseline value at the centre bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) - + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv.as_mv, + + mvsad_err_cost(&best_mv->as_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); // Apply further limits to prevent us looking using vectors that stretch @@ -1845,7 +1843,7 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, row_max = MIN(row_max, x->mv_row_max); for (r = row_min; r < row_max; r++) { - this_mv.as_mv.row = r; + this_mv.row = r; check_here = r * mv_stride + in_what + col_min; c = col_min; @@ -1858,8 +1856,8 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, thissad = (unsigned int)sad_array8[i]; if (thissad < bestsad) { - this_mv.as_mv.col = c; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.col = c; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1884,8 +1882,8 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, thissad = sad_array[i]; if (thissad < bestsad) { - this_mv.as_mv.col = c; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.col = c; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1906,8 +1904,8 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, bestsad); if (thissad < bestsad) { - this_mv.as_mv.col = c; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.col = c; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit); if (thissad < bestsad) { @@ -1923,21 +1921,22 @@ int vp9_full_search_sadx8(MACROBLOCK *x, int_mv *ref_mv, } } - this_mv.as_mv.row = best_mv->as_mv.row * 8; - this_mv.as_mv.col = best_mv->as_mv.col * 8; + this_mv.row = best_mv->as_mv.row * 8; + this_mv.col = best_mv->as_mv.col * 8; if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); else return INT_MAX; } int vp9_refining_search_sad_c(MACROBLOCK *x, - int_mv *ref_mv, int error_per_bit, + MV *ref_mv, int error_per_bit, int search_range, vp9_variance_fn_ptr_t *fn_ptr, - int *mvjcost, int *mvcost[2], int_mv *center_mv) { + int *mvjcost, int *mvcost[2], + const MV *center_mv) { const MACROBLOCKD* const xd = &x->e_mbd; MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}}; int i, j; @@ -1947,31 +1946,31 @@ int vp9_refining_search_sad_c(MACROBLOCK *x, int in_what_stride = xd->plane[0].pre[0].stride; uint8_t *what = x->plane[0].src.buf; uint8_t *best_address = xd->plane[0].pre[0].buf + - (ref_mv->as_mv.row * xd->plane[0].pre[0].stride) + - ref_mv->as_mv.col; + (ref_mv->row * xd->plane[0].pre[0].stride) + + ref_mv->col; uint8_t *check_here; unsigned int thissad; - int_mv this_mv; + MV this_mv; unsigned int bestsad = INT_MAX; - int_mv fcenter_mv; + MV fcenter_mv; int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.row = center_mv->row >> 3; + fcenter_mv.col = center_mv->col >> 3; bestsad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride, 0x7fffffff) + - mvsad_err_cost(&ref_mv->as_mv, &fcenter_mv.as_mv, + mvsad_err_cost(ref_mv, &fcenter_mv, mvjsadcost, mvsadcost, error_per_bit); for (i = 0; i < search_range; i++) { int best_site = -1; for (j = 0; j < 4; j++) { - this_row_offset = ref_mv->as_mv.row + neighbors[j].row; - this_col_offset = ref_mv->as_mv.col + neighbors[j].col; + this_row_offset = ref_mv->row + neighbors[j].row; + this_col_offset = ref_mv->col + neighbors[j].col; if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) && @@ -1983,9 +1982,9 @@ int vp9_refining_search_sad_c(MACROBLOCK *x, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = this_row_offset; - this_mv.as_mv.col = this_col_offset; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = this_row_offset; + this_mv.col = this_col_offset; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, error_per_bit); if (thissad < bestsad) { @@ -1999,29 +1998,30 @@ int vp9_refining_search_sad_c(MACROBLOCK *x, if (best_site == -1) { break; } else { - ref_mv->as_mv.row += neighbors[best_site].row; - ref_mv->as_mv.col += neighbors[best_site].col; + ref_mv->row += neighbors[best_site].row; + ref_mv->col += neighbors[best_site].col; best_address += (neighbors[best_site].row) * in_what_stride + neighbors[best_site].col; } } - this_mv.as_mv.row = ref_mv->as_mv.row * 8; - this_mv.as_mv.col = ref_mv->as_mv.col * 8; + this_mv.row = ref_mv->row * 8; + this_mv.col = ref_mv->col * 8; if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); else return INT_MAX; } int vp9_refining_search_sadx4(MACROBLOCK *x, - int_mv *ref_mv, int error_per_bit, + MV *ref_mv, int error_per_bit, int search_range, vp9_variance_fn_ptr_t *fn_ptr, - int *mvjcost, int *mvcost[2], int_mv *center_mv) { + int *mvjcost, int *mvcost[2], + const MV *center_mv) { const MACROBLOCKD* const xd = &x->e_mbd; MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}}; int i, j; @@ -2031,31 +2031,31 @@ int vp9_refining_search_sadx4(MACROBLOCK *x, int in_what_stride = xd->plane[0].pre[0].stride; uint8_t *what = x->plane[0].src.buf; uint8_t *best_address = xd->plane[0].pre[0].buf + - (ref_mv->as_mv.row * xd->plane[0].pre[0].stride) + - ref_mv->as_mv.col; + (ref_mv->row * xd->plane[0].pre[0].stride) + + ref_mv->col; uint8_t *check_here; unsigned int thissad; - int_mv this_mv; + MV this_mv; unsigned int bestsad = INT_MAX; - int_mv fcenter_mv; + MV fcenter_mv; int *mvjsadcost = x->nmvjointsadcost; int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]}; - fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; - fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; + fcenter_mv.row = center_mv->row >> 3; + fcenter_mv.col = center_mv->col >> 3; bestsad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride, 0x7fffffff) + - mvsad_err_cost(&ref_mv->as_mv, &fcenter_mv.as_mv, + mvsad_err_cost(ref_mv, &fcenter_mv, mvjsadcost, mvsadcost, error_per_bit); for (i = 0; i < search_range; i++) { int best_site = -1; - int all_in = ((ref_mv->as_mv.row - 1) > x->mv_row_min) & - ((ref_mv->as_mv.row + 1) < x->mv_row_max) & - ((ref_mv->as_mv.col - 1) > x->mv_col_min) & - ((ref_mv->as_mv.col + 1) < x->mv_col_max); + int all_in = ((ref_mv->row - 1) > x->mv_row_min) & + ((ref_mv->row + 1) < x->mv_row_max) & + ((ref_mv->col - 1) > x->mv_col_min) & + ((ref_mv->col + 1) < x->mv_col_max); if (all_in) { unsigned int sad_array[4]; @@ -2070,9 +2070,9 @@ int vp9_refining_search_sadx4(MACROBLOCK *x, for (j = 0; j < 4; j++) { if (sad_array[j] < bestsad) { - this_mv.as_mv.row = ref_mv->as_mv.row + neighbors[j].row; - this_mv.as_mv.col = ref_mv->as_mv.col + neighbors[j].col; - sad_array[j] += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = ref_mv->row + neighbors[j].row; + this_mv.col = ref_mv->col + neighbors[j].col; + sad_array[j] += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, error_per_bit); if (sad_array[j] < bestsad) { @@ -2083,8 +2083,8 @@ int vp9_refining_search_sadx4(MACROBLOCK *x, } } else { for (j = 0; j < 4; j++) { - this_row_offset = ref_mv->as_mv.row + neighbors[j].row; - this_col_offset = ref_mv->as_mv.col + neighbors[j].col; + this_row_offset = ref_mv->row + neighbors[j].row; + this_col_offset = ref_mv->col + neighbors[j].col; if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) && @@ -2096,9 +2096,9 @@ int vp9_refining_search_sadx4(MACROBLOCK *x, bestsad); if (thissad < bestsad) { - this_mv.as_mv.row = this_row_offset; - this_mv.as_mv.col = this_col_offset; - thissad += mvsad_err_cost(&this_mv.as_mv, &fcenter_mv.as_mv, + this_mv.row = this_row_offset; + this_mv.col = this_col_offset; + thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvjsadcost, mvsadcost, error_per_bit); if (thissad < bestsad) { @@ -2113,20 +2113,20 @@ int vp9_refining_search_sadx4(MACROBLOCK *x, if (best_site == -1) { break; } else { - ref_mv->as_mv.row += neighbors[best_site].row; - ref_mv->as_mv.col += neighbors[best_site].col; + ref_mv->row += neighbors[best_site].row; + ref_mv->col += neighbors[best_site].col; best_address += (neighbors[best_site].row) * in_what_stride + neighbors[best_site].col; } } - this_mv.as_mv.row = ref_mv->as_mv.row * 8; - this_mv.as_mv.col = ref_mv->as_mv.col * 8; + this_mv.row = ref_mv->row * 8; + this_mv.col = ref_mv->col * 8; if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) + - mv_err_cost(&this_mv.as_mv, ¢er_mv->as_mv, + mv_err_cost(&this_mv, center_mv, mvjcost, mvcost, x->errorperbit); else return INT_MAX; diff --git a/vp9/encoder/vp9_mcomp.h b/vp9/encoder/vp9_mcomp.h index 10c2e4fca..c574e61ab 100644 --- a/vp9/encoder/vp9_mcomp.h +++ b/vp9/encoder/vp9_mcomp.h @@ -28,7 +28,7 @@ #define BORDER_MV_PIXELS_B16 (16 + VP9_INTERP_EXTEND) -void vp9_clamp_mv_min_max(MACROBLOCK *x, MV *mv); +void vp9_set_mv_search_range(MACROBLOCK *x, MV *mv); int vp9_mv_bit_cost(const MV *mv, const MV *ref, const int *mvjcost, int *mvcost[2], int weight); void vp9_init_dsmotion_compensation(MACROBLOCK *x, int stride); @@ -103,25 +103,25 @@ extern fractional_mv_step_comp_fp vp9_find_best_sub_pixel_comp_iterative; extern fractional_mv_step_comp_fp vp9_find_best_sub_pixel_comp_tree; typedef int (*vp9_full_search_fn_t)(MACROBLOCK *x, - int_mv *ref_mv, int sad_per_bit, + MV *ref_mv, int sad_per_bit, int distance, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, int *mvcost[2], - int_mv *center_mv, int n); + const MV *center_mv, int n); typedef int (*vp9_refining_search_fn_t)(MACROBLOCK *x, - int_mv *ref_mv, int sad_per_bit, + MV *ref_mv, int sad_per_bit, int distance, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, int *mvcost[2], - int_mv *center_mv); + const MV *center_mv); typedef int (*vp9_diamond_search_fn_t)(MACROBLOCK *x, - int_mv *ref_mv, int_mv *best_mv, + MV *ref_mv, MV *best_mv, int search_param, int sad_per_bit, int *num00, vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost, int *mvcost[2], - int_mv *center_mv); + const MV *center_mv); int vp9_refining_search_8p_c(MACROBLOCK *x, int_mv *ref_mv, int error_per_bit, diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index fac074adb..9747eb5a2 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -654,6 +654,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->tx_size_search_method = USE_FULL_RD; sf->use_lp32x32fdct = 0; sf->adaptive_motion_search = 0; + sf->adaptive_pred_filter_type = 0; sf->use_avoid_tested_higherror = 0; sf->reference_masking = 0; sf->use_one_partition_size_always = 0; @@ -717,6 +718,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->use_rd_breakout = 1; sf->adaptive_motion_search = 1; + sf->adaptive_pred_filter_type = 1; sf->auto_mv_step_size = 1; sf->adaptive_rd_thresh = 2; sf->recode_loop = 2; @@ -744,9 +746,10 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->use_rd_breakout = 1; sf->adaptive_motion_search = 1; + sf->adaptive_pred_filter_type = 2; sf->auto_mv_step_size = 1; - sf->disable_filter_search_var_thresh = 16; + sf->disable_filter_search_var_thresh = 50; sf->comp_inter_joint_search_thresh = BLOCK_SIZES; sf->auto_min_max_partition_size = 1; @@ -779,9 +782,10 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->use_rd_breakout = 1; sf->adaptive_motion_search = 1; + sf->adaptive_pred_filter_type = 2; sf->auto_mv_step_size = 1; - sf->disable_filter_search_var_thresh = 16; + sf->disable_filter_search_var_thresh = 100; sf->comp_inter_joint_search_thresh = BLOCK_SIZES; sf->auto_min_max_partition_size = 1; @@ -812,9 +816,10 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->use_rd_breakout = 1; sf->adaptive_motion_search = 1; + sf->adaptive_pred_filter_type = 2; sf->auto_mv_step_size = 1; - sf->disable_filter_search_var_thresh = 16; + sf->disable_filter_search_var_thresh = 200; sf->comp_inter_joint_search_thresh = BLOCK_SIZES; sf->auto_min_max_partition_size = 1; @@ -860,7 +865,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->search_method = HEX; sf->subpel_iters_per_step = 1; sf->disable_split_var_thresh = 64; - sf->disable_filter_search_var_thresh = 96; + sf->disable_filter_search_var_thresh = 500; for (i = 0; i < TX_SIZES; i++) { sf->intra_y_mode_mask[i] = INTRA_DC_ONLY; sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY; @@ -921,7 +926,7 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) { if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer, cpi->oxcf.width, cpi->oxcf.height, cm->subsampling_x, cm->subsampling_y, - VP9BORDERINPIXELS)) + VP9BORDERINPIXELS, NULL, NULL, NULL)) vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to allocate altref buffer"); } @@ -989,14 +994,14 @@ static void update_frame_size(VP9_COMP *cpi) { if (vp9_realloc_frame_buffer(&cpi->last_frame_uf, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9BORDERINPIXELS)) + VP9BORDERINPIXELS, NULL, NULL, NULL)) vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to reallocate last frame buffer"); if (vp9_realloc_frame_buffer(&cpi->scaled_source, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9BORDERINPIXELS)) + VP9BORDERINPIXELS, NULL, NULL, NULL)) vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to reallocate scaled source buffer"); @@ -2564,7 +2569,7 @@ static void scale_references(VP9_COMP *cpi) { vp9_realloc_frame_buffer(&cm->yv12_fb[new_fb], cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9BORDERINPIXELS); + VP9BORDERINPIXELS, NULL, NULL, NULL); scale_and_extend_frame(ref, &cm->yv12_fb[new_fb]); cpi->scaled_ref_idx[i] = new_fb; } else { @@ -2662,7 +2667,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { #endif static void encode_with_recode_loop(VP9_COMP *cpi, - unsigned long *size, + size_t *size, uint8_t *dest, int *q, int bottom_index, @@ -2859,7 +2864,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, } static void encode_frame_to_data_rate(VP9_COMP *cpi, - unsigned long *size, + size_t *size, uint8_t *dest, unsigned int *frame_flags) { VP9_COMMON *const cm = &cpi->common; @@ -3238,12 +3243,12 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1; } -static void Pass0Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, +static void Pass0Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest, unsigned int *frame_flags) { encode_frame_to_data_rate(cpi, size, dest, frame_flags); } -static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, +static void Pass1Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest, unsigned int *frame_flags) { (void) size; (void) dest; @@ -3253,8 +3258,8 @@ static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, vp9_first_pass(cpi); } -static void Pass2Encode(VP9_COMP *cpi, unsigned long *size, - unsigned char *dest, unsigned int *frame_flags) { +static void Pass2Encode(VP9_COMP *cpi, size_t *size, + uint8_t *dest, unsigned int *frame_flags) { cpi->enable_encode_breakout = 1; if (!cpi->refresh_alt_ref_frame) @@ -3319,7 +3324,7 @@ int is_next_frame_arf(VP9_COMP *cpi) { #endif int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, - unsigned long *size, unsigned char *dest, + size_t *size, uint8_t *dest, int64_t *time_stamp, int64_t *time_end, int flush) { VP9_COMP *cpi = (VP9_COMP *) ptr; VP9_COMMON *cm = &cpi->common; @@ -3554,7 +3559,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9BORDERINPIXELS); + VP9BORDERINPIXELS, NULL, NULL, NULL); // Calculate scaling factors for each of the 3 available references for (i = 0; i < REFS_PER_FRAME; ++i) { diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index dcd853fbf..5f37a0789 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -270,6 +270,7 @@ typedef struct { int using_small_partition_info; // TODO(jingning): combine the related motion search speed features int adaptive_motion_search; + int adaptive_pred_filter_type; // Implements various heuristics to skip searching modes // The heuristics selected are based on flags @@ -681,8 +682,7 @@ static int get_scale_ref_frame_idx(VP9_COMP *cpi, void vp9_encode_frame(VP9_COMP *cpi); -void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, - unsigned long *size); +void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size); void vp9_activity_masking(VP9_COMP *cpi, MACROBLOCK *x); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 3e1832783..5702e5aec 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -686,7 +686,7 @@ void vp9_get_entropy_contexts(TX_SIZE tx_size, t_left[i] = !!*(const uint64_t *)&left[i]; break; default: - assert(!"Invalid transform size."); + assert(0 && "Invalid transform size."); } } @@ -1669,15 +1669,15 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0; vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile, + i, 0, mi_row, mi_col, &frame_mv[NEARESTMV][mbmi->ref_frame[0]], - &frame_mv[NEARMV][mbmi->ref_frame[0]], - i, 0, mi_row, mi_col); + &frame_mv[NEARMV][mbmi->ref_frame[0]]); if (has_second_rf) { frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0; vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile, + i, 1, mi_row, mi_col, &frame_mv[NEARESTMV][mbmi->ref_frame[1]], - &frame_mv[NEARMV][mbmi->ref_frame[1]], - i, 1, mi_row, mi_col); + &frame_mv[NEARMV][mbmi->ref_frame[1]]); } // search for the best motion vector on this segment for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) { @@ -1781,7 +1781,7 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, // adjust src pointer for this block mi_buf_shift(x, i); - vp9_clamp_mv_min_max(x, &bsi->ref_mv->as_mv); + vp9_set_mv_search_range(x, &bsi->ref_mv->as_mv); if (cpi->sf.search_method == HEX) { bestsme = vp9_hex_search(x, &mvp_full.as_mv, @@ -1813,10 +1813,10 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, clamp_mv(&mvp_full.as_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max); - thissme = cpi->full_search_sad(x, &mvp_full, + thissme = cpi->full_search_sad(x, &mvp_full.as_mv, sadpb, 16, v_fn_ptr, x->nmvjointcost, x->mvcost, - bsi->ref_mv, i); + &bsi->ref_mv->as_mv, i); if (thissme < bestsme) { bestsme = thissme; @@ -2344,7 +2344,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, setup_pre_planes(xd, 0, scaled_ref_frame, mi_row, mi_col, NULL); } - vp9_clamp_mv_min_max(x, &ref_mv.as_mv); + vp9_set_mv_search_range(x, &ref_mv.as_mv); // Adjust search parameters based on small partitions' result. if (x->fast_ms) { @@ -2523,7 +2523,7 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x, // Compound motion search on first ref frame. if (id) xd->plane[0].pre[0] = ref_yv12[id]; - vp9_clamp_mv_min_max(x, &ref_mv[id].as_mv); + vp9_set_mv_search_range(x, &ref_mv[id].as_mv); // Use mv result from single mode as mvp. tmp_mv.as_int = frame_mv[refs[id]].as_int; @@ -3237,7 +3237,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, break; case NONE: case MAX_REF_FRAMES: - assert(!"Invalid Reference frame"); + assert(0 && "Invalid Reference frame"); } } if (cpi->mode_skip_mask & ((int64_t)1 << mode_index)) @@ -3811,8 +3811,6 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, int skip_uv[TX_SIZES]; MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 }; struct scale_factors scale_factor[4]; - unsigned int ref_frame_mask = 0; - unsigned int mode_mask = 0; int intra_cost_penalty = 20 * vp9_dc_quant(cpi->common.base_qindex, cpi->common.y_dc_delta_q); int_mv seg_mvs[4][MAX_REF_FRAMES]; @@ -3842,15 +3840,6 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, *returnrate = INT_MAX; - // Create a mask set to 1 for each reference frame used by a smaller - // resolution. - if (cpi->sf.use_avoid_tested_higherror) { - ref_frame_mask = 0; - mode_mask = 0; - ref_frame_mask = ~ref_frame_mask; - mode_mask = ~mode_mask; - } - for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) { if (cpi->ref_frame_flags & flag_list[ref_frame]) { setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame, @@ -3902,7 +3891,7 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, break; case NONE: case MAX_REF_FRAMES: - assert(!"Invalid Reference frame"); + assert(0 && "Invalid Reference frame"); } } if (cpi->mode_skip_mask & ((int64_t)1 << mode_index)) @@ -4075,6 +4064,14 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, cpi->sf.disable_filter_search_var_thresh) { tmp_best_filter = EIGHTTAP; vp9_zero(cpi->rd_filter_cache); + } else if (cpi->sf.adaptive_pred_filter_type == 1 && + ctx->pred_filter_type < SWITCHABLE) { + tmp_best_filter = ctx->pred_filter_type; + vp9_zero(cpi->rd_filter_cache); + } else if (cpi->sf.adaptive_pred_filter_type == 2) { + tmp_best_filter = ctx->pred_filter_type < SWITCHABLE ? + ctx->pred_filter_type : 0; + vp9_zero(cpi->rd_filter_cache); } else { for (switchable_filter_index = 0; switchable_filter_index < SWITCHABLE_FILTERS; @@ -4141,7 +4138,7 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, } } - if (tmp_best_rdu == INT64_MAX) + if (tmp_best_rdu == INT64_MAX && pred_exists) continue; mbmi->interp_filter = (cm->mcomp_filter_type == SWITCHABLE ? diff --git a/vp9/encoder/vp9_treewriter.h b/vp9/encoder/vp9_treewriter.h index a2f9df139..703272c64 100644 --- a/vp9/encoder/vp9_treewriter.h +++ b/vp9/encoder/vp9_treewriter.h @@ -8,19 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ - #ifndef VP9_ENCODER_VP9_TREEWRITER_H_ #define VP9_ENCODER_VP9_TREEWRITER_H_ -/* Trees map alphabets into huffman-like codes suitable for an arithmetic - bit coder. Timothy S Murphy 11 October 2004 */ - #include "vp9/common/vp9_treecoder.h" - #include "vp9/encoder/vp9_boolhuff.h" /* for now */ -#define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8) - #define vp9_cost_zero(prob) (vp9_prob_cost[prob]) #define vp9_cost_one(prob) vp9_cost_zero(vp9_complement(prob)) @@ -33,31 +26,6 @@ static INLINE unsigned int cost_branch256(const unsigned int ct[2], return ct[0] * vp9_cost_zero(p) + ct[1] * vp9_cost_one(p); } -static INLINE void treed_write(vp9_writer *w, - vp9_tree tree, const vp9_prob *probs, - int bits, int len, - vp9_tree_index i) { - do { - const int bit = (bits >> --len) & 1; - vp9_write(w, bit, probs[i >> 1]); - i = tree[i + bit]; - } while (len); -} - -struct vp9_token { - int value; - int len; -}; - - -void vp9_tokens_from_tree(struct vp9_token*, const vp9_tree_index *); - -static INLINE void write_token(vp9_writer *w, vp9_tree tree, - const vp9_prob *probs, - const struct vp9_token *token) { - treed_write(w, tree, probs, token->value, token->len, 0); -} - static INLINE int treed_cost(vp9_tree tree, const vp9_prob *probs, int bits, int len) { int cost = 0; @@ -79,4 +47,27 @@ void vp9_tree_probs_from_distribution(vp9_tree tree, unsigned int branch_ct[ /* n - 1 */ ][2], const unsigned int num_events[ /* n */ ]); +struct vp9_token { + int value; + int len; +}; + +void vp9_tokens_from_tree(struct vp9_token*, const vp9_tree_index *); + +static INLINE void vp9_write_tree(vp9_writer *w, const vp9_tree_index *tree, + const vp9_prob *probs, int bits, int len, + vp9_tree_index i) { + do { + const int bit = (bits >> --len) & 1; + vp9_write(w, bit, probs[i >> 1]); + i = tree[i + bit]; + } while (len); +} + +static INLINE void vp9_write_token(vp9_writer *w, const vp9_tree_index *tree, + const vp9_prob *probs, + const struct vp9_token *token) { + vp9_write_tree(w, tree, probs, token->value, token->len, 0); +} + #endif // VP9_ENCODER_VP9_TREEWRITER_H_ diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 5d53a4149..6bfca8d80 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -77,14 +77,14 @@ struct vpx_codec_alg_priv { vpx_codec_enc_cfg_t cfg; struct vp9_extracfg vp8_cfg; VP9_CONFIG oxcf; - VP9_PTR cpi; + VP9_PTR cpi; unsigned char *cx_data; - unsigned int cx_data_sz; + size_t cx_data_sz; unsigned char *pending_cx_data; - unsigned int pending_cx_data_sz; + size_t pending_cx_data_sz; int pending_frame_count; - uint32_t pending_frame_sizes[8]; - uint32_t pending_frame_magnitude; + size_t pending_frame_sizes[8]; + size_t pending_frame_magnitude; vpx_image_t preview_img; vp8_postproc_cfg_t preview_ppcfg; vpx_codec_pkt_list_decl(64) pkt_list; @@ -100,7 +100,7 @@ static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) { case VP8_ALTR_FRAME: return VP9_ALT_FLAG; } - assert(!"Invalid Reference Frame"); + assert(0 && "Invalid Reference Frame"); return VP9_LAST_FLAG; } @@ -708,7 +708,7 @@ static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t *ctx, unsigned int lib_flags; YV12_BUFFER_CONFIG sd; int64_t dst_time_stamp, dst_end_time_stamp; - unsigned long size, cx_data_sz; + size_t size, cx_data_sz; unsigned char *cx_data; /* Set up internal flags */ diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index fde73e4ab..c123c4653 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -59,6 +59,13 @@ struct vpx_codec_alg_priv { int img_setup; int img_avail; int invert_tile_order; + int fb_lru; + + /* External buffer info to save for VP9 common. */ + vpx_codec_frame_buffer_t *fb_list; // External frame buffers + int fb_count; // Total number of frame buffers + vpx_realloc_frame_buffer_cb_fn_t realloc_fb_cb; + void *user_priv; // Private data associated with the external frame buffers. }; static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si, @@ -307,10 +314,32 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, ctx->postproc_cfg.noise_level = 0; } - if (!optr) + if (!optr) { res = VPX_CODEC_ERROR; - else + } else { + VP9D_COMP *const pbi = (VP9D_COMP*)optr; + VP9_COMMON *const cm = &pbi->common; + if (ctx->fb_list != NULL && ctx->realloc_fb_cb != NULL && + ctx->fb_count > 0) { + cm->fb_list = ctx->fb_list; + cm->fb_count = ctx->fb_count; + cm->realloc_fb_cb = ctx->realloc_fb_cb; + cm->user_priv = ctx->user_priv; + } else { + cm->fb_count = FRAME_BUFFERS; + } + cm->fb_lru = ctx->fb_lru; + CHECK_MEM_ERROR(cm, cm->yv12_fb, + vpx_calloc(cm->fb_count, sizeof(*cm->yv12_fb))); + CHECK_MEM_ERROR(cm, cm->fb_idx_ref_cnt, + vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_cnt))); + if (cm->fb_lru) { + CHECK_MEM_ERROR(cm, cm->fb_idx_ref_lru, + vpx_calloc(cm->fb_count, + sizeof(*cm->fb_idx_ref_lru))); + } ctx->pbi = optr; + } } ctx->decoder_init = 1; @@ -347,7 +376,7 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, } if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) { - VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; + VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi; res = update_error_state(ctx, &pbi->common.error); } @@ -475,6 +504,27 @@ static vpx_image_t *vp9_get_frame(vpx_codec_alg_priv_t *ctx, return img; } +static vpx_codec_err_t vp9_set_frame_buffers( + vpx_codec_alg_priv_t *ctx, + vpx_codec_frame_buffer_t *fb_list, int fb_count, + vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) { + if (fb_count < REF_FRAMES) { + /* The application must pass in at least REF_FRAMES frame buffers. */ + return VPX_CODEC_INVALID_PARAM; + } else if (!ctx->pbi) { + /* If the decoder has already been initialized, do not accept external + * frame buffers. + */ + ctx->fb_list = fb_list; + ctx->fb_count = fb_count; + ctx->realloc_fb_cb = cb; + ctx->user_priv = user_priv; + return VPX_CODEC_OK; + } + + return VPX_CODEC_ERROR; +} + static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t *ctx, vpx_codec_mmap_t *mmap, vpx_codec_iter_t *iter) { @@ -639,7 +689,7 @@ static vpx_codec_err_t get_last_ref_updates(vpx_codec_alg_priv_t *ctx, int ctrl_id, va_list args) { int *update_info = va_arg(args, int *); - VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; + VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi; if (update_info) { *update_info = pbi->refresh_frame_flags; @@ -657,7 +707,7 @@ static vpx_codec_err_t get_frame_corrupted(vpx_codec_alg_priv_t *ctx, int *corrupted = va_arg(args, int *); if (corrupted) { - VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; + VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi; if (pbi) *corrupted = pbi->common.frame_to_show->corrupted; else @@ -674,7 +724,7 @@ static vpx_codec_err_t get_display_size(vpx_codec_alg_priv_t *ctx, int *const display_size = va_arg(args, int *); if (display_size) { - const VP9D_COMP *const pbi = (VP9D_COMP *)ctx->pbi; + const VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi; if (pbi) { display_size[0] = pbi->common.display_width; display_size[1] = pbi->common.display_height; @@ -694,6 +744,21 @@ static vpx_codec_err_t set_invert_tile_order(vpx_codec_alg_priv_t *ctx, return VPX_CODEC_OK; } +static vpx_codec_err_t set_frame_buffer_lru_cache(vpx_codec_alg_priv_t *ctx, + int ctr_id, + va_list args) { + VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi; + + // Save for later to pass into vp9 common. + ctx->fb_lru = va_arg(args, int); + + if (pbi) { + VP9_COMMON *const cm = &pbi->common; + cm->fb_lru = ctx->fb_lru; + } + return VPX_CODEC_OK; +} + static vpx_codec_ctrl_fn_map_t ctf_maps[] = { {VP8_SET_REFERENCE, set_reference}, {VP8_COPY_REFERENCE, copy_reference}, @@ -707,6 +772,7 @@ static vpx_codec_ctrl_fn_map_t ctf_maps[] = { {VP9_GET_REFERENCE, get_reference}, {VP9D_GET_DISPLAY_SIZE, get_display_size}, {VP9_INVERT_TILE_DECODE_ORDER, set_invert_tile_order}, + {VP9D_SET_FRAME_BUFFER_LRU_CACHE, set_frame_buffer_lru_cache}, { -1, NULL}, }; @@ -717,7 +783,8 @@ static vpx_codec_ctrl_fn_map_t ctf_maps[] = { CODEC_INTERFACE(vpx_codec_vp9_dx) = { "WebM Project VP9 Decoder" VERSION_STRING, VPX_CODEC_INTERNAL_ABI_VERSION, - VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC, + VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC | + VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER, /* vpx_codec_caps_t caps; */ vp9_init, /* vpx_codec_init_fn_t init; */ vp9_destroy, /* vpx_codec_destroy_fn_t destroy; */ @@ -729,6 +796,7 @@ CODEC_INTERFACE(vpx_codec_vp9_dx) = { vp9_get_si, /* vpx_codec_get_si_fn_t get_si; */ vp9_decode, /* vpx_codec_decode_fn_t decode; */ vp9_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */ + vp9_set_frame_buffers, /* vpx_codec_set_frame_buffers_fn_t set_fb; */ }, { // NOLINT /* encoder functions */ diff --git a/vpx/exports_dec b/vpx/exports_dec index ed121f7ec..d058c9bdb 100644 --- a/vpx/exports_dec +++ b/vpx/exports_dec @@ -7,3 +7,4 @@ text vpx_codec_peek_stream_info text vpx_codec_register_put_frame_cb text vpx_codec_register_put_slice_cb text vpx_codec_set_mem_map +text vpx_codec_set_frame_buffers diff --git a/vpx/internal/vpx_codec_internal.h b/vpx/internal/vpx_codec_internal.h index 05fed977e..75b4a1877 100644 --- a/vpx/internal/vpx_codec_internal.h +++ b/vpx/internal/vpx_codec_internal.h @@ -56,7 +56,7 @@ * types, removing or reassigning enums, adding/removing/rearranging * fields to structures */ -#define VPX_CODEC_INTERNAL_ABI_VERSION (4) /**<\hideinitializer*/ +#define VPX_CODEC_INTERNAL_ABI_VERSION (5) /**<\hideinitializer*/ typedef struct vpx_codec_alg_priv vpx_codec_alg_priv_t; typedef struct vpx_codec_priv_enc_mr_cfg vpx_codec_priv_enc_mr_cfg_t; @@ -215,6 +215,36 @@ typedef vpx_codec_err_t (*vpx_codec_decode_fn_t)(vpx_codec_alg_priv_t *ctx, typedef vpx_image_t *(*vpx_codec_get_frame_fn_t)(vpx_codec_alg_priv_t *ctx, vpx_codec_iter_t *iter); +/*!\brief Pass in external frame buffers for the decoder to use. + * + * Registers a given function to be called when the current frame to + * decode will be bigger than the external frame buffer size. This + * function must be called before the first call to decode or libvpx + * will assume the default behavior of allocating frame buffers internally. + * Frame buffers with a size of 0 are valid. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] fb_list Pointer to array of frame buffers + * \param[in] fb_count Number of elements in frame buffer array + * \param[in] cb Pointer to the callback function + * \param[in] user_priv User's private data + * + * \retval #VPX_CODEC_OK + * External frame buffers will be used by libvpx. + * \retval #VPX_CODEC_INVALID_PARAM + * fb_count was less than the value needed by the codec. + * \retval #VPX_CODEC_ERROR + * Decoder context not initialized, or algorithm not capable of + * using external frame buffers. + * + * \note + * When decoding VP9, the application must pass in at least 8 external + * frame buffers, as VP9 can have up to 8 reference frames. + */ +typedef vpx_codec_err_t (*vpx_codec_set_frame_buffers_fn_t)( + vpx_codec_alg_priv_t *ctx, + vpx_codec_frame_buffer_t *fb_list, int fb_count, + vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv); /*\brief eXternal Memory Allocation memory map get iterator * @@ -305,6 +335,7 @@ struct vpx_codec_iface { vpx_codec_get_si_fn_t get_si; /**< \copydoc ::vpx_codec_get_si_fn_t */ vpx_codec_decode_fn_t decode; /**< \copydoc ::vpx_codec_decode_fn_t */ vpx_codec_get_frame_fn_t get_frame; /**< \copydoc ::vpx_codec_get_frame_fn_t */ + vpx_codec_set_frame_buffers_fn_t set_fb; /**< \copydoc ::vpx_codec_set_frame_buffers_fn_t */ } dec; struct vpx_codec_enc_iface { vpx_codec_enc_cfg_map_t *cfg_maps; /**< \copydoc ::vpx_codec_enc_cfg_map_t */ diff --git a/vpx/src/vpx_decoder.c b/vpx/src/vpx_decoder.c index a99e48f88..39fd217ea 100644 --- a/vpx/src/vpx_decoder.c +++ b/vpx/src/vpx_decoder.c @@ -226,3 +226,22 @@ vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx, return SAVE_STATUS(ctx, res); } + +vpx_codec_err_t vpx_codec_set_frame_buffers( + vpx_codec_ctx_t *ctx, + vpx_codec_frame_buffer_t *fb_list, int fb_count, + vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) { + vpx_codec_err_t res; + + if (!ctx || !fb_list || fb_count <= 0 || !cb) { + res = VPX_CODEC_INVALID_PARAM; + } else if (!ctx->iface || !ctx->priv || + !(ctx->iface->caps & VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER)) { + res = VPX_CODEC_ERROR; + } else { + res = ctx->iface->dec.set_fb(ctx->priv->alg_priv, fb_list, fb_count, + cb, user_priv); + } + + return SAVE_STATUS(ctx, res); +} diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h index b457b9302..218f0b87a 100644 --- a/vpx/vp8dx.h +++ b/vpx/vp8dx.h @@ -79,6 +79,13 @@ enum vp8_dec_control_id { /** For testing. */ VP9_INVERT_TILE_DECODE_ORDER, + /** control function to set the vp9 decoder into using the least recently + * used frame buffer when a new buffer is requested. Takes an int and if + * the value is zero will turn off using lru cache. The value of zero is + * the default. If the value is anything besides zero, then that will turn + * on lru cache.*/ + VP9D_SET_FRAME_BUFFER_LRU_CACHE, + VP8_DECODER_CTRL_ID_MAX }; @@ -110,6 +117,7 @@ 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(VP9_INVERT_TILE_DECODE_ORDER, int) +VPX_CTRL_USE_TYPE(VP9D_SET_FRAME_BUFFER_LRU_CACHE, int) /*! @} - end defgroup vp8_decoder */ diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk index 549c24908..df3ff6ef1 100644 --- a/vpx/vpx_codec.mk +++ b/vpx/vpx_codec.mk @@ -27,6 +27,7 @@ API_DOC_SRCS-yes += vpx_codec.h API_DOC_SRCS-yes += vpx_decoder.h API_DOC_SRCS-yes += vpx_encoder.h API_DOC_SRCS-yes += vpx_image.h +API_DOC_SRCS-yes += vpx_external_frame_buffer.h API_SRCS-yes += src/vpx_decoder.c API_SRCS-yes += vpx_decoder.h @@ -38,4 +39,5 @@ API_SRCS-yes += src/vpx_image.c API_SRCS-yes += vpx_codec.h API_SRCS-yes += vpx_codec.mk API_SRCS-yes += vpx_image.h +API_SRCS-yes += vpx_external_frame_buffer.h API_SRCS-$(BUILD_LIBVPX) += vpx_integer.h diff --git a/vpx/vpx_decoder.h b/vpx/vpx_decoder.h index 2dcd024cc..08f7f434e 100644 --- a/vpx/vpx_decoder.h +++ b/vpx/vpx_decoder.h @@ -30,6 +30,7 @@ extern "C" { #endif #include "vpx_codec.h" +#include "vpx_external_frame_buffer.h" /*!\brief Current ABI version number * @@ -39,7 +40,7 @@ extern "C" { * types, removing or reassigning enums, adding/removing/rearranging * fields to structures */ -#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/ +#define VPX_DECODER_ABI_VERSION (3 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/ /*! \brief Decoder capabilities bitfield * @@ -66,6 +67,8 @@ extern "C" { */ #define VPX_CODEC_CAP_FRAME_THREADING 0x200000 /**< Can support frame-based multi-threading */ +#define VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER 0x400000 /**< Can support external + frame buffers */ #define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */ #define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded @@ -326,6 +329,49 @@ extern "C" { /*!@} - end defgroup cap_put_slice*/ + /*!\defgroup cap_external_frame_buffer External Frame Buffer Functions + * + * The following section is required to be implemented for all decoders + * that advertise the VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER capability. + * Calling this function for codecs that don't advertise this capability + * will result in an error code being returned, usually VPX_CODEC_ERROR. + * + * \note + * Currently this only works with VP9. + * @{ + */ + + /*!\brief Pass in external frame buffers for the decoder to use. + * + * Registers a given function to be called when the current frame to + * decode will be bigger than the external frame buffer size. This + * function must be called before the first call to decode or libvpx + * will assume the default behavior of allocating frame buffers internally. + * Frame buffers with a size of 0 are valid. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] fb_list Pointer to array of frame buffers + * \param[in] fb_count Number of elements in frame buffer array + * \param[in] cb Pointer to the callback function + * \param[in] user_priv User's private data + * + * \retval #VPX_CODEC_OK + * External frame buffers passed into the decoder. + * \retval #VPX_CODEC_ERROR + * Decoder context not initialized, or algorithm not capable of + * using external frame buffers. + * + * \note + * When decoding VP9, the application must pass in at least 8 external + * frame buffers, as VP9 can have up to 8 reference frames. + */ + vpx_codec_err_t vpx_codec_set_frame_buffers( + vpx_codec_ctx_t *ctx, + vpx_codec_frame_buffer_t *fb_list, int fb_count, + vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv); + + /*!@} - end defgroup cap_external_frame_buffer */ + /*!@} - end defgroup decoder*/ #ifdef __cplusplus } diff --git a/vpx/vpx_external_frame_buffer.h b/vpx/vpx_external_frame_buffer.h new file mode 100644 index 000000000..adf133042 --- /dev/null +++ b/vpx/vpx_external_frame_buffer.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef VPX_VPX_EXTERNAL_FRAME_BUFFER_H_ +#define VPX_VPX_EXTERNAL_FRAME_BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vpx/vpx_integer.h" + +/*!\brief External frame buffer + * + * This structure is used to hold external frame buffers passed into the + * decoder by the application. + */ +typedef struct vpx_codec_frame_buffer { + uint8_t *data; /**< Pointer to the data buffer */ + size_t size; /**< Size of data in bytes */ + void *frame_priv; /**< Frame's private data */ +} vpx_codec_frame_buffer_t; + +/*!\brief realloc frame buffer callback prototype + * + * This callback is invoked by the decoder to notify the application one + * of the external frame buffers must increase in size, in order for the + * decode call to complete. The callback must allocate at least new_size in + * bytes and assign it to fb->data. Then the callback must set fb->size to + * the allocated size. The application does not need to align the allocated + * data. The callback is usually triggered by a frame size change. On success + * the callback must return 0. Any failure the callback must return a value + * less than 0. + * + * \param[in] user_priv User's private data + * \param[in] new_size Size in bytes needed by the buffer. + * \param[in/out] fb Pointer to frame buffer to increase size. + */ +typedef int (*vpx_realloc_frame_buffer_cb_fn_t)( + void *user_priv, size_t new_size, vpx_codec_frame_buffer_t *fb); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VPX_VPX_EXTERNAL_FRAME_BUFFER_H_ diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c index 7c3f7ece9..a020e19b7 100644 --- a/vpx_scale/generic/yv12config.c +++ b/vpx_scale/generic/yv12config.c @@ -19,10 +19,18 @@ /**************************************************************************** * ****************************************************************************/ + +#define yv12_align_addr(addr, align) \ + (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align)) + int vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) { if (ybf) { - vpx_free(ybf->buffer_alloc); + // If libvpx is using external frame buffers then buffer_alloc_sz must + // not be set. + if (ybf->buffer_alloc_sz > 0) { + vpx_free(ybf->buffer_alloc); + } /* buffer_alloc isn't accessed by most functions. Rather y_buffer, u_buffer and v_buffer point to buffer_alloc and are used. Clear out @@ -108,7 +116,9 @@ int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) { if (ybf) { - vpx_free(ybf->buffer_alloc); + if (ybf->buffer_alloc_sz > 0) { + vpx_free(ybf->buffer_alloc); + } /* buffer_alloc isn't accessed by most functions. Rather y_buffer, u_buffer and v_buffer point to buffer_alloc and are used. Clear out @@ -123,7 +133,10 @@ int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) { int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, - int ss_x, int ss_y, int border) { + int ss_x, int ss_y, int border, + vpx_codec_frame_buffer_t *ext_fb, + vpx_realloc_frame_buffer_cb_fn_t cb, + void *user_priv) { if (ybf) { const int aligned_width = (width + 7) & ~7; const int aligned_height = (height + 7) & ~7; @@ -148,15 +161,36 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, #else const int frame_size = yplane_size + 2 * uvplane_size; #endif - if (frame_size > ybf->buffer_alloc_sz) { - // Allocation to hold larger frame, or first allocation. - if (ybf->buffer_alloc) - vpx_free(ybf->buffer_alloc); - ybf->buffer_alloc = vpx_memalign(32, frame_size); - ybf->buffer_alloc_sz = frame_size; + + if (ext_fb != NULL) { + const int align_addr_extra_size = 31; + const int external_frame_size = frame_size + align_addr_extra_size; + if (external_frame_size > ext_fb->size) { + // Allocation to hold larger frame, or first allocation. + if (cb(user_priv, external_frame_size, ext_fb) < 0) { + return -1; + } + + if (ext_fb->data == NULL || ext_fb->size < external_frame_size) { + return -1; + } + + ybf->buffer_alloc = yv12_align_addr(ext_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); + ybf->buffer_alloc = vpx_memalign(32, frame_size); + ybf->buffer_alloc_sz = frame_size; + } + + if (ybf->buffer_alloc_sz < frame_size) + return -1; } - if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size) + if (!ybf->buffer_alloc) return -1; /* Only support allocating buffers that have a border that's a multiple @@ -206,7 +240,8 @@ int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int ss_x, int ss_y, int border) { if (ybf) { vp9_free_frame_buffer(ybf); - return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border); + return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border, + NULL, NULL, NULL); } return -2; } diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h index 0e950fb14..f23e1163c 100644 --- a/vpx_scale/yv12config.h +++ b/vpx_scale/yv12config.h @@ -15,6 +15,7 @@ extern "C" { #endif +#include "vpx/vpx_external_frame_buffer.h" #include "vpx/vpx_integer.h" #define VP8BORDERINPIXELS 32 @@ -64,9 +65,20 @@ extern "C" { int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int ss_x, int ss_y, int border); + + // Updates the yv12 buffer config with the frame buffer. If ext_fb is not + // NULL then libvpx is using external frame buffers. The function will + // check if the frame buffer is big enough to fit the decoded frame and + // try to reallocate the frame buffer. If ext_fb is not NULL and the frame + // buffer is not big enough libvpx will call cb with minimum size in bytes. + // + // Returns 0 on success. Returns < 0 on failure. int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int ss_x, int ss_y, - int border); + int border, + vpx_codec_frame_buffer_t *ext_fb, + vpx_realloc_frame_buffer_cb_fn_t cb, + void *user_priv); int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf); #ifdef __cplusplus @@ -89,6 +89,10 @@ static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0, "Enable decoder error-concealment"); static const arg_def_t scalearg = ARG_DEF("S", "scale", 0, "Scale output frames uniformly"); +static const arg_def_t fb_arg = + ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use"); +static const arg_def_t fb_lru_arg = + ARG_DEF(NULL, "frame-buffers-lru", 1, "Turn on/off frame buffer lru"); #if CONFIG_MD5 @@ -98,7 +102,7 @@ static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0, static const arg_def_t *all_args[] = { &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg, &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, - &threadsarg, &verbosearg, &scalearg, + &threadsarg, &verbosearg, &scalearg, &fb_arg, &fb_lru_arg, #if CONFIG_MD5 &md5arg, #endif @@ -314,6 +318,31 @@ void show_progress(int frame_in, int frame_out, unsigned long dx_time) { (float)frame_out * 1000000.0 / (float)dx_time); } +// Called by libvpx if the frame buffer size needs to increase. +// +// Parameters: +// user_priv Data passed into libvpx. +// new_size Minimum size needed by libvpx to decompress the next frame. +// fb Pointer to the frame buffer to update. +// +// Returns 0 on success. Returns < 0 on failure. +int realloc_vp9_frame_buffer(void *user_priv, size_t new_size, + vpx_codec_frame_buffer_t *fb) { + (void)user_priv; + if (!fb) + return -1; + + free(fb->data); + fb->data = (uint8_t*)malloc(new_size); + if (!fb->data) { + fb->size = 0; + return -1; + } + + fb->size = new_size; + return 0; +} + void generate_filename(const char *pattern, char *out, size_t q_len, unsigned int d_w, unsigned int d_h, unsigned int frame_in) { @@ -428,6 +457,9 @@ int main_loop(int argc, const char **argv_) { int do_scale = 0; vpx_image_t *scaled_img = NULL; int frame_avail, got_data; + int num_external_frame_buffers = 0; + int fb_lru_cache = 0; + vpx_codec_frame_buffer_t *frame_buffers = NULL; struct VpxDecInputContext input = {0}; struct VpxInputContext vpx_input_ctx = {0}; @@ -487,6 +519,10 @@ int main_loop(int argc, const char **argv_) { quiet = 0; else if (arg_match(&arg, &scalearg, argi)) do_scale = 1; + else if (arg_match(&arg, &fb_arg, argi)) + num_external_frame_buffers = arg_parse_uint(&arg); + else if (arg_match(&arg, &fb_lru_arg, argi)) + fb_lru_cache = arg_parse_uint(&arg); #if CONFIG_VP8_DECODER else if (arg_match(&arg, &addnoise_level, argi)) { @@ -704,6 +740,30 @@ int main_loop(int argc, const char **argv_) { arg_skip--; } + if (num_external_frame_buffers > 0) { + // Allocate the frame buffer list, setting all of the values to 0. + // Including the size of frame buffers. Libvpx will request the + // application to realloc the frame buffer data if the size is too small. + frame_buffers = (vpx_codec_frame_buffer_t*)calloc( + num_external_frame_buffers, sizeof(*frame_buffers)); + if (vpx_codec_set_frame_buffers(&decoder, frame_buffers, + num_external_frame_buffers, + realloc_vp9_frame_buffer, + NULL)) { + fprintf(stderr, "Failed to configure external frame buffers: %s\n", + vpx_codec_error(&decoder)); + return EXIT_FAILURE; + } + } + + if (fb_lru_cache > 0 && + vpx_codec_control(&decoder, VP9D_SET_FRAME_BUFFER_LRU_CACHE, + fb_lru_cache)) { + fprintf(stderr, "Failed to set frame buffer lru cache: %s\n", + vpx_codec_error(&decoder)); + return EXIT_FAILURE; + } + frame_avail = 1; got_data = 0; @@ -878,6 +938,10 @@ fail: free(buf); if (scaled_img) vpx_img_free(scaled_img); + for (i = 0; i < num_external_frame_buffers; ++i) { + free(frame_buffers[i].data); + } + free(frame_buffers); fclose(infile); free(argv); @@ -117,8 +117,10 @@ int webm_read_frame(struct WebmInputContext *webm_ctx, do { /* End of this packet, get another. */ - if (webm_ctx->pkt) + if (webm_ctx->pkt) { nestegg_free_packet(webm_ctx->pkt); + webm_ctx->pkt = NULL; + } if (nestegg_read_packet(webm_ctx->nestegg_ctx, &webm_ctx->pkt) <= 0 || nestegg_packet_track(webm_ctx->pkt, &track)) { @@ -188,6 +190,9 @@ int webm_guess_framerate(struct WebmInputContext *webm_ctx, } void webm_free(struct WebmInputContext *webm_ctx) { - if (webm_ctx && webm_ctx->nestegg_ctx) + if (webm_ctx && webm_ctx->nestegg_ctx) { + if (webm_ctx->pkt) + nestegg_free_packet(webm_ctx->pkt); nestegg_destroy(webm_ctx->nestegg_ctx); + } } |