Compare commits
	
		
			13 Commits
		
	
	
		
			javanwhist
			...
			playground
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6b0c636b96 | ||
| 
						 | 
					b0aa2db2e7 | ||
| 
						 | 
					95d0f87d6e | ||
| 
						 | 
					c741a4fe03 | ||
| 
						 | 
					430c389f16 | ||
| 
						 | 
					d8b0d40bf6 | ||
| 
						 | 
					a4dfcd9a2d | ||
| 
						 | 
					be17f1b338 | ||
| 
						 | 
					ffdad39324 | ||
| 
						 | 
					07ac101806 | ||
| 
						 | 
					a49d80bfc8 | ||
| 
						 | 
					77a29953c5 | ||
| 
						 | 
					1a4b017fad | 
@@ -137,7 +137,9 @@ for opt in "$@"; do
 | 
			
		||||
        ;;
 | 
			
		||||
        --lib) proj_kind="lib"
 | 
			
		||||
        ;;
 | 
			
		||||
        --src-path-bare=*) src_path_bare=$(fix_path "$optval")
 | 
			
		||||
        --src-path-bare=*)
 | 
			
		||||
            src_path_bare=$(fix_path "$optval")
 | 
			
		||||
            src_path_bare=${src_path_bare%/}
 | 
			
		||||
        ;;
 | 
			
		||||
        --static-crt) use_static_runtime=true
 | 
			
		||||
        ;;
 | 
			
		||||
@@ -151,9 +153,9 @@ for opt in "$@"; do
 | 
			
		||||
            esac
 | 
			
		||||
        ;;
 | 
			
		||||
        -I*)
 | 
			
		||||
            opt="${opt%/}"
 | 
			
		||||
            opt=${opt##-I}
 | 
			
		||||
            opt=$(fix_path "$opt")
 | 
			
		||||
            opt="${opt%/}"
 | 
			
		||||
            incs="${incs}${incs:+;}"${opt}""
 | 
			
		||||
            yasmincs="${yasmincs} -I"${opt}""
 | 
			
		||||
        ;;
 | 
			
		||||
@@ -414,7 +416,7 @@ generate_vcproj() {
 | 
			
		||||
                    vpx)
 | 
			
		||||
                        tag Tool \
 | 
			
		||||
                            Name="VCPreBuildEventTool" \
 | 
			
		||||
                            CommandLine="call obj_int_extract.bat $src_path_bare $plat_no_ws\\\$(ConfigurationName)" \
 | 
			
		||||
                            CommandLine="call obj_int_extract.bat "$src_path_bare" $plat_no_ws\\\$(ConfigurationName)" \
 | 
			
		||||
 | 
			
		||||
                        tag Tool \
 | 
			
		||||
                            Name="VCCLCompilerTool" \
 | 
			
		||||
 
 | 
			
		||||
@@ -157,7 +157,9 @@ for opt in "$@"; do
 | 
			
		||||
        ;;
 | 
			
		||||
        --lib) proj_kind="lib"
 | 
			
		||||
        ;;
 | 
			
		||||
        --src-path-bare=*) src_path_bare=$(fix_path "$optval")
 | 
			
		||||
        --src-path-bare=*)
 | 
			
		||||
            src_path_bare=$(fix_path "$optval")
 | 
			
		||||
            src_path_bare=${src_path_bare%/}
 | 
			
		||||
        ;;
 | 
			
		||||
        --static-crt) use_static_runtime=true
 | 
			
		||||
        ;;
 | 
			
		||||
@@ -173,9 +175,9 @@ for opt in "$@"; do
 | 
			
		||||
            esac
 | 
			
		||||
        ;;
 | 
			
		||||
        -I*)
 | 
			
		||||
            opt="${opt%/}"
 | 
			
		||||
            opt=${opt##-I}
 | 
			
		||||
            opt=$(fix_path "$opt")
 | 
			
		||||
            opt="${opt%/}"
 | 
			
		||||
            incs="${incs}${incs:+;}"${opt}""
 | 
			
		||||
            yasmincs="${yasmincs} -I"${opt}""
 | 
			
		||||
        ;;
 | 
			
		||||
 
 | 
			
		||||
@@ -50,9 +50,79 @@ build_target() {
 | 
			
		||||
  vlog "***Done building target: ${target}***"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Returns the preprocessor symbol for the target specified by $1.
 | 
			
		||||
target_to_preproc_symbol() {
 | 
			
		||||
  target="$1"
 | 
			
		||||
  case "${target}" in
 | 
			
		||||
    armv6-*)
 | 
			
		||||
      echo "__ARM_ARCH_6__"
 | 
			
		||||
      ;;
 | 
			
		||||
    armv7-*)
 | 
			
		||||
      echo "__ARM_ARCH_7__"
 | 
			
		||||
      ;;
 | 
			
		||||
    armv7s-*)
 | 
			
		||||
      echo "__ARM_ARCH_7S__"
 | 
			
		||||
      ;;
 | 
			
		||||
    x86-*)
 | 
			
		||||
      echo "__i386__"
 | 
			
		||||
      ;;
 | 
			
		||||
    x86_64-*)
 | 
			
		||||
      echo "__x86_64__"
 | 
			
		||||
      ;;
 | 
			
		||||
    *)
 | 
			
		||||
      echo "#error ${target} unknown/unsupported"
 | 
			
		||||
      return 1
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Create a vpx_config.h shim that, based on preprocessor settings for the
 | 
			
		||||
# current target CPU, includes the real vpx_config.h for the current target.
 | 
			
		||||
# $1 is the list of targets.
 | 
			
		||||
create_vpx_framework_config_shim() {
 | 
			
		||||
  local targets="$1"
 | 
			
		||||
  local config_file="${HEADER_DIR}/vpx_config.h"
 | 
			
		||||
  local preproc_symbol=""
 | 
			
		||||
  local target=""
 | 
			
		||||
  local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_"
 | 
			
		||||
 | 
			
		||||
  local file_header="/*
 | 
			
		||||
 *  Copyright (c) $(date +%Y) 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* GENERATED FILE: DO NOT EDIT! */
 | 
			
		||||
 | 
			
		||||
#ifndef ${include_guard}
 | 
			
		||||
#define ${include_guard}
 | 
			
		||||
 | 
			
		||||
#if defined"
 | 
			
		||||
 | 
			
		||||
  printf "%s" "${file_header}" > "${config_file}"
 | 
			
		||||
  for target in ${targets}; do
 | 
			
		||||
    preproc_symbol=$(target_to_preproc_symbol "${target}")
 | 
			
		||||
    printf " ${preproc_symbol}\n" >> "${config_file}"
 | 
			
		||||
    printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}"
 | 
			
		||||
    printf "#elif defined" >> "${config_file}"
 | 
			
		||||
    mkdir "${HEADER_DIR}/${target}"
 | 
			
		||||
    cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}"
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  # Consume the last line of output from the loop: We don't want it.
 | 
			
		||||
  sed -i '' -e '$d' "${config_file}"
 | 
			
		||||
 | 
			
		||||
  printf "#endif\n\n" >> "${config_file}"
 | 
			
		||||
  printf "#endif  // ${include_guard}" >> "${config_file}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Configures and builds each target specified by $1, and then builds
 | 
			
		||||
# VPX.framework.
 | 
			
		||||
build_targets() {
 | 
			
		||||
build_framework() {
 | 
			
		||||
  local lib_list=""
 | 
			
		||||
  local targets="$1"
 | 
			
		||||
  local target=""
 | 
			
		||||
@@ -75,15 +145,20 @@ build_targets() {
 | 
			
		||||
 | 
			
		||||
  cd "${ORIG_PWD}"
 | 
			
		||||
 | 
			
		||||
  # Includes are identical for all platforms, and according to dist target
 | 
			
		||||
  # behavior vpx_config.h and vpx_version.h aren't actually necessary for user
 | 
			
		||||
  # apps built with libvpx. So, just copy the includes from the last target
 | 
			
		||||
  # built.
 | 
			
		||||
  # TODO(tomfinegan): The above is a lame excuse. Build common config/version
 | 
			
		||||
  # includes that use the preprocessor to include the correct file.
 | 
			
		||||
  # The basic libvpx API includes are all the same; just grab the most recent
 | 
			
		||||
  # set.
 | 
			
		||||
  cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}"
 | 
			
		||||
 | 
			
		||||
  # Build the fat library.
 | 
			
		||||
  ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX
 | 
			
		||||
 | 
			
		||||
  # Create the vpx_config.h shim that allows usage of vpx_config.h from
 | 
			
		||||
  # within VPX.framework.
 | 
			
		||||
  create_vpx_framework_config_shim "${targets}"
 | 
			
		||||
 | 
			
		||||
  # Copy in vpx_version.h.
 | 
			
		||||
  cp -p "${BUILD_ROOT}/${target}/vpx_version.h" "${HEADER_DIR}"
 | 
			
		||||
 | 
			
		||||
  vlog "Created fat library ${FRAMEWORK_DIR}/VPX containing:"
 | 
			
		||||
  for lib in ${lib_list}; do
 | 
			
		||||
    vlog "  $(echo ${lib} | awk -F / '{print $2, $NF}')"
 | 
			
		||||
@@ -166,4 +241,4 @@ cat << EOF
 | 
			
		||||
EOF
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
build_targets "${TARGETS}"
 | 
			
		||||
build_framework "${TARGETS}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -273,6 +273,13 @@ EXPERIMENT_LIST="
 | 
			
		||||
    multiple_arf
 | 
			
		||||
    spatial_svc
 | 
			
		||||
    denoising
 | 
			
		||||
    masked_interinter
 | 
			
		||||
    interintra
 | 
			
		||||
    masked_interintra
 | 
			
		||||
    filterintra
 | 
			
		||||
    ext_tx
 | 
			
		||||
    supertx
 | 
			
		||||
    copy_coding
 | 
			
		||||
"
 | 
			
		||||
CONFIG_LIST="
 | 
			
		||||
    external_build
 | 
			
		||||
 
 | 
			
		||||
@@ -296,6 +296,7 @@ int main(int argc, const char **argv) {
 | 
			
		||||
  int frame_duration = 1; /* 1 timebase tick per frame */
 | 
			
		||||
  FILE *infile = NULL;
 | 
			
		||||
  int end_of_stream = 0;
 | 
			
		||||
  int frame_size;
 | 
			
		||||
 | 
			
		||||
  memset(&svc_ctx, 0, sizeof(svc_ctx));
 | 
			
		||||
  svc_ctx.log_print = 1;
 | 
			
		||||
@@ -351,11 +352,10 @@ int main(int argc, const char **argv) {
 | 
			
		||||
      die_codec(&codec, "Failed to encode frame");
 | 
			
		||||
    }
 | 
			
		||||
    if (!(app_input.passes == 2 && app_input.pass == 1)) {
 | 
			
		||||
      if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
 | 
			
		||||
      while ((frame_size = vpx_svc_get_frame_size(&svc_ctx)) > 0) {
 | 
			
		||||
        vpx_video_writer_write_frame(writer,
 | 
			
		||||
                                     vpx_svc_get_buffer(&svc_ctx),
 | 
			
		||||
                                     vpx_svc_get_frame_size(&svc_ctx),
 | 
			
		||||
                                     pts);
 | 
			
		||||
                                     frame_size, pts);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (vpx_svc_get_rc_stats_buffer_size(&svc_ctx) > 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,13 +15,27 @@
 | 
			
		||||
 | 
			
		||||
namespace libvpx_test {
 | 
			
		||||
 | 
			
		||||
const char kVP8Name[] = "WebM Project VP8";
 | 
			
		||||
 | 
			
		||||
vpx_codec_err_t Decoder::PeekStream(const uint8_t *cxdata, size_t size,
 | 
			
		||||
                                    vpx_codec_stream_info_t *stream_info) {
 | 
			
		||||
  return vpx_codec_peek_stream_info(CodecInterface(),
 | 
			
		||||
                                    cxdata, static_cast<unsigned int>(size),
 | 
			
		||||
                                    stream_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size) {
 | 
			
		||||
  return DecodeFrame(cxdata, size, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size,
 | 
			
		||||
                                     void *user_priv) {
 | 
			
		||||
  vpx_codec_err_t res_dec;
 | 
			
		||||
  InitOnce();
 | 
			
		||||
  REGISTER_STATE_CHECK(
 | 
			
		||||
      res_dec = vpx_codec_decode(&decoder_,
 | 
			
		||||
                                 cxdata, static_cast<unsigned int>(size),
 | 
			
		||||
                                 NULL, 0));
 | 
			
		||||
                                 user_priv, 0));
 | 
			
		||||
  return res_dec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -29,13 +43,37 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) {
 | 
			
		||||
  vpx_codec_dec_cfg_t dec_cfg = {0};
 | 
			
		||||
  Decoder* const decoder = codec_->CreateDecoder(dec_cfg, 0);
 | 
			
		||||
  ASSERT_TRUE(decoder != NULL);
 | 
			
		||||
  const char *codec_name = decoder->GetDecoderName();
 | 
			
		||||
  const bool is_vp8 = strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0;
 | 
			
		||||
 | 
			
		||||
  // Decode frames.
 | 
			
		||||
  for (video->Begin(); video->cxdata(); video->Next()) {
 | 
			
		||||
  for (video->Begin(); !::testing::Test::HasFailure() && video->cxdata();
 | 
			
		||||
       video->Next()) {
 | 
			
		||||
    PreDecodeFrameHook(*video, decoder);
 | 
			
		||||
 | 
			
		||||
    vpx_codec_stream_info_t stream_info;
 | 
			
		||||
    stream_info.sz = sizeof(stream_info);
 | 
			
		||||
    const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(),
 | 
			
		||||
                                                         video->frame_size(),
 | 
			
		||||
                                                         &stream_info);
 | 
			
		||||
    if (is_vp8) {
 | 
			
		||||
      /* Vp8's implementation of PeekStream returns an error if the frame you
 | 
			
		||||
       * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first
 | 
			
		||||
       * frame, which must be a keyframe. */
 | 
			
		||||
      if (video->frame_number() == 0)
 | 
			
		||||
        ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
 | 
			
		||||
            << vpx_codec_err_to_string(res_peek);
 | 
			
		||||
    } else {
 | 
			
		||||
      /* The Vp9 implementation of PeekStream returns an error only if the
 | 
			
		||||
       * data passed to it isn't a valid Vp9 chunk. */
 | 
			
		||||
      ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
 | 
			
		||||
          << vpx_codec_err_to_string(res_peek);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
 | 
			
		||||
                                                   video->frame_size());
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
 | 
			
		||||
    if (!HandleDecodeResult(res_dec, *video, decoder))
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    DxDataIterator dec_iter = decoder->GetDxData();
 | 
			
		||||
    const vpx_image_t *img = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -49,8 +49,14 @@ class Decoder {
 | 
			
		||||
    vpx_codec_destroy(&decoder_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vpx_codec_err_t PeekStream(const uint8_t *cxdata, size_t size,
 | 
			
		||||
                             vpx_codec_stream_info_t *stream_info);
 | 
			
		||||
 | 
			
		||||
  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size);
 | 
			
		||||
 | 
			
		||||
  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size,
 | 
			
		||||
                              void *user_priv);
 | 
			
		||||
 | 
			
		||||
  DxDataIterator GetDxData() {
 | 
			
		||||
    return DxDataIterator(&decoder_);
 | 
			
		||||
  }
 | 
			
		||||
@@ -85,6 +91,10 @@ class Decoder {
 | 
			
		||||
        &decoder_, cb_get, cb_release, user_priv);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const char* GetDecoderName() {
 | 
			
		||||
    return vpx_codec_iface_name(CodecInterface());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  virtual vpx_codec_iface_t* CodecInterface() const = 0;
 | 
			
		||||
 | 
			
		||||
@@ -114,6 +124,14 @@ class DecoderTest {
 | 
			
		||||
  virtual void PreDecodeFrameHook(const CompressedVideoSource& video,
 | 
			
		||||
                                  Decoder *decoder) {}
 | 
			
		||||
 | 
			
		||||
  // Hook to be called to handle decode result. Return true to continue.
 | 
			
		||||
  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
 | 
			
		||||
                                  const CompressedVideoSource& /* video */,
 | 
			
		||||
                                  Decoder *decoder) {
 | 
			
		||||
    EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
 | 
			
		||||
    return VPX_CODEC_OK == res_dec;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Hook to be called on every decompressed frame.
 | 
			
		||||
  virtual void DecompressedFrameHook(const vpx_image_t& img,
 | 
			
		||||
                                     const unsigned int frame_number) {}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								test/invalid_file_test.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								test/invalid_file_test.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 *  Use of this source code is governed by a BSD-style license
 | 
			
		||||
 *  that can be found in the LICENSE file in the root of the source
 | 
			
		||||
 *  tree. An additional intellectual property rights grant can be found
 | 
			
		||||
 *  in the file PATENTS.  All contributing project authors may
 | 
			
		||||
 *  be found in the AUTHORS file in the root of the source tree.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "third_party/googletest/src/include/gtest/gtest.h"
 | 
			
		||||
#include "./vpx_config.h"
 | 
			
		||||
#include "test/codec_factory.h"
 | 
			
		||||
#include "test/decode_test_driver.h"
 | 
			
		||||
#include "test/ivf_video_source.h"
 | 
			
		||||
#include "test/util.h"
 | 
			
		||||
#if CONFIG_WEBM_IO
 | 
			
		||||
#include "test/webm_video_source.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "vpx_mem/vpx_mem.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
class InvalidFileTest
 | 
			
		||||
    : public ::libvpx_test::DecoderTest,
 | 
			
		||||
      public ::libvpx_test::CodecTestWithParam<const char*> {
 | 
			
		||||
 protected:
 | 
			
		||||
  InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(NULL) {}
 | 
			
		||||
 | 
			
		||||
  virtual ~InvalidFileTest() {
 | 
			
		||||
    if (res_file_ != NULL)
 | 
			
		||||
      fclose(res_file_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void OpenResFile(const std::string &res_file_name_) {
 | 
			
		||||
    res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
 | 
			
		||||
    ASSERT_TRUE(res_file_ != NULL) << "Result file open failed. Filename: "
 | 
			
		||||
        << res_file_name_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual bool HandleDecodeResult(
 | 
			
		||||
      const vpx_codec_err_t res_dec,
 | 
			
		||||
      const libvpx_test::CompressedVideoSource &video,
 | 
			
		||||
      libvpx_test::Decoder *decoder) {
 | 
			
		||||
    EXPECT_TRUE(res_file_ != NULL);
 | 
			
		||||
    int expected_res_dec;
 | 
			
		||||
 | 
			
		||||
    // Read integer result.
 | 
			
		||||
    const int res = fscanf(res_file_, "%d", &expected_res_dec);
 | 
			
		||||
    EXPECT_NE(res, EOF) << "Read result data failed";
 | 
			
		||||
 | 
			
		||||
    // Check results match.
 | 
			
		||||
    EXPECT_EQ(expected_res_dec, res_dec)
 | 
			
		||||
        << "Results don't match: frame number = " << video.frame_number();
 | 
			
		||||
 | 
			
		||||
    return !HasFailure();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  FILE *res_file_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_P(InvalidFileTest, ReturnCode) {
 | 
			
		||||
  const std::string filename = GET_PARAM(1);
 | 
			
		||||
  libvpx_test::CompressedVideoSource *video = NULL;
 | 
			
		||||
 | 
			
		||||
  // 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") {
 | 
			
		||||
#if CONFIG_WEBM_IO
 | 
			
		||||
    video = new libvpx_test::WebMVideoSource(filename);
 | 
			
		||||
#else
 | 
			
		||||
    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
 | 
			
		||||
            filename.c_str());
 | 
			
		||||
    return;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
  video->Init();
 | 
			
		||||
 | 
			
		||||
  // Construct result file name. The file holds a list of expected integer
 | 
			
		||||
  // results, one for each decoded frame.  Any result that doesn't match
 | 
			
		||||
  // the files list will cause a test failure.
 | 
			
		||||
  const std::string res_filename = filename + ".res";
 | 
			
		||||
  OpenResFile(res_filename);
 | 
			
		||||
 | 
			
		||||
  // Decode frame, and check the md5 matching.
 | 
			
		||||
  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
 | 
			
		||||
  delete video;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *const kVP9InvalidFileTests[] = {
 | 
			
		||||
  "invalid-vp90-01.webm",
 | 
			
		||||
  "invalid-vp90-02.webm",
 | 
			
		||||
  "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
 | 
			
		||||
 | 
			
		||||
VP9_INSTANTIATE_TEST_CASE(InvalidFileTest,
 | 
			
		||||
                          ::testing::ValuesIn(kVP9InvalidFileTests,
 | 
			
		||||
                                              kVP9InvalidFileTests +
 | 
			
		||||
                                              NELEMENTS(kVP9InvalidFileTests)));
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
							
								
								
									
										121
									
								
								test/svc_test.cc
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								test/svc_test.cc
									
									
									
									
									
								
							@@ -265,9 +265,17 @@ TEST_F(SvcTest, FirstFrameHasLayers) {
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  EXPECT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
 | 
			
		||||
  if (vpx_svc_get_frame_size(&svc_) == 0) {
 | 
			
		||||
    // Flush encoder
 | 
			
		||||
    res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
 | 
			
		||||
                         video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
    EXPECT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int frame_size = vpx_svc_get_frame_size(&svc_);
 | 
			
		||||
  EXPECT_GT(frame_size, 0);
 | 
			
		||||
  const vpx_codec_err_t res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
 | 
			
		||||
  // this test fails with a decoder error
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
@@ -277,6 +285,9 @@ TEST_F(SvcTest, EncodeThreeFrames) {
 | 
			
		||||
  svc_.spatial_layers = 2;
 | 
			
		||||
  vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
 | 
			
		||||
  vpx_svc_set_quantizers(&svc_, "40,30", 0);
 | 
			
		||||
  int decoded_frames = 0;
 | 
			
		||||
  vpx_codec_err_t res_dec;
 | 
			
		||||
  int frame_size;
 | 
			
		||||
 | 
			
		||||
  vpx_codec_err_t res =
 | 
			
		||||
      vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
 | 
			
		||||
@@ -291,13 +302,14 @@ TEST_F(SvcTest, EncodeThreeFrames) {
 | 
			
		||||
  // This frame is a keyframe.
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
 | 
			
		||||
  vpx_codec_err_t res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
  if ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // FRAME 1
 | 
			
		||||
  video.Next();
 | 
			
		||||
@@ -305,12 +317,14 @@ TEST_F(SvcTest, EncodeThreeFrames) {
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
 | 
			
		||||
  res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
  if ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // FRAME 2
 | 
			
		||||
  video.Next();
 | 
			
		||||
@@ -318,12 +332,29 @@ TEST_F(SvcTest, EncodeThreeFrames) {
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
 | 
			
		||||
  res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
  if ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Flush encoder
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  EXPECT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
 | 
			
		||||
  while ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(decoded_frames, 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(SvcTest, GetLayerResolution) {
 | 
			
		||||
@@ -413,6 +444,9 @@ TEST_F(SvcTest, TwoPassEncode) {
 | 
			
		||||
  vpx_codec_destroy(&codec_);
 | 
			
		||||
 | 
			
		||||
  // Second pass encode
 | 
			
		||||
  int decoded_frames = 0;
 | 
			
		||||
  vpx_codec_err_t res_dec;
 | 
			
		||||
  int frame_size;
 | 
			
		||||
  codec_enc_.g_pass = VPX_RC_LAST_PASS;
 | 
			
		||||
  codec_enc_.rc_twopass_stats_in.buf = &stats_buf[0];
 | 
			
		||||
  codec_enc_.rc_twopass_stats_in.sz = stats_buf.size();
 | 
			
		||||
@@ -427,12 +461,14 @@ TEST_F(SvcTest, TwoPassEncode) {
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
 | 
			
		||||
  vpx_codec_err_t res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
  if ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // FRAME 1
 | 
			
		||||
  video.Next();
 | 
			
		||||
@@ -440,12 +476,14 @@ TEST_F(SvcTest, TwoPassEncode) {
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
 | 
			
		||||
  res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
  if ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // FRAME 2
 | 
			
		||||
  video.Next();
 | 
			
		||||
@@ -453,12 +491,29 @@ TEST_F(SvcTest, TwoPassEncode) {
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
  EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
 | 
			
		||||
  res_dec = decoder_->DecodeFrame(
 | 
			
		||||
      static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)),
 | 
			
		||||
      vpx_svc_get_frame_size(&svc_));
 | 
			
		||||
  ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
  if ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Flush encoder
 | 
			
		||||
  res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
 | 
			
		||||
                       video.duration(), VPX_DL_GOOD_QUALITY);
 | 
			
		||||
  EXPECT_EQ(VPX_CODEC_OK, res);
 | 
			
		||||
 | 
			
		||||
  while ((frame_size = vpx_svc_get_frame_size(&svc_)) > 0) {
 | 
			
		||||
    EXPECT_EQ((decoded_frames == 0), vpx_svc_is_keyframe(&svc_));
 | 
			
		||||
    res_dec = decoder_->DecodeFrame(
 | 
			
		||||
        static_cast<const uint8_t *>(vpx_svc_get_buffer(&svc_)), frame_size);
 | 
			
		||||
    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
 | 
			
		||||
    ++decoded_frames;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(decoded_frames, 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
d5dfb0151c9051f8c85999255645d7a23916d3c0  hantro_collage_w352h288.yuv
 | 
			
		||||
b87815bf86020c592ccc7a846ba2e28ec8043902  hantro_odd.yuv
 | 
			
		||||
fe346136b9b8c1e6f6084cc106485706915795e4  invalid-vp90-01.webm
 | 
			
		||||
25751f5d3b05ff03f0719ad42cd625348eb8961e  invalid-vp90-01.webm.res
 | 
			
		||||
d78e2fceba5ac942246503ec8366f879c4775ca5  invalid-vp90-02.webm
 | 
			
		||||
2dadee5306245fa5eeb0f99652d0e17afbcba96d  invalid-vp90-02.webm.res
 | 
			
		||||
b1f1c3ec79114b9a0651af24ce634afb44a9a419  rush_hour_444.y4m
 | 
			
		||||
5184c46ddca8b1fadd16742e8500115bc8f749da  vp80-00-comprehensive-001.ivf
 | 
			
		||||
65bf1bbbced81b97bd030f376d1b7f61a224793f  vp80-00-comprehensive-002.ivf
 | 
			
		||||
@@ -576,6 +580,8 @@ d48c5db1b0f8e60521a7c749696b8067886033a3  vp90-2-09-aq2.webm
 | 
			
		||||
54638c38009198c38c8f3b25c182b709b6c1fd2e  vp90-2-09-lf_deltas.webm.md5
 | 
			
		||||
510d95f3beb3b51c572611fdaeeece12277dac30  vp90-2-10-show-existing-frame.webm
 | 
			
		||||
14d631096f4bfa2d71f7f739aec1448fb3c33bad  vp90-2-10-show-existing-frame.webm.md5
 | 
			
		||||
d2feea7728e8d2c615981d0f47427a4a5a45d881  vp90-2-10-show-existing-frame2.webm
 | 
			
		||||
5f7c7811baa3e4f03be1dd78c33971b727846821  vp90-2-10-show-existing-frame2.webm.md5
 | 
			
		||||
b4318e75f73a6a08992c7326de2fb589c2a794c7  vp90-2-11-size-351x287.webm
 | 
			
		||||
b3c48382cf7d0454e83a02497c229d27720f9e20  vp90-2-11-size-351x287.webm.md5
 | 
			
		||||
8e0096475ea2535bac71d3e2fc09e0c451c444df  vp90-2-11-size-351x288.webm
 | 
			
		||||
@@ -638,5 +644,5 @@ e615575ded499ea1d992f3b38e3baa434509cdcd  vp90-2-15-segkey.webm
 | 
			
		||||
e3ab35d4316c5e81325c50f5236ceca4bc0d35df  vp90-2-15-segkey.webm.md5
 | 
			
		||||
9b7ca2cac09d34c4a5d296c1900f93b1e2f69d0d  vp90-2-15-segkey_adpq.webm
 | 
			
		||||
8f46ba5f785d0c2170591a153e0d0d146a7c8090  vp90-2-15-segkey_adpq.webm.md5
 | 
			
		||||
d78e2fceba5ac942246503ec8366f879c4775ca5  vp90-2-15-fuzz-flicker.webm
 | 
			
		||||
bbd7dd15f43a703ff0a332fee4959e7b23bf77dc  vp90-2-15-fuzz-flicker.webm.md5
 | 
			
		||||
76024eb753cdac6a5e5703aaea189d35c3c30ac7  invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf
 | 
			
		||||
d3964f9dad9f60363c81b688324d95b4ec7c8038  invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf.res
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								test/test.mk
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								test/test.mk
									
									
									
									
									
								
							@@ -30,6 +30,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += cq_test.cc
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
 | 
			
		||||
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += user_priv_test.cc
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_test.cc
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += borders_test.cc
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += cpu_speed_test.cc
 | 
			
		||||
@@ -54,6 +55,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ../webmdec.h
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += webm_video_source.h
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += invalid_file_test.cc
 | 
			
		||||
LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += test_vector_test.cc
 | 
			
		||||
 | 
			
		||||
# Currently we only support decoder perf tests for vp9. Also they read from WebM
 | 
			
		||||
@@ -690,6 +692,8 @@ LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf.md5
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm.md5
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm.md5
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm.md5
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm
 | 
			
		||||
@@ -754,8 +758,14 @@ LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm.md5
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm.md5
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-fuzz-flicker.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-fuzz-flicker.webm.md5
 | 
			
		||||
 | 
			
		||||
# Invalid files for testing libvpx error checking.
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01.webm.res
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02.webm
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02.webm.res
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf
 | 
			
		||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf.res
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
 | 
			
		||||
# BBB VP9 streams
 | 
			
		||||
 
 | 
			
		||||
@@ -161,6 +161,7 @@ const char *const kVP9TestVectors[] = {
 | 
			
		||||
  "vp90-2-08-tile-4x1.webm", "vp90-2-09-subpixel-00.ivf",
 | 
			
		||||
  "vp90-2-02-size-lf-1920x1080.webm", "vp90-2-09-aq2.webm",
 | 
			
		||||
  "vp90-2-09-lf_deltas.webm", "vp90-2-10-show-existing-frame.webm",
 | 
			
		||||
  "vp90-2-10-show-existing-frame2.webm",
 | 
			
		||||
  "vp90-2-11-size-351x287.webm", "vp90-2-11-size-351x288.webm",
 | 
			
		||||
  "vp90-2-11-size-352x287.webm", "vp90-2-12-droppable_1.ivf",
 | 
			
		||||
  "vp90-2-12-droppable_2.ivf", "vp90-2-12-droppable_3.ivf",
 | 
			
		||||
@@ -179,7 +180,6 @@ const char *const kVP9TestVectors[] = {
 | 
			
		||||
  "vp90-2-14-resize-fp-tiles-8-16.webm", "vp90-2-14-resize-fp-tiles-8-1.webm",
 | 
			
		||||
  "vp90-2-14-resize-fp-tiles-8-2.webm", "vp90-2-14-resize-fp-tiles-8-4.webm",
 | 
			
		||||
  "vp90-2-15-segkey.webm", "vp90-2-15-segkey_adpq.webm",
 | 
			
		||||
  "vp90-2-15-fuzz-flicker.webm"
 | 
			
		||||
};
 | 
			
		||||
const int kNumVP9TestVectors = NELEMENTS(kVP9TestVectors);
 | 
			
		||||
#endif  // CONFIG_VP9_DECODER
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								test/user_priv_test.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								test/user_priv_test.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 *  Use of this source code is governed by a BSD-style license
 | 
			
		||||
 *  that can be found in the LICENSE file in the root of the source
 | 
			
		||||
 *  tree. An additional intellectual property rights grant can be found
 | 
			
		||||
 *  in the file PATENTS.  All contributing project authors may
 | 
			
		||||
 *  be found in the AUTHORS file in the root of the source tree.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "third_party/googletest/src/include/gtest/gtest.h"
 | 
			
		||||
#include "./vpx_config.h"
 | 
			
		||||
#include "test/acm_random.h"
 | 
			
		||||
#include "test/codec_factory.h"
 | 
			
		||||
#include "test/decode_test_driver.h"
 | 
			
		||||
#include "test/ivf_video_source.h"
 | 
			
		||||
#include "test/md5_helper.h"
 | 
			
		||||
#include "test/util.h"
 | 
			
		||||
#if CONFIG_WEBM_IO
 | 
			
		||||
#include "test/webm_video_source.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "vpx_mem/vpx_mem.h"
 | 
			
		||||
#include "vpx/vp8.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
using std::string;
 | 
			
		||||
using libvpx_test::ACMRandom;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_WEBM_IO
 | 
			
		||||
 | 
			
		||||
void CheckUserPrivateData(void *user_priv, int *target) {
 | 
			
		||||
  // actual pointer value should be the same as expected.
 | 
			
		||||
  EXPECT_EQ(reinterpret_cast<void *>(target), user_priv) <<
 | 
			
		||||
      "user_priv pointer value does not match.";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decodes |filename|. Passes in user_priv data when calling DecodeFrame and
 | 
			
		||||
// compares the user_priv from return img with the original user_priv to see if
 | 
			
		||||
// they match. Both the pointer values and the values inside the addresses
 | 
			
		||||
// should match.
 | 
			
		||||
string DecodeFile(const string &filename) {
 | 
			
		||||
  ACMRandom rnd(ACMRandom::DeterministicSeed());
 | 
			
		||||
  libvpx_test::WebMVideoSource video(filename);
 | 
			
		||||
  video.Init();
 | 
			
		||||
 | 
			
		||||
  vpx_codec_dec_cfg_t cfg = {0};
 | 
			
		||||
  libvpx_test::VP9Decoder decoder(cfg, 0);
 | 
			
		||||
 | 
			
		||||
  libvpx_test::MD5 md5;
 | 
			
		||||
  int frame_num = 0;
 | 
			
		||||
  for (video.Begin(); !::testing::Test::HasFailure() && video.cxdata();
 | 
			
		||||
       video.Next()) {
 | 
			
		||||
    void *user_priv = reinterpret_cast<void *>(&frame_num);
 | 
			
		||||
    const vpx_codec_err_t res =
 | 
			
		||||
        decoder.DecodeFrame(video.cxdata(), video.frame_size(),
 | 
			
		||||
                            (frame_num == 0) ? NULL : user_priv);
 | 
			
		||||
    if (res != VPX_CODEC_OK) {
 | 
			
		||||
      EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    libvpx_test::DxDataIterator dec_iter = decoder.GetDxData();
 | 
			
		||||
    const vpx_image_t *img = NULL;
 | 
			
		||||
 | 
			
		||||
    // Get decompressed data.
 | 
			
		||||
    while ((img = dec_iter.Next())) {
 | 
			
		||||
      if (frame_num == 0) {
 | 
			
		||||
        CheckUserPrivateData(img->user_priv, NULL);
 | 
			
		||||
      } else {
 | 
			
		||||
        CheckUserPrivateData(img->user_priv, &frame_num);
 | 
			
		||||
 | 
			
		||||
        // Also test ctrl_get_reference api.
 | 
			
		||||
        struct vp9_ref_frame ref;
 | 
			
		||||
        // Randomly fetch a reference frame.
 | 
			
		||||
        ref.idx = rnd.Rand8() % 3;
 | 
			
		||||
        decoder.Control(VP9_GET_REFERENCE, &ref);
 | 
			
		||||
 | 
			
		||||
        CheckUserPrivateData(ref.img.user_priv, &frame_num);
 | 
			
		||||
      }
 | 
			
		||||
      md5.Add(img);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    frame_num++;
 | 
			
		||||
  }
 | 
			
		||||
  return string(md5.Get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(UserPrivTest, VideoDecode) {
 | 
			
		||||
  // no tiles or frame parallel; this exercises the decoding to test the
 | 
			
		||||
  // user_priv.
 | 
			
		||||
  EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc",
 | 
			
		||||
               DecodeFile("vp90-2-03-size-226x226.webm").c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // CONFIG_WEBM_IO
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
							
								
								
									
										231
									
								
								third_party/libmkv/EbmlIDs.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								third_party/libmkv/EbmlIDs.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright (c) 2010 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 MKV_DEFS_HPP
 | 
			
		||||
#define MKV_DEFS_HPP 1
 | 
			
		||||
 | 
			
		||||
/* Commenting out values not available in webm, but available in matroska */
 | 
			
		||||
 | 
			
		||||
enum mkv {
 | 
			
		||||
  EBML = 0x1A45DFA3,
 | 
			
		||||
  EBMLVersion = 0x4286,
 | 
			
		||||
  EBMLReadVersion = 0x42F7,
 | 
			
		||||
  EBMLMaxIDLength = 0x42F2,
 | 
			
		||||
  EBMLMaxSizeLength = 0x42F3,
 | 
			
		||||
  DocType = 0x4282,
 | 
			
		||||
  DocTypeVersion = 0x4287,
 | 
			
		||||
  DocTypeReadVersion = 0x4285,
 | 
			
		||||
/* CRC_32 = 0xBF, */
 | 
			
		||||
  Void = 0xEC,
 | 
			
		||||
  SignatureSlot = 0x1B538667,
 | 
			
		||||
  SignatureAlgo = 0x7E8A,
 | 
			
		||||
  SignatureHash = 0x7E9A,
 | 
			
		||||
  SignaturePublicKey = 0x7EA5,
 | 
			
		||||
  Signature = 0x7EB5,
 | 
			
		||||
  SignatureElements = 0x7E5B,
 | 
			
		||||
  SignatureElementList = 0x7E7B,
 | 
			
		||||
  SignedElement = 0x6532,
 | 
			
		||||
  /* segment */
 | 
			
		||||
  Segment = 0x18538067,
 | 
			
		||||
  /* Meta Seek Information */
 | 
			
		||||
  SeekHead = 0x114D9B74,
 | 
			
		||||
  Seek = 0x4DBB,
 | 
			
		||||
  SeekID = 0x53AB,
 | 
			
		||||
  SeekPosition = 0x53AC,
 | 
			
		||||
  /* Segment Information */
 | 
			
		||||
  Info = 0x1549A966,
 | 
			
		||||
/* SegmentUID = 0x73A4, */
 | 
			
		||||
/* SegmentFilename = 0x7384, */
 | 
			
		||||
/* PrevUID = 0x3CB923, */
 | 
			
		||||
/* PrevFilename = 0x3C83AB, */
 | 
			
		||||
/* NextUID = 0x3EB923, */
 | 
			
		||||
/* NextFilename = 0x3E83BB, */
 | 
			
		||||
/* SegmentFamily = 0x4444, */
 | 
			
		||||
/* ChapterTranslate = 0x6924, */
 | 
			
		||||
/* ChapterTranslateEditionUID = 0x69FC, */
 | 
			
		||||
/* ChapterTranslateCodec = 0x69BF, */
 | 
			
		||||
/* ChapterTranslateID = 0x69A5, */
 | 
			
		||||
  TimecodeScale = 0x2AD7B1,
 | 
			
		||||
  Segment_Duration = 0x4489,
 | 
			
		||||
  DateUTC = 0x4461,
 | 
			
		||||
/* Title = 0x7BA9, */
 | 
			
		||||
  MuxingApp = 0x4D80,
 | 
			
		||||
  WritingApp = 0x5741,
 | 
			
		||||
  /* Cluster */
 | 
			
		||||
  Cluster = 0x1F43B675,
 | 
			
		||||
  Timecode = 0xE7,
 | 
			
		||||
/* SilentTracks = 0x5854, */
 | 
			
		||||
/* SilentTrackNumber = 0x58D7, */
 | 
			
		||||
/* Position = 0xA7, */
 | 
			
		||||
  PrevSize = 0xAB,
 | 
			
		||||
  BlockGroup = 0xA0,
 | 
			
		||||
  Block = 0xA1,
 | 
			
		||||
/* BlockVirtual = 0xA2, */
 | 
			
		||||
  BlockAdditions = 0x75A1,
 | 
			
		||||
  BlockMore = 0xA6,
 | 
			
		||||
  BlockAddID = 0xEE,
 | 
			
		||||
  BlockAdditional = 0xA5,
 | 
			
		||||
  BlockDuration = 0x9B,
 | 
			
		||||
/* ReferencePriority = 0xFA, */
 | 
			
		||||
  ReferenceBlock = 0xFB,
 | 
			
		||||
/* ReferenceVirtual = 0xFD, */
 | 
			
		||||
/* CodecState = 0xA4, */
 | 
			
		||||
/* Slices = 0x8E, */
 | 
			
		||||
/* TimeSlice = 0xE8, */
 | 
			
		||||
  LaceNumber = 0xCC,
 | 
			
		||||
/* FrameNumber = 0xCD, */
 | 
			
		||||
/* BlockAdditionID = 0xCB, */
 | 
			
		||||
/* MkvDelay = 0xCE, */
 | 
			
		||||
/* Cluster_Duration = 0xCF, */
 | 
			
		||||
  SimpleBlock = 0xA3,
 | 
			
		||||
/* EncryptedBlock = 0xAF, */
 | 
			
		||||
  /* Track */
 | 
			
		||||
  Tracks = 0x1654AE6B,
 | 
			
		||||
  TrackEntry = 0xAE,
 | 
			
		||||
  TrackNumber = 0xD7,
 | 
			
		||||
  TrackUID = 0x73C5,
 | 
			
		||||
  TrackType = 0x83,
 | 
			
		||||
  FlagEnabled = 0xB9,
 | 
			
		||||
  FlagDefault = 0x88,
 | 
			
		||||
  FlagForced = 0x55AA,
 | 
			
		||||
  FlagLacing = 0x9C,
 | 
			
		||||
/* MinCache = 0x6DE7, */
 | 
			
		||||
/* MaxCache = 0x6DF8, */
 | 
			
		||||
  DefaultDuration = 0x23E383,
 | 
			
		||||
/* TrackTimecodeScale = 0x23314F, */
 | 
			
		||||
/* TrackOffset = 0x537F, */
 | 
			
		||||
  MaxBlockAdditionID = 0x55EE,
 | 
			
		||||
  Name = 0x536E,
 | 
			
		||||
  Language = 0x22B59C,
 | 
			
		||||
  CodecID = 0x86,
 | 
			
		||||
  CodecPrivate = 0x63A2,
 | 
			
		||||
  CodecName = 0x258688,
 | 
			
		||||
/* AttachmentLink = 0x7446, */
 | 
			
		||||
/* CodecSettings = 0x3A9697, */
 | 
			
		||||
/* CodecInfoURL = 0x3B4040, */
 | 
			
		||||
/* CodecDownloadURL = 0x26B240, */
 | 
			
		||||
/* CodecDecodeAll = 0xAA, */
 | 
			
		||||
/* TrackOverlay = 0x6FAB, */
 | 
			
		||||
/* TrackTranslate = 0x6624, */
 | 
			
		||||
/* TrackTranslateEditionUID = 0x66FC, */
 | 
			
		||||
/* TrackTranslateCodec = 0x66BF, */
 | 
			
		||||
/* TrackTranslateTrackID = 0x66A5, */
 | 
			
		||||
  /* video */
 | 
			
		||||
  Video = 0xE0,
 | 
			
		||||
  FlagInterlaced = 0x9A,
 | 
			
		||||
  StereoMode = 0x53B8,
 | 
			
		||||
  AlphaMode = 0x53C0,
 | 
			
		||||
  PixelWidth = 0xB0,
 | 
			
		||||
  PixelHeight = 0xBA,
 | 
			
		||||
  PixelCropBottom = 0x54AA,
 | 
			
		||||
  PixelCropTop = 0x54BB,
 | 
			
		||||
  PixelCropLeft = 0x54CC,
 | 
			
		||||
  PixelCropRight = 0x54DD,
 | 
			
		||||
  DisplayWidth = 0x54B0,
 | 
			
		||||
  DisplayHeight = 0x54BA,
 | 
			
		||||
  DisplayUnit = 0x54B2,
 | 
			
		||||
  AspectRatioType = 0x54B3,
 | 
			
		||||
/* ColourSpace = 0x2EB524, */
 | 
			
		||||
/* GammaValue = 0x2FB523, */
 | 
			
		||||
  FrameRate = 0x2383E3,
 | 
			
		||||
  /* end video */
 | 
			
		||||
  /* audio */
 | 
			
		||||
  Audio = 0xE1,
 | 
			
		||||
  SamplingFrequency = 0xB5,
 | 
			
		||||
  OutputSamplingFrequency = 0x78B5,
 | 
			
		||||
  Channels = 0x9F,
 | 
			
		||||
/* ChannelPositions = 0x7D7B, */
 | 
			
		||||
  BitDepth = 0x6264,
 | 
			
		||||
  /* end audio */
 | 
			
		||||
  /* content encoding */
 | 
			
		||||
/* ContentEncodings = 0x6d80, */
 | 
			
		||||
/* ContentEncoding = 0x6240, */
 | 
			
		||||
/* ContentEncodingOrder = 0x5031, */
 | 
			
		||||
/* ContentEncodingScope = 0x5032, */
 | 
			
		||||
/* ContentEncodingType = 0x5033, */
 | 
			
		||||
/* ContentCompression = 0x5034, */
 | 
			
		||||
/* ContentCompAlgo = 0x4254, */
 | 
			
		||||
/* ContentCompSettings = 0x4255, */
 | 
			
		||||
/* ContentEncryption = 0x5035, */
 | 
			
		||||
/* ContentEncAlgo = 0x47e1, */
 | 
			
		||||
/* ContentEncKeyID = 0x47e2, */
 | 
			
		||||
/* ContentSignature = 0x47e3, */
 | 
			
		||||
/* ContentSigKeyID = 0x47e4, */
 | 
			
		||||
/* ContentSigAlgo = 0x47e5, */
 | 
			
		||||
/* ContentSigHashAlgo = 0x47e6, */
 | 
			
		||||
  /* end content encoding */
 | 
			
		||||
  /* Cueing Data */
 | 
			
		||||
  Cues = 0x1C53BB6B,
 | 
			
		||||
  CuePoint = 0xBB,
 | 
			
		||||
  CueTime = 0xB3,
 | 
			
		||||
  CueTrackPositions = 0xB7,
 | 
			
		||||
  CueTrack = 0xF7,
 | 
			
		||||
  CueClusterPosition = 0xF1,
 | 
			
		||||
  CueBlockNumber = 0x5378
 | 
			
		||||
/* CueCodecState = 0xEA, */
 | 
			
		||||
/* CueReference = 0xDB, */
 | 
			
		||||
/* CueRefTime = 0x96, */
 | 
			
		||||
/* CueRefCluster = 0x97, */
 | 
			
		||||
/* CueRefNumber = 0x535F, */
 | 
			
		||||
/* CueRefCodecState = 0xEB, */
 | 
			
		||||
  /* Attachment */
 | 
			
		||||
/* Attachments = 0x1941A469, */
 | 
			
		||||
/* AttachedFile = 0x61A7, */
 | 
			
		||||
/* FileDescription = 0x467E, */
 | 
			
		||||
/* FileName = 0x466E, */
 | 
			
		||||
/* FileMimeType = 0x4660, */
 | 
			
		||||
/* FileData = 0x465C, */
 | 
			
		||||
/* FileUID = 0x46AE, */
 | 
			
		||||
/* FileReferral = 0x4675, */
 | 
			
		||||
  /* Chapters */
 | 
			
		||||
/* Chapters = 0x1043A770, */
 | 
			
		||||
/* EditionEntry = 0x45B9, */
 | 
			
		||||
/* EditionUID = 0x45BC, */
 | 
			
		||||
/* EditionFlagHidden = 0x45BD, */
 | 
			
		||||
/* EditionFlagDefault = 0x45DB, */
 | 
			
		||||
/* EditionFlagOrdered = 0x45DD, */
 | 
			
		||||
/* ChapterAtom = 0xB6, */
 | 
			
		||||
/* ChapterUID = 0x73C4, */
 | 
			
		||||
/* ChapterTimeStart = 0x91, */
 | 
			
		||||
/* ChapterTimeEnd = 0x92, */
 | 
			
		||||
/* ChapterFlagHidden = 0x98, */
 | 
			
		||||
/* ChapterFlagEnabled = 0x4598, */
 | 
			
		||||
/* ChapterSegmentUID = 0x6E67, */
 | 
			
		||||
/* ChapterSegmentEditionUID = 0x6EBC, */
 | 
			
		||||
/* ChapterPhysicalEquiv = 0x63C3, */
 | 
			
		||||
/* ChapterTrack = 0x8F, */
 | 
			
		||||
/* ChapterTrackNumber = 0x89, */
 | 
			
		||||
/* ChapterDisplay = 0x80, */
 | 
			
		||||
/* ChapString = 0x85, */
 | 
			
		||||
/* ChapLanguage = 0x437C, */
 | 
			
		||||
/* ChapCountry = 0x437E, */
 | 
			
		||||
/* ChapProcess = 0x6944, */
 | 
			
		||||
/* ChapProcessCodecID = 0x6955, */
 | 
			
		||||
/* ChapProcessPrivate = 0x450D, */
 | 
			
		||||
/* ChapProcessCommand = 0x6911, */
 | 
			
		||||
/* ChapProcessTime = 0x6922, */
 | 
			
		||||
/* ChapProcessData = 0x6933, */
 | 
			
		||||
  /* Tagging */
 | 
			
		||||
/* Tags = 0x1254C367, */
 | 
			
		||||
/* Tag = 0x7373, */
 | 
			
		||||
/* Targets = 0x63C0, */
 | 
			
		||||
/* TargetTypeValue = 0x68CA, */
 | 
			
		||||
/* TargetType = 0x63CA, */
 | 
			
		||||
/* Tagging_TrackUID = 0x63C5, */
 | 
			
		||||
/* Tagging_EditionUID = 0x63C9, */
 | 
			
		||||
/* Tagging_ChapterUID = 0x63C4, */
 | 
			
		||||
/* AttachmentUID = 0x63C6, */
 | 
			
		||||
/* SimpleTag = 0x67C8, */
 | 
			
		||||
/* TagName = 0x45A3, */
 | 
			
		||||
/* TagLanguage = 0x447A, */
 | 
			
		||||
/* TagDefault = 0x4484, */
 | 
			
		||||
/* TagString = 0x4487, */
 | 
			
		||||
/* TagBinary = 0x4485, */
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										157
									
								
								third_party/libmkv/EbmlWriter.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								third_party/libmkv/EbmlWriter.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright (c) 2010 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 "EbmlWriter.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <wchar.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#define LITERALU64(n) n
 | 
			
		||||
#else
 | 
			
		||||
#define LITERALU64(n) n##LLU
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteLen(EbmlGlobal *glob, int64_t val) {
 | 
			
		||||
  /* TODO check and make sure we are not > than 0x0100000000000000LLU */
 | 
			
		||||
  unsigned char size = 8; /* size in bytes to output */
 | 
			
		||||
 | 
			
		||||
  /* mask to compare for byte size */
 | 
			
		||||
  int64_t minVal = 0xff;
 | 
			
		||||
 | 
			
		||||
  for (size = 1; size < 8; size ++) {
 | 
			
		||||
    if (val < minVal)
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    minVal = (minVal << 7);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val |= (((uint64_t)0x80) << ((size - 1) * 7));
 | 
			
		||||
 | 
			
		||||
  Ebml_Serialize(glob, (void *) &val, sizeof(val), size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteString(EbmlGlobal *glob, const char *str) {
 | 
			
		||||
  const size_t size_ = strlen(str);
 | 
			
		||||
  const uint64_t  size = size_;
 | 
			
		||||
  Ebml_WriteLen(glob, size);
 | 
			
		||||
  /* TODO: it's not clear from the spec whether the nul terminator
 | 
			
		||||
   * should be serialized too.  For now we omit the null terminator.
 | 
			
		||||
   */
 | 
			
		||||
  Ebml_Write(glob, str, (unsigned long)size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr) {
 | 
			
		||||
  const size_t strlen = wcslen(wstr);
 | 
			
		||||
 | 
			
		||||
  /* TODO: it's not clear from the spec whether the nul terminator
 | 
			
		||||
   * should be serialized too.  For now we include it.
 | 
			
		||||
   */
 | 
			
		||||
  const uint64_t  size = strlen;
 | 
			
		||||
 | 
			
		||||
  Ebml_WriteLen(glob, size);
 | 
			
		||||
  Ebml_Write(glob, wstr, (unsigned long)size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) {
 | 
			
		||||
  int len;
 | 
			
		||||
 | 
			
		||||
  if (class_id >= 0x01000000)
 | 
			
		||||
    len = 4;
 | 
			
		||||
  else if (class_id >= 0x00010000)
 | 
			
		||||
    len = 3;
 | 
			
		||||
  else if (class_id >= 0x00000100)
 | 
			
		||||
    len = 2;
 | 
			
		||||
  else
 | 
			
		||||
    len = 1;
 | 
			
		||||
 | 
			
		||||
  Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
 | 
			
		||||
  unsigned char sizeSerialized = 8 | 0x80;
 | 
			
		||||
  Ebml_WriteID(glob, class_id);
 | 
			
		||||
  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
 | 
			
		||||
  Ebml_Serialize(glob, &ui, sizeof(ui), 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui) {
 | 
			
		||||
  unsigned char size = 8; /* size in bytes to output */
 | 
			
		||||
  unsigned char sizeSerialized = 0;
 | 
			
		||||
  unsigned long minVal;
 | 
			
		||||
 | 
			
		||||
  Ebml_WriteID(glob, class_id);
 | 
			
		||||
  minVal = 0x7fLU; /* mask to compare for byte size */
 | 
			
		||||
 | 
			
		||||
  for (size = 1; size < 4; size ++) {
 | 
			
		||||
    if (ui < minVal) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    minVal <<= 7;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  sizeSerialized = 0x80 | size;
 | 
			
		||||
  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
 | 
			
		||||
  Ebml_Serialize(glob, &ui, sizeof(ui), size);
 | 
			
		||||
}
 | 
			
		||||
/* TODO: perhaps this is a poor name for this id serializer helper function */
 | 
			
		||||
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin) {
 | 
			
		||||
  int size;
 | 
			
		||||
  for (size = 4; size > 1; size--) {
 | 
			
		||||
    if (bin & (unsigned int)0x000000ff << ((size - 1) * 8))
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  Ebml_WriteID(glob, class_id);
 | 
			
		||||
  Ebml_WriteLen(glob, size);
 | 
			
		||||
  Ebml_WriteID(glob, bin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d) {
 | 
			
		||||
  unsigned char len = 0x88;
 | 
			
		||||
 | 
			
		||||
  Ebml_WriteID(glob, class_id);
 | 
			
		||||
  Ebml_Serialize(glob, &len, sizeof(len), 1);
 | 
			
		||||
  Ebml_Serialize(glob,  &d, sizeof(d), 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteSigned16(EbmlGlobal *glob, short val) {
 | 
			
		||||
  signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
 | 
			
		||||
  Ebml_Serialize(glob, &out, sizeof(out), 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s) {
 | 
			
		||||
  Ebml_WriteID(glob, class_id);
 | 
			
		||||
  Ebml_WriteString(glob, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s) {
 | 
			
		||||
  Ebml_WriteID(glob,  class_id);
 | 
			
		||||
  Ebml_WriteUTF8(glob,  s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length) {
 | 
			
		||||
  Ebml_WriteID(glob, class_id);
 | 
			
		||||
  Ebml_WriteLen(glob, data_length);
 | 
			
		||||
  Ebml_Write(glob,  data, data_length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize) {
 | 
			
		||||
  unsigned char tmp = 0;
 | 
			
		||||
  unsigned long i = 0;
 | 
			
		||||
 | 
			
		||||
  Ebml_WriteID(glob, 0xEC);
 | 
			
		||||
  Ebml_WriteLen(glob, vSize);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < vSize; i++) {
 | 
			
		||||
    Ebml_Write(glob, &tmp, 1);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TODO Serialize Date */
 | 
			
		||||
							
								
								
									
										42
									
								
								third_party/libmkv/EbmlWriter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								third_party/libmkv/EbmlWriter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright (c) 2010 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 EBMLWRITER_HPP
 | 
			
		||||
#define EBMLWRITER_HPP
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include "vpx/vpx_integer.h"
 | 
			
		||||
 | 
			
		||||
/* note: you must define write and serialize functions as well as your own
 | 
			
		||||
 * EBML_GLOBAL
 | 
			
		||||
 *
 | 
			
		||||
 * These functions MUST be implemented
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct EbmlGlobal EbmlGlobal;
 | 
			
		||||
void  Ebml_Serialize(EbmlGlobal *glob, const void *, int, unsigned long);
 | 
			
		||||
void  Ebml_Write(EbmlGlobal *glob, const void *, unsigned long);
 | 
			
		||||
 | 
			
		||||
/*****/
 | 
			
		||||
 | 
			
		||||
void Ebml_WriteLen(EbmlGlobal *glob, int64_t val);
 | 
			
		||||
void Ebml_WriteString(EbmlGlobal *glob, const char *str);
 | 
			
		||||
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr);
 | 
			
		||||
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id);
 | 
			
		||||
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui);
 | 
			
		||||
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
 | 
			
		||||
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
 | 
			
		||||
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d);
 | 
			
		||||
/* TODO make this more generic to signed */
 | 
			
		||||
void Ebml_WriteSigned16(EbmlGlobal *glob, short val);
 | 
			
		||||
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s);
 | 
			
		||||
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s);
 | 
			
		||||
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length);
 | 
			
		||||
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize);
 | 
			
		||||
/* TODO need date function */
 | 
			
		||||
#endif
 | 
			
		||||
@@ -463,9 +463,7 @@ $vp8_short_walsh4x4_neon_asm=vp8_short_walsh4x4_neon;
 | 
			
		||||
# Quantizer
 | 
			
		||||
#
 | 
			
		||||
add_proto qw/void vp8_regular_quantize_b/, "struct block *, struct blockd *";
 | 
			
		||||
specialize qw/vp8_regular_quantize_b sse2/;
 | 
			
		||||
# TODO(johann) Update sse4 implementation and re-enable
 | 
			
		||||
#$vp8_regular_quantize_b_sse4_1=vp8_regular_quantize_b_sse4;
 | 
			
		||||
specialize qw/vp8_regular_quantize_b sse2 sse4_1/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/void vp8_fast_quantize_b/, "struct block *, struct blockd *";
 | 
			
		||||
specialize qw/vp8_fast_quantize_b sse2 ssse3 media neon_asm/;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,10 @@
 | 
			
		||||
        int cmp = (x[z] < boost) | (y[z] == 0); \
 | 
			
		||||
        zbin_boost_ptr++; \
 | 
			
		||||
        if (cmp) \
 | 
			
		||||
            goto select_eob_end_##i; \
 | 
			
		||||
            break; \
 | 
			
		||||
        qcoeff_ptr[z] = y[z]; \
 | 
			
		||||
        eob = i; \
 | 
			
		||||
        zbin_boost_ptr = b->zrun_zbin_boost; \
 | 
			
		||||
        select_eob_end_##i:; \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
void vp8_regular_quantize_b_sse2(BLOCK *b, BLOCKD *d)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,256 +0,0 @@
 | 
			
		||||
;
 | 
			
		||||
;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
 | 
			
		||||
;
 | 
			
		||||
;  Use of this source code is governed by a BSD-style license and patent
 | 
			
		||||
;  grant that can be found in the LICENSE file in the root of the source
 | 
			
		||||
;  tree. All contributing project authors may be found in the AUTHORS
 | 
			
		||||
;  file in the root of the source tree.
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%include "vpx_ports/x86_abi_support.asm"
 | 
			
		||||
%include "vp8_asm_enc_offsets.asm"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
; void vp8_regular_quantize_b_sse4 | arg
 | 
			
		||||
;  (BLOCK  *b,                     |  0
 | 
			
		||||
;   BLOCKD *d)                     |  1
 | 
			
		||||
 | 
			
		||||
global sym(vp8_regular_quantize_b_sse4) PRIVATE
 | 
			
		||||
sym(vp8_regular_quantize_b_sse4):
 | 
			
		||||
 | 
			
		||||
%if ABI_IS_32BIT
 | 
			
		||||
    push        rbp
 | 
			
		||||
    mov         rbp, rsp
 | 
			
		||||
    GET_GOT     rbx
 | 
			
		||||
    push        rdi
 | 
			
		||||
    push        rsi
 | 
			
		||||
 | 
			
		||||
    ALIGN_STACK 16, rax
 | 
			
		||||
    %define qcoeff      0 ; 32
 | 
			
		||||
    %define stack_size 32
 | 
			
		||||
    sub         rsp, stack_size
 | 
			
		||||
%else
 | 
			
		||||
  %if LIBVPX_YASM_WIN64
 | 
			
		||||
    SAVE_XMM 8, u
 | 
			
		||||
    push        rdi
 | 
			
		||||
    push        rsi
 | 
			
		||||
  %endif
 | 
			
		||||
%endif
 | 
			
		||||
    ; end prolog
 | 
			
		||||
 | 
			
		||||
%if ABI_IS_32BIT
 | 
			
		||||
    mov         rdi, arg(0)                 ; BLOCK *b
 | 
			
		||||
    mov         rsi, arg(1)                 ; BLOCKD *d
 | 
			
		||||
%else
 | 
			
		||||
  %if LIBVPX_YASM_WIN64
 | 
			
		||||
    mov         rdi, rcx                    ; BLOCK *b
 | 
			
		||||
    mov         rsi, rdx                    ; BLOCKD *d
 | 
			
		||||
  %else
 | 
			
		||||
    ;mov         rdi, rdi                    ; BLOCK *b
 | 
			
		||||
    ;mov         rsi, rsi                    ; BLOCKD *d
 | 
			
		||||
  %endif
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
    mov         rax, [rdi + vp8_block_coeff]
 | 
			
		||||
    mov         rcx, [rdi + vp8_block_zbin]
 | 
			
		||||
    mov         rdx, [rdi + vp8_block_round]
 | 
			
		||||
    movd        xmm7, [rdi + vp8_block_zbin_extra]
 | 
			
		||||
 | 
			
		||||
    ; z
 | 
			
		||||
    movdqa      xmm0, [rax]
 | 
			
		||||
    movdqa      xmm1, [rax + 16]
 | 
			
		||||
 | 
			
		||||
    ; duplicate zbin_oq_value
 | 
			
		||||
    pshuflw     xmm7, xmm7, 0
 | 
			
		||||
    punpcklwd   xmm7, xmm7
 | 
			
		||||
 | 
			
		||||
    movdqa      xmm2, xmm0
 | 
			
		||||
    movdqa      xmm3, xmm1
 | 
			
		||||
 | 
			
		||||
    ; sz
 | 
			
		||||
    psraw       xmm0, 15
 | 
			
		||||
    psraw       xmm1, 15
 | 
			
		||||
 | 
			
		||||
    ; (z ^ sz)
 | 
			
		||||
    pxor        xmm2, xmm0
 | 
			
		||||
    pxor        xmm3, xmm1
 | 
			
		||||
 | 
			
		||||
    ; x = abs(z)
 | 
			
		||||
    psubw       xmm2, xmm0
 | 
			
		||||
    psubw       xmm3, xmm1
 | 
			
		||||
 | 
			
		||||
    ; zbin
 | 
			
		||||
    movdqa      xmm4, [rcx]
 | 
			
		||||
    movdqa      xmm5, [rcx + 16]
 | 
			
		||||
 | 
			
		||||
    ; *zbin_ptr + zbin_oq_value
 | 
			
		||||
    paddw       xmm4, xmm7
 | 
			
		||||
    paddw       xmm5, xmm7
 | 
			
		||||
 | 
			
		||||
    movdqa      xmm6, xmm2
 | 
			
		||||
    movdqa      xmm7, xmm3
 | 
			
		||||
 | 
			
		||||
    ; x - (*zbin_ptr + zbin_oq_value)
 | 
			
		||||
    psubw       xmm6, xmm4
 | 
			
		||||
    psubw       xmm7, xmm5
 | 
			
		||||
 | 
			
		||||
    ; round
 | 
			
		||||
    movdqa      xmm4, [rdx]
 | 
			
		||||
    movdqa      xmm5, [rdx + 16]
 | 
			
		||||
 | 
			
		||||
    mov         rax, [rdi + vp8_block_quant_shift]
 | 
			
		||||
    mov         rcx, [rdi + vp8_block_quant]
 | 
			
		||||
    mov         rdx, [rdi + vp8_block_zrun_zbin_boost]
 | 
			
		||||
 | 
			
		||||
    ; x + round
 | 
			
		||||
    paddw       xmm2, xmm4
 | 
			
		||||
    paddw       xmm3, xmm5
 | 
			
		||||
 | 
			
		||||
    ; quant
 | 
			
		||||
    movdqa      xmm4, [rcx]
 | 
			
		||||
    movdqa      xmm5, [rcx + 16]
 | 
			
		||||
 | 
			
		||||
    ; y = x * quant_ptr >> 16
 | 
			
		||||
    pmulhw      xmm4, xmm2
 | 
			
		||||
    pmulhw      xmm5, xmm3
 | 
			
		||||
 | 
			
		||||
    ; y += x
 | 
			
		||||
    paddw       xmm2, xmm4
 | 
			
		||||
    paddw       xmm3, xmm5
 | 
			
		||||
 | 
			
		||||
    pxor        xmm4, xmm4
 | 
			
		||||
%if ABI_IS_32BIT
 | 
			
		||||
    movdqa      [rsp + qcoeff], xmm4
 | 
			
		||||
    movdqa      [rsp + qcoeff + 16], xmm4
 | 
			
		||||
%else
 | 
			
		||||
    pxor        xmm8, xmm8
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
    ; quant_shift
 | 
			
		||||
    movdqa      xmm5, [rax]
 | 
			
		||||
 | 
			
		||||
    ; zrun_zbin_boost
 | 
			
		||||
    mov         rax, rdx
 | 
			
		||||
 | 
			
		||||
%macro ZIGZAG_LOOP 5
 | 
			
		||||
    ; x
 | 
			
		||||
    pextrw      ecx, %4, %2
 | 
			
		||||
 | 
			
		||||
    ; if (x >= zbin)
 | 
			
		||||
    sub         cx, WORD PTR[rdx]           ; x - zbin
 | 
			
		||||
    lea         rdx, [rdx + 2]              ; zbin_boost_ptr++
 | 
			
		||||
    jl          .rq_zigzag_loop_%1          ; x < zbin
 | 
			
		||||
 | 
			
		||||
    pextrw      edi, %3, %2                 ; y
 | 
			
		||||
 | 
			
		||||
    ; downshift by quant_shift[rc]
 | 
			
		||||
    pextrb      ecx, xmm5, %1               ; quant_shift[rc]
 | 
			
		||||
    sar         edi, cl                     ; also sets Z bit
 | 
			
		||||
    je          .rq_zigzag_loop_%1          ; !y
 | 
			
		||||
%if ABI_IS_32BIT
 | 
			
		||||
    mov         WORD PTR[rsp + qcoeff + %1 *2], di
 | 
			
		||||
%else
 | 
			
		||||
    pinsrw      %5, edi, %2                 ; qcoeff[rc]
 | 
			
		||||
%endif
 | 
			
		||||
    mov         rdx, rax                    ; reset to b->zrun_zbin_boost
 | 
			
		||||
.rq_zigzag_loop_%1:
 | 
			
		||||
%endmacro
 | 
			
		||||
; in vp8_default_zig_zag1d order: see vp8/common/entropy.c
 | 
			
		||||
ZIGZAG_LOOP  0, 0, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  1, 1, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  4, 4, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  8, 0, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP  5, 5, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  2, 2, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  3, 3, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  6, 6, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP  9, 1, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP 12, 4, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP 13, 5, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP 10, 2, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP  7, 7, xmm2, xmm6, xmm4
 | 
			
		||||
ZIGZAG_LOOP 11, 3, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP 14, 6, xmm3, xmm7, xmm8
 | 
			
		||||
ZIGZAG_LOOP 15, 7, xmm3, xmm7, xmm8
 | 
			
		||||
 | 
			
		||||
    mov         rcx, [rsi + vp8_blockd_dequant]
 | 
			
		||||
    mov         rdi, [rsi + vp8_blockd_dqcoeff]
 | 
			
		||||
 | 
			
		||||
%if ABI_IS_32BIT
 | 
			
		||||
    movdqa      xmm4, [rsp + qcoeff]
 | 
			
		||||
    movdqa      xmm5, [rsp + qcoeff + 16]
 | 
			
		||||
%else
 | 
			
		||||
    %define     xmm5 xmm8
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
    ; y ^ sz
 | 
			
		||||
    pxor        xmm4, xmm0
 | 
			
		||||
    pxor        xmm5, xmm1
 | 
			
		||||
    ; x = (y ^ sz) - sz
 | 
			
		||||
    psubw       xmm4, xmm0
 | 
			
		||||
    psubw       xmm5, xmm1
 | 
			
		||||
 | 
			
		||||
    ; dequant
 | 
			
		||||
    movdqa      xmm0, [rcx]
 | 
			
		||||
    movdqa      xmm1, [rcx + 16]
 | 
			
		||||
 | 
			
		||||
    mov         rcx, [rsi + vp8_blockd_qcoeff]
 | 
			
		||||
 | 
			
		||||
    pmullw      xmm0, xmm4
 | 
			
		||||
    pmullw      xmm1, xmm5
 | 
			
		||||
 | 
			
		||||
    ; store qcoeff
 | 
			
		||||
    movdqa      [rcx], xmm4
 | 
			
		||||
    movdqa      [rcx + 16], xmm5
 | 
			
		||||
 | 
			
		||||
    ; store dqcoeff
 | 
			
		||||
    movdqa      [rdi], xmm0
 | 
			
		||||
    movdqa      [rdi + 16], xmm1
 | 
			
		||||
 | 
			
		||||
    mov         rcx, [rsi + vp8_blockd_eob]
 | 
			
		||||
 | 
			
		||||
    ; select the last value (in zig_zag order) for EOB
 | 
			
		||||
    pxor        xmm6, xmm6
 | 
			
		||||
    pcmpeqw     xmm4, xmm6
 | 
			
		||||
    pcmpeqw     xmm5, xmm6
 | 
			
		||||
 | 
			
		||||
    packsswb    xmm4, xmm5
 | 
			
		||||
    pshufb      xmm4, [GLOBAL(zig_zag1d)]
 | 
			
		||||
    pmovmskb    edx, xmm4
 | 
			
		||||
    xor         rdi, rdi
 | 
			
		||||
    mov         eax, -1
 | 
			
		||||
    xor         dx, ax
 | 
			
		||||
    bsr         eax, edx
 | 
			
		||||
    sub         edi, edx
 | 
			
		||||
    sar         edi, 31
 | 
			
		||||
    add         eax, 1
 | 
			
		||||
    and         eax, edi
 | 
			
		||||
 | 
			
		||||
    mov         BYTE PTR [rcx], al          ; store eob
 | 
			
		||||
 | 
			
		||||
    ; begin epilog
 | 
			
		||||
%if ABI_IS_32BIT
 | 
			
		||||
    add         rsp, stack_size
 | 
			
		||||
    pop         rsp
 | 
			
		||||
 | 
			
		||||
    pop         rsi
 | 
			
		||||
    pop         rdi
 | 
			
		||||
    RESTORE_GOT
 | 
			
		||||
    pop         rbp
 | 
			
		||||
%else
 | 
			
		||||
  %undef xmm5
 | 
			
		||||
  %if LIBVPX_YASM_WIN64
 | 
			
		||||
    pop         rsi
 | 
			
		||||
    pop         rdi
 | 
			
		||||
    RESTORE_XMM
 | 
			
		||||
  %endif
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
SECTION_RODATA
 | 
			
		||||
align 16
 | 
			
		||||
; vp8/common/entropy.c: vp8_default_zig_zag1d
 | 
			
		||||
zig_zag1d:
 | 
			
		||||
    db 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
 | 
			
		||||
							
								
								
									
										128
									
								
								vp8/encoder/x86/quantize_sse4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								vp8/encoder/x86/quantize_sse4.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <smmintrin.h> /* SSE4.1 */
 | 
			
		||||
 | 
			
		||||
#include "./vp8_rtcd.h"
 | 
			
		||||
#include "vp8/encoder/block.h"
 | 
			
		||||
#include "vp8/common/entropy.h" /* vp8_default_inv_zig_zag */
 | 
			
		||||
 | 
			
		||||
#define SELECT_EOB(i, z, x, y, q) \
 | 
			
		||||
    do { \
 | 
			
		||||
        short boost = *zbin_boost_ptr; \
 | 
			
		||||
        short x_z = _mm_extract_epi16(x, z); \
 | 
			
		||||
        short y_z = _mm_extract_epi16(y, z); \
 | 
			
		||||
        int cmp = (x_z < boost) | (y_z == 0); \
 | 
			
		||||
        zbin_boost_ptr++; \
 | 
			
		||||
        if (cmp) \
 | 
			
		||||
            break; \
 | 
			
		||||
        q = _mm_insert_epi16(q, y_z, z); \
 | 
			
		||||
        eob = i; \
 | 
			
		||||
        zbin_boost_ptr = b->zrun_zbin_boost; \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
void vp8_regular_quantize_b_sse4_1(BLOCK *b, BLOCKD *d) {
 | 
			
		||||
    char eob = 0;
 | 
			
		||||
    short *zbin_boost_ptr  = b->zrun_zbin_boost;
 | 
			
		||||
 | 
			
		||||
    __m128i sz0, x0, sz1, x1, y0, y1, x_minus_zbin0, x_minus_zbin1,
 | 
			
		||||
            dqcoeff0, dqcoeff1;
 | 
			
		||||
    __m128i quant_shift0 = _mm_load_si128((__m128i *)(b->quant_shift));
 | 
			
		||||
    __m128i quant_shift1 = _mm_load_si128((__m128i *)(b->quant_shift + 8));
 | 
			
		||||
    __m128i z0 = _mm_load_si128((__m128i *)(b->coeff));
 | 
			
		||||
    __m128i z1 = _mm_load_si128((__m128i *)(b->coeff+8));
 | 
			
		||||
    __m128i zbin_extra = _mm_cvtsi32_si128(b->zbin_extra);
 | 
			
		||||
    __m128i zbin0 = _mm_load_si128((__m128i *)(b->zbin));
 | 
			
		||||
    __m128i zbin1 = _mm_load_si128((__m128i *)(b->zbin + 8));
 | 
			
		||||
    __m128i round0 = _mm_load_si128((__m128i *)(b->round));
 | 
			
		||||
    __m128i round1 = _mm_load_si128((__m128i *)(b->round + 8));
 | 
			
		||||
    __m128i quant0 = _mm_load_si128((__m128i *)(b->quant));
 | 
			
		||||
    __m128i quant1 = _mm_load_si128((__m128i *)(b->quant + 8));
 | 
			
		||||
    __m128i dequant0 = _mm_load_si128((__m128i *)(d->dequant));
 | 
			
		||||
    __m128i dequant1 = _mm_load_si128((__m128i *)(d->dequant + 8));
 | 
			
		||||
    __m128i qcoeff0 = _mm_setzero_si128();
 | 
			
		||||
    __m128i qcoeff1 = _mm_setzero_si128();
 | 
			
		||||
 | 
			
		||||
    /* Duplicate to all lanes. */
 | 
			
		||||
    zbin_extra = _mm_shufflelo_epi16(zbin_extra, 0);
 | 
			
		||||
    zbin_extra = _mm_unpacklo_epi16(zbin_extra, zbin_extra);
 | 
			
		||||
 | 
			
		||||
    /* Sign of z: z >> 15 */
 | 
			
		||||
    sz0 = _mm_srai_epi16(z0, 15);
 | 
			
		||||
    sz1 = _mm_srai_epi16(z1, 15);
 | 
			
		||||
 | 
			
		||||
    /* x = abs(z): (z ^ sz) - sz */
 | 
			
		||||
    x0 = _mm_xor_si128(z0, sz0);
 | 
			
		||||
    x1 = _mm_xor_si128(z1, sz1);
 | 
			
		||||
    x0 = _mm_sub_epi16(x0, sz0);
 | 
			
		||||
    x1 = _mm_sub_epi16(x1, sz1);
 | 
			
		||||
 | 
			
		||||
    /* zbin[] + zbin_extra */
 | 
			
		||||
    zbin0 = _mm_add_epi16(zbin0, zbin_extra);
 | 
			
		||||
    zbin1 = _mm_add_epi16(zbin1, zbin_extra);
 | 
			
		||||
 | 
			
		||||
    /* In C x is compared to zbin where zbin = zbin[] + boost + extra. Rebalance
 | 
			
		||||
     * the equation because boost is the only value which can change:
 | 
			
		||||
     * x - (zbin[] + extra) >= boost */
 | 
			
		||||
    x_minus_zbin0 = _mm_sub_epi16(x0, zbin0);
 | 
			
		||||
    x_minus_zbin1 = _mm_sub_epi16(x1, zbin1);
 | 
			
		||||
 | 
			
		||||
    /* All the remaining calculations are valid whether they are done now with
 | 
			
		||||
     * simd or later inside the loop one at a time. */
 | 
			
		||||
    x0 = _mm_add_epi16(x0, round0);
 | 
			
		||||
    x1 = _mm_add_epi16(x1, round1);
 | 
			
		||||
 | 
			
		||||
    y0 = _mm_mulhi_epi16(x0, quant0);
 | 
			
		||||
    y1 = _mm_mulhi_epi16(x1, quant1);
 | 
			
		||||
 | 
			
		||||
    y0 = _mm_add_epi16(y0, x0);
 | 
			
		||||
    y1 = _mm_add_epi16(y1, x1);
 | 
			
		||||
 | 
			
		||||
    /* Instead of shifting each value independently we convert the scaling
 | 
			
		||||
     * factor with 1 << (16 - shift) so we can use multiply/return high half. */
 | 
			
		||||
    y0 = _mm_mulhi_epi16(y0, quant_shift0);
 | 
			
		||||
    y1 = _mm_mulhi_epi16(y1, quant_shift1);
 | 
			
		||||
 | 
			
		||||
    /* Return the sign: (y ^ sz) - sz */
 | 
			
		||||
    y0 = _mm_xor_si128(y0, sz0);
 | 
			
		||||
    y1 = _mm_xor_si128(y1, sz1);
 | 
			
		||||
    y0 = _mm_sub_epi16(y0, sz0);
 | 
			
		||||
    y1 = _mm_sub_epi16(y1, sz1);
 | 
			
		||||
 | 
			
		||||
    /* The loop gets unrolled anyway. Avoid the vp8_default_zig_zag1d lookup. */
 | 
			
		||||
    SELECT_EOB(1, 0, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(2, 1, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(3, 4, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(4, 0, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(5, 5, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(6, 2, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(7, 3, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(8, 6, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(9, 1, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(10, 4, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(11, 5, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(12, 2, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(13, 7, x_minus_zbin0, y0, qcoeff0);
 | 
			
		||||
    SELECT_EOB(14, 3, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(15, 6, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
    SELECT_EOB(16, 7, x_minus_zbin1, y1, qcoeff1);
 | 
			
		||||
 | 
			
		||||
    _mm_store_si128((__m128i *)(d->qcoeff), qcoeff0);
 | 
			
		||||
    _mm_store_si128((__m128i *)(d->qcoeff + 8), qcoeff1);
 | 
			
		||||
 | 
			
		||||
    dqcoeff0 = _mm_mullo_epi16(qcoeff0, dequant0);
 | 
			
		||||
    dqcoeff1 = _mm_mullo_epi16(qcoeff1, dequant1);
 | 
			
		||||
 | 
			
		||||
    _mm_store_si128((__m128i *)(d->dqcoeff), dqcoeff0);
 | 
			
		||||
    _mm_store_si128((__m128i *)(d->dqcoeff + 8), dqcoeff1);
 | 
			
		||||
 | 
			
		||||
    *d->eob = eob;
 | 
			
		||||
}
 | 
			
		||||
@@ -89,6 +89,7 @@ VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/dct_sse2.asm
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/fwalsh_sse2.asm
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/quantize_sse2.c
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/quantize_ssse3.c
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE4_1) += encoder/x86/quantize_sse4.c
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_TEMPORAL_DENOISING),yes)
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/denoising_sse2.c
 | 
			
		||||
@@ -97,7 +98,6 @@ endif
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/subtract_sse2.asm
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/temporal_filter_apply_sse2.asm
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp8_enc_stubs_sse2.c
 | 
			
		||||
VP8_CX_SRCS-$(HAVE_SSE4_1) += encoder/x86/quantize_sse4.asm
 | 
			
		||||
VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/quantize_mmx.asm
 | 
			
		||||
VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodeopt.asm
 | 
			
		||||
VP8_CX_SRCS-$(ARCH_X86_64) += encoder/x86/ssim_opt_x86_64.asm
 | 
			
		||||
 
 | 
			
		||||
@@ -25,12 +25,14 @@ void vp9_convolve8_neon(const uint8_t *src, ptrdiff_t src_stride,
 | 
			
		||||
  // Account for the vertical phase needing 3 lines prior and 4 lines post
 | 
			
		||||
  int intermediate_height = h + 7;
 | 
			
		||||
 | 
			
		||||
  if (x_step_q4 != 16 || y_step_q4 != 16)
 | 
			
		||||
    return vp9_convolve8_c(src, src_stride,
 | 
			
		||||
                           dst, dst_stride,
 | 
			
		||||
                           filter_x, x_step_q4,
 | 
			
		||||
                           filter_y, y_step_q4,
 | 
			
		||||
                           w, h);
 | 
			
		||||
  if (x_step_q4 != 16 || y_step_q4 != 16) {
 | 
			
		||||
    vp9_convolve8_c(src, src_stride,
 | 
			
		||||
                    dst, dst_stride,
 | 
			
		||||
                    filter_x, x_step_q4,
 | 
			
		||||
                    filter_y, y_step_q4,
 | 
			
		||||
                    w, h);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Filter starting 3 lines back. The neon implementation will ignore the
 | 
			
		||||
   * given height and filter a multiple of 4 lines. Since this goes in to
 | 
			
		||||
@@ -57,12 +59,14 @@ void vp9_convolve8_avg_neon(const uint8_t *src, ptrdiff_t src_stride,
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(8, uint8_t, temp, 64 * 72);
 | 
			
		||||
  int intermediate_height = h + 7;
 | 
			
		||||
 | 
			
		||||
  if (x_step_q4 != 16 || y_step_q4 != 16)
 | 
			
		||||
    return vp9_convolve8_avg_c(src, src_stride,
 | 
			
		||||
                               dst, dst_stride,
 | 
			
		||||
                               filter_x, x_step_q4,
 | 
			
		||||
                               filter_y, y_step_q4,
 | 
			
		||||
                               w, h);
 | 
			
		||||
  if (x_step_q4 != 16 || y_step_q4 != 16) {
 | 
			
		||||
    vp9_convolve8_avg_c(src, src_stride,
 | 
			
		||||
                        dst, dst_stride,
 | 
			
		||||
                        filter_x, x_step_q4,
 | 
			
		||||
                        filter_y, y_step_q4,
 | 
			
		||||
                        w, h);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* This implementation has the same issues as above. In addition, we only want
 | 
			
		||||
   * to average the values after both passes.
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "./vp9_rtcd.h"
 | 
			
		||||
#include "vpx/vpx_integer.h"
 | 
			
		||||
 | 
			
		||||
void vp9_lpf_horizontal_8_dual_neon(uint8_t *s, int p /* pitch */,
 | 
			
		||||
                                    const uint8_t *blimit0,
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,9 @@ void vp9_free_frame_buffers(VP9_COMMON *cm) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vp9_free_frame_buffer(&cm->post_proc_buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_free_context_buffers(VP9_COMMON *cm) {
 | 
			
		||||
  free_mi(cm);
 | 
			
		||||
 | 
			
		||||
  vpx_free(cm->last_frame_seg_map);
 | 
			
		||||
@@ -165,37 +167,55 @@ int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) {
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
  vp9_free_frame_buffers(cm);
 | 
			
		||||
  vp9_free_context_buffers(cm);
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_frame_bufs(VP9_COMMON *cm) {
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  cm->new_fb_idx = FRAME_BUFFERS - 1;
 | 
			
		||||
  cm->frame_bufs[cm->new_fb_idx].ref_count = 1;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < REF_FRAMES; ++i) {
 | 
			
		||||
    cm->ref_frame_map[i] = i;
 | 
			
		||||
    cm->frame_bufs[i].ref_count = 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) {
 | 
			
		||||
  const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
 | 
			
		||||
  const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
 | 
			
		||||
  int i;
 | 
			
		||||
  const int ss_x = cm->subsampling_x;
 | 
			
		||||
  const int ss_y = cm->subsampling_y;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  vp9_free_frame_buffers(cm);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < FRAME_BUFFERS; i++) {
 | 
			
		||||
  for (i = 0; i < FRAME_BUFFERS; ++i) {
 | 
			
		||||
    cm->frame_bufs[i].ref_count = 0;
 | 
			
		||||
    if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height,
 | 
			
		||||
                               ss_x, ss_y, VP9_ENC_BORDER_IN_PIXELS) < 0)
 | 
			
		||||
      goto fail;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cm->new_fb_idx = FRAME_BUFFERS - 1;
 | 
			
		||||
  cm->frame_bufs[cm->new_fb_idx].ref_count = 1;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < REF_FRAMES; i++) {
 | 
			
		||||
    cm->ref_frame_map[i] = i;
 | 
			
		||||
    cm->frame_bufs[i].ref_count = 1;
 | 
			
		||||
  }
 | 
			
		||||
  init_frame_bufs(cm);
 | 
			
		||||
 | 
			
		||||
  if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
 | 
			
		||||
                             VP9_ENC_BORDER_IN_PIXELS) < 0)
 | 
			
		||||
    goto fail;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
  vp9_free_frame_buffers(cm);
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
 | 
			
		||||
  const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
 | 
			
		||||
  const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
 | 
			
		||||
 | 
			
		||||
  vp9_free_context_buffers(cm);
 | 
			
		||||
 | 
			
		||||
  set_mb_mi(cm, aligned_width, aligned_height);
 | 
			
		||||
 | 
			
		||||
  if (alloc_mi(cm, cm->mi_stride * (cm->mi_rows + MI_BLOCK_SIZE)))
 | 
			
		||||
@@ -224,12 +244,13 @@ int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) {
 | 
			
		||||
  return 0;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
  vp9_free_frame_buffers(cm);
 | 
			
		||||
  vp9_free_context_buffers(cm);
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_remove_common(VP9_COMMON *cm) {
 | 
			
		||||
  vp9_free_frame_buffers(cm);
 | 
			
		||||
  vp9_free_context_buffers(cm);
 | 
			
		||||
  vp9_free_internal_frame_buffers(&cm->int_frame_buffers);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,12 @@ void vp9_remove_common(struct VP9Common *cm);
 | 
			
		||||
int vp9_resize_frame_buffers(struct VP9Common *cm, int width, int height);
 | 
			
		||||
 | 
			
		||||
int vp9_alloc_frame_buffers(struct VP9Common *cm, int width, int height);
 | 
			
		||||
int vp9_alloc_state_buffers(struct VP9Common *cm, int width, int height);
 | 
			
		||||
int vp9_alloc_context_buffers(struct VP9Common *cm, int width, int height);
 | 
			
		||||
 | 
			
		||||
void vp9_free_frame_buffers(struct VP9Common *cm);
 | 
			
		||||
void vp9_free_state_buffers(struct VP9Common *cm);
 | 
			
		||||
void vp9_free_context_buffers(struct VP9Common *cm);
 | 
			
		||||
 | 
			
		||||
void vp9_update_frame_size(struct VP9Common *cm);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,9 @@ extern "C" {
 | 
			
		||||
#define BLOCK_SIZE_GROUPS 4
 | 
			
		||||
#define SKIP_CONTEXTS 3
 | 
			
		||||
#define INTER_MODE_CONTEXTS 7
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
#define COPY_MODE_CONTEXTS 5
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Segment Feature Masks */
 | 
			
		||||
#define MAX_MV_REF_CANDIDATES 2
 | 
			
		||||
@@ -79,6 +82,16 @@ typedef enum {
 | 
			
		||||
  MB_MODE_COUNT
 | 
			
		||||
} PREDICTION_MODE;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NOREF,
 | 
			
		||||
  REF0,
 | 
			
		||||
  REF1,
 | 
			
		||||
  REF2,
 | 
			
		||||
  COPY_MODE_COUNT
 | 
			
		||||
} COPY_MODE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static INLINE int is_inter_mode(PREDICTION_MODE mode) {
 | 
			
		||||
  return mode >= NEARESTMV && mode <= NEWMV;
 | 
			
		||||
}
 | 
			
		||||
@@ -118,11 +131,86 @@ static INLINE int mi_width_log2(BLOCK_SIZE sb_type) {
 | 
			
		||||
  return mi_width_log2_lookup[sb_type];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static INLINE TX_SIZE bsize_to_tx_size(BLOCK_SIZE bsize) {
 | 
			
		||||
  const TX_SIZE tx_size_lookup[BLOCK_SIZES] = {
 | 
			
		||||
    TX_4X4, TX_4X4, TX_4X4,
 | 
			
		||||
    TX_8X8, TX_8X8, TX_8X8,
 | 
			
		||||
    TX_16X16, TX_16X16, TX_16X16,
 | 
			
		||||
    TX_32X32, TX_32X32, TX_32X32, TX_32X32};
 | 
			
		||||
  return tx_size_lookup[bsize];
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
#define MASK_BITS_SML   3
 | 
			
		||||
#define MASK_BITS_MED   4
 | 
			
		||||
#define MASK_BITS_BIG   5
 | 
			
		||||
#define MASK_NONE      -1
 | 
			
		||||
 | 
			
		||||
static inline int get_mask_bits(BLOCK_SIZE sb_type) {
 | 
			
		||||
  if (sb_type < BLOCK_8X8)
 | 
			
		||||
    return 0;
 | 
			
		||||
  if (sb_type <= BLOCK_8X8)
 | 
			
		||||
    return MASK_BITS_SML;
 | 
			
		||||
  else if (sb_type <= BLOCK_32X32)
 | 
			
		||||
    return MASK_BITS_MED;
 | 
			
		||||
  else
 | 
			
		||||
    return MASK_BITS_BIG;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
static INLINE TX_SIZE intra_size_log2_for_interintra(int bs) {
 | 
			
		||||
  switch (bs) {
 | 
			
		||||
    case 4:
 | 
			
		||||
      return TX_4X4;
 | 
			
		||||
      break;
 | 
			
		||||
    case 8:
 | 
			
		||||
      return TX_8X8;
 | 
			
		||||
      break;
 | 
			
		||||
    case 16:
 | 
			
		||||
      return TX_16X16;
 | 
			
		||||
      break;
 | 
			
		||||
    case 32:
 | 
			
		||||
      return TX_32X32;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return TX_32X32;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INLINE int is_interintra_allowed(BLOCK_SIZE sb_type) {
 | 
			
		||||
  return ((sb_type >= BLOCK_8X8) && (sb_type < BLOCK_64X64));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
#define MASK_BITS_SML_INTERINTRA   3
 | 
			
		||||
#define MASK_BITS_MED_INTERINTRA   4
 | 
			
		||||
#define MASK_BITS_BIG_INTERINTRA   5
 | 
			
		||||
#define MASK_NONE_INTERINTRA      -1
 | 
			
		||||
static INLINE int get_mask_bits_interintra(BLOCK_SIZE sb_type) {
 | 
			
		||||
  if (sb_type == BLOCK_4X4)
 | 
			
		||||
     return 0;
 | 
			
		||||
  if (sb_type <= BLOCK_8X8)
 | 
			
		||||
    return MASK_BITS_SML_INTERINTRA;
 | 
			
		||||
  else if (sb_type <= BLOCK_32X32)
 | 
			
		||||
    return MASK_BITS_MED_INTERINTRA;
 | 
			
		||||
  else
 | 
			
		||||
    return MASK_BITS_BIG_INTERINTRA;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// This structure now relates to 8x8 block regions.
 | 
			
		||||
typedef struct {
 | 
			
		||||
  // Common for both INTER and INTRA blocks
 | 
			
		||||
  BLOCK_SIZE sb_type;
 | 
			
		||||
  PREDICTION_MODE mode;
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  int filterbit, uv_filterbit;
 | 
			
		||||
#endif
 | 
			
		||||
  TX_SIZE tx_size;
 | 
			
		||||
  uint8_t skip;
 | 
			
		||||
  uint8_t segment_id;
 | 
			
		||||
@@ -137,10 +225,34 @@ typedef struct {
 | 
			
		||||
  int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
 | 
			
		||||
  uint8_t mode_context[MAX_REF_FRAMES];
 | 
			
		||||
  INTERP_FILTER interp_filter;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  EXT_TX_TYPE ext_txfrm;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  int use_masked_interinter;
 | 
			
		||||
  int mask_index;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  PREDICTION_MODE interintra_mode, interintra_uv_mode;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  int interintra_mask_index;
 | 
			
		||||
  int interintra_uv_mask_index;
 | 
			
		||||
  int use_masked_interintra;
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  COPY_MODE copy_mode;
 | 
			
		||||
  int inter_ref_count;
 | 
			
		||||
#endif
 | 
			
		||||
} MB_MODE_INFO;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MB_MODE_INFO mbmi;
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  int b_filter_info[4];
 | 
			
		||||
#endif
 | 
			
		||||
  b_mode_info bmi[4];
 | 
			
		||||
} MODE_INFO;
 | 
			
		||||
 | 
			
		||||
@@ -149,6 +261,16 @@ static INLINE PREDICTION_MODE get_y_mode(const MODE_INFO *mi, int block) {
 | 
			
		||||
                                      : mi->mbmi.mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
static INLINE int is_filter_allowed(PREDICTION_MODE mode) {
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INLINE int is_filter_enabled(TX_SIZE txsize) {
 | 
			
		||||
  return (txsize <= TX_32X32);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static INLINE int is_inter_block(const MB_MODE_INFO *mbmi) {
 | 
			
		||||
  return mbmi->ref_frame[0] > INTRA_FRAME;
 | 
			
		||||
}
 | 
			
		||||
@@ -240,6 +362,13 @@ typedef struct macroblockd {
 | 
			
		||||
  PARTITION_CONTEXT left_seg_context[8];
 | 
			
		||||
} MACROBLOCKD;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static INLINE int supertx_enabled(const MB_MODE_INFO *mbmi) {
 | 
			
		||||
  return mbmi->tx_size >
 | 
			
		||||
         MIN(b_width_log2(mbmi->sb_type), b_height_log2(mbmi->sb_type));
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
 | 
			
		||||
                                     PARTITION_TYPE partition) {
 | 
			
		||||
  const BLOCK_SIZE subsize = subsize_lookup[partition][bsize];
 | 
			
		||||
@@ -253,8 +382,20 @@ static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type,
 | 
			
		||||
                                  const MACROBLOCKD *xd) {
 | 
			
		||||
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
 | 
			
		||||
#if !CONFIG_EXT_TX
 | 
			
		||||
  if (plane_type != PLANE_TYPE_Y || is_inter_block(mbmi))
 | 
			
		||||
    return DCT_DCT;
 | 
			
		||||
#else
 | 
			
		||||
  if (plane_type != PLANE_TYPE_Y)
 | 
			
		||||
      return DCT_DCT;
 | 
			
		||||
 | 
			
		||||
  if (is_inter_block(mbmi)) {
 | 
			
		||||
    if (mbmi->ext_txfrm == NORM || mbmi->tx_size >= TX_32X32)
 | 
			
		||||
      return DCT_DCT;
 | 
			
		||||
    else
 | 
			
		||||
      return ADST_ADST;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  return intra_mode_to_tx_type_lookup[mbmi->mode];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -262,8 +403,20 @@ static INLINE TX_TYPE get_tx_type_4x4(PLANE_TYPE plane_type,
 | 
			
		||||
                                      const MACROBLOCKD *xd, int ib) {
 | 
			
		||||
  const MODE_INFO *const mi = xd->mi[0];
 | 
			
		||||
 | 
			
		||||
#if !CONFIG_EXT_TX
 | 
			
		||||
  if (plane_type != PLANE_TYPE_Y || xd->lossless || is_inter_block(&mi->mbmi))
 | 
			
		||||
    return DCT_DCT;
 | 
			
		||||
#else
 | 
			
		||||
  if (plane_type != PLANE_TYPE_Y || xd->lossless)
 | 
			
		||||
      return DCT_DCT;
 | 
			
		||||
 | 
			
		||||
  if (is_inter_block(&mi->mbmi)) {
 | 
			
		||||
    if (mi->mbmi.ext_txfrm == NORM)
 | 
			
		||||
      return DCT_DCT;
 | 
			
		||||
    else
 | 
			
		||||
      return ADST_ADST;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  return intra_mode_to_tx_type_lookup[get_y_mode(mi, ib)];
 | 
			
		||||
}
 | 
			
		||||
@@ -281,7 +434,15 @@ static INLINE TX_SIZE get_uv_tx_size_impl(TX_SIZE y_tx_size, BLOCK_SIZE bsize) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INLINE TX_SIZE get_uv_tx_size(const MB_MODE_INFO *mbmi) {
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (!supertx_enabled(mbmi)) {
 | 
			
		||||
#endif
 | 
			
		||||
  return get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  } else {
 | 
			
		||||
    return uvsupertx_size_lookup[mbmi->tx_size];
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INLINE BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
 | 
			
		||||
 
 | 
			
		||||
@@ -133,6 +133,15 @@ const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2] = {
 | 
			
		||||
  {{BLOCK_64X64, BLOCK_64X32},   {BLOCK_32X64,   BLOCK_32X32}},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
const TX_SIZE uvsupertx_size_lookup[TX_SIZES] = {
 | 
			
		||||
    TX_4X4,
 | 
			
		||||
    TX_4X4,
 | 
			
		||||
    TX_8X8,
 | 
			
		||||
    TX_16X16
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Generates 4 bit field in which each bit set to 1 represents
 | 
			
		||||
// a blocksize partition  1111 means we split 64x64, 32x32, 16x16
 | 
			
		||||
// and 8x8.  1000 means we just split the 64x64 to 32x32
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,9 @@ extern const BLOCK_SIZE subsize_lookup[PARTITION_TYPES][BLOCK_SIZES];
 | 
			
		||||
extern const TX_SIZE max_txsize_lookup[BLOCK_SIZES];
 | 
			
		||||
extern const TX_SIZE tx_mode_to_biggest_tx_size[TX_MODES];
 | 
			
		||||
extern const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2];
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
extern const TX_SIZE uvsupertx_size_lookup[TX_SIZES];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
 
 | 
			
		||||
@@ -117,17 +117,25 @@ static void convolve(const uint8_t *src, ptrdiff_t src_stride,
 | 
			
		||||
                     const InterpKernel *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];
 | 
			
		||||
  // Note: Fixed size intermediate buffer, temp, places limits on parameters.
 | 
			
		||||
  // 2d filtering proceeds in 2 steps:
 | 
			
		||||
  //   (1) Interpolate horizontally into an intermediate buffer, temp.
 | 
			
		||||
  //   (2) Interpolate temp vertically to derive the sub-pixel result.
 | 
			
		||||
  // Deriving the maximum number of rows in the temp buffer (135):
 | 
			
		||||
  // --Smallest scaling factor is x1/2 ==> y_step_q4 = 32 (Normative).
 | 
			
		||||
  // --Largest block size is 64x64 pixels.
 | 
			
		||||
  // --64 rows in the downscaled frame span a distance of (64 - 1) * 32 in the
 | 
			
		||||
  //   original frame (in 1/16th pixel units).
 | 
			
		||||
  // --Must round-up because block may be located at sub-pixel position.
 | 
			
		||||
  // --Require an additional SUBPEL_TAPS rows for the 8-tap filter tails.
 | 
			
		||||
  // --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
 | 
			
		||||
  uint8_t temp[135 * 64];
 | 
			
		||||
  int intermediate_height = (((h - 1) * y_step_q4 + 15) >> 4) + SUBPEL_TAPS;
 | 
			
		||||
 | 
			
		||||
  assert(w <= 64);
 | 
			
		||||
  assert(h <= 64);
 | 
			
		||||
  assert(y_step_q4 <= 80);
 | 
			
		||||
  assert(x_step_q4 <= 80);
 | 
			
		||||
  assert(y_step_q4 <= 32);
 | 
			
		||||
  assert(x_step_q4 <= 32);
 | 
			
		||||
 | 
			
		||||
  if (intermediate_height < h)
 | 
			
		||||
    intermediate_height = h;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,84 @@
 | 
			
		||||
#include "vp9/common/vp9_onyxc_int.h"
 | 
			
		||||
#include "vp9/common/vp9_seg_common.h"
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
static const vp9_prob default_masked_interinter_prob[BLOCK_SIZES] = {
 | 
			
		||||
    192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
static const vp9_prob default_interintra_prob[BLOCK_SIZES] = {
 | 
			
		||||
  192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
 | 
			
		||||
};
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
static const vp9_prob default_masked_interintra_prob[BLOCK_SIZES] = {
 | 
			
		||||
  192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
static const vp9_prob default_filterintra_prob[TX_SIZES][INTRA_MODES] = {
 | 
			
		||||
  // DC     V      H    D45   D135   D117   D153   D207    D63     TM
 | 
			
		||||
  {153,   171,   147,   150,   129,   101,   100,   153,   132,   111},
 | 
			
		||||
  {171,   173,   185,   131,    70,    53,    70,   148,   127,   114},
 | 
			
		||||
  {175,   203,   213,    86,    45,    71,    41,   150,   125,   154},
 | 
			
		||||
  {235,   230,   154,   202,   154,   205,    37,   128,     0,   202}
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
static const vp9_prob default_ext_tx_prob = 178;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static const vp9_prob default_supertx_prob[TX_SIZES] = {
 | 
			
		||||
  255, 160, 160, 160
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const vp9_prob default_supertxsplit_prob[TX_SIZES] = {
 | 
			
		||||
  255, 200, 200, 200
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
static const vp9_prob default_copy_noref_prob[COPY_MODE_CONTEXTS]
 | 
			
		||||
                                             [BLOCK_SIZES] = {
 | 
			
		||||
  {255, 255, 255,  82, 148, 182,  65, 193, 158,  70, 138, 101,  23},
 | 
			
		||||
  {255, 255, 255, 118, 153, 161, 123, 169, 157,  82, 101, 123,  88},
 | 
			
		||||
  {255, 255, 255, 130, 178, 226, 194, 196, 174, 173, 135, 144, 141},
 | 
			
		||||
  {255, 255, 255, 178, 218, 225, 197, 230, 222, 215, 220, 220, 220},
 | 
			
		||||
  {255, 255, 255, 243, 248, 241, 233, 249, 249, 249, 249, 249, 249}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const vp9_prob default_copy_mode_probs_l2[COPY_MODE_CONTEXTS][1] = {
 | 
			
		||||
  {207},
 | 
			
		||||
  {135},
 | 
			
		||||
  {141},
 | 
			
		||||
  {189},
 | 
			
		||||
  {209}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)] = {
 | 
			
		||||
  -(REF0 - REF0), -(REF1 - REF0)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const vp9_prob default_copy_mode_probs[COPY_MODE_CONTEXTS]
 | 
			
		||||
                                             [COPY_MODE_COUNT - 2] = {
 | 
			
		||||
  {130, 159},
 | 
			
		||||
  {126, 176},
 | 
			
		||||
  {120, 150},
 | 
			
		||||
  {158, 183},
 | 
			
		||||
  {149, 125}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)] = {
 | 
			
		||||
  -(REF0 - REF0),  2,
 | 
			
		||||
  -(REF1 - REF0),  -(REF2 - REF0)
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const vp9_prob vp9_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1] = {
 | 
			
		||||
  {  // above = dc
 | 
			
		||||
    { 137,  30,  42, 148, 151, 207,  70,  52,  91 },  // left = dc
 | 
			
		||||
@@ -245,7 +323,11 @@ const vp9_tree_index vp9_partition_tree[TREE_SIZE(PARTITION_TYPES)] = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const vp9_prob default_intra_inter_p[INTRA_INTER_CONTEXTS] = {
 | 
			
		||||
#if !CONFIG_COPY_CODING
 | 
			
		||||
  9, 102, 187, 225
 | 
			
		||||
#else
 | 
			
		||||
  35, 112, 187, 225
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const vp9_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
 | 
			
		||||
@@ -326,6 +408,30 @@ void vp9_init_mode_probs(FRAME_CONTEXT *fc) {
 | 
			
		||||
  fc->tx_probs = default_tx_probs;
 | 
			
		||||
  vp9_copy(fc->skip_probs, default_skip_probs);
 | 
			
		||||
  vp9_copy(fc->inter_mode_probs, default_inter_mode_probs);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  vp9_copy(fc->masked_interinter_prob, default_masked_interinter_prob);
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  vp9_copy(fc->interintra_prob, default_interintra_prob);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  vp9_copy(fc->masked_interintra_prob, default_masked_interintra_prob);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  vp9_copy(fc->filterintra_prob, default_filterintra_prob);
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  fc->ext_tx_prob = default_ext_tx_prob;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  vp9_copy(fc->supertx_prob, default_supertx_prob);
 | 
			
		||||
  vp9_copy(fc->supertxsplit_prob, default_supertxsplit_prob);
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  vp9_copy(fc->copy_noref_prob, default_copy_noref_prob);
 | 
			
		||||
  vp9_copy(fc->copy_mode_probs_l2, default_copy_mode_probs_l2);
 | 
			
		||||
  vp9_copy(fc->copy_mode_probs, default_copy_mode_probs);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const vp9_tree_index vp9_switchable_interp_tree
 | 
			
		||||
@@ -416,6 +522,73 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) {
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < SKIP_CONTEXTS; ++i)
 | 
			
		||||
    fc->skip_probs[i] = adapt_prob(pre_fc->skip_probs[i], counts->skip[i]);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  if (cm->use_masked_interinter) {
 | 
			
		||||
    for (i = 0; i < BLOCK_SIZES; ++i) {
 | 
			
		||||
      if (get_mask_bits(i))
 | 
			
		||||
        fc->masked_interinter_prob[i] = adapt_prob
 | 
			
		||||
                                      (pre_fc->masked_interinter_prob[i],
 | 
			
		||||
                                       counts->masked_interinter[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  if (cm->use_interintra) {
 | 
			
		||||
    for (i = 0; i < BLOCK_SIZES; ++i) {
 | 
			
		||||
      if (is_interintra_allowed(i))
 | 
			
		||||
        fc->interintra_prob[i] = adapt_prob(pre_fc->interintra_prob[i],
 | 
			
		||||
                                            counts->interintra[i]);
 | 
			
		||||
    }
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
    if (cm->use_masked_interintra) {
 | 
			
		||||
      for (i = 0; i < BLOCK_SIZES; ++i) {
 | 
			
		||||
        if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
 | 
			
		||||
          fc->masked_interintra_prob[i] = adapt_prob(
 | 
			
		||||
                                          pre_fc->masked_interintra_prob[i],
 | 
			
		||||
                                          counts->masked_interintra[i]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  for (i = 0; i < TX_SIZES; ++i)
 | 
			
		||||
    for (j = 0; j < INTRA_MODES; ++j)
 | 
			
		||||
      fc->filterintra_prob[i][j] = adapt_prob(pre_fc->filterintra_prob[i][j],
 | 
			
		||||
                                   counts->filterintra[i][j]);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  fc->ext_tx_prob = adapt_prob(pre_fc->ext_tx_prob, counts->ext_tx);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  for (i = 1; i < TX_SIZES; ++i) {
 | 
			
		||||
    fc->supertx_prob[i] = adapt_prob(pre_fc->supertx_prob[i],
 | 
			
		||||
                                     counts->supertx[i]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (i = 1; i < TX_SIZES; ++i) {
 | 
			
		||||
    fc->supertxsplit_prob[i] = adapt_prob(pre_fc->supertxsplit_prob[i],
 | 
			
		||||
                                          counts->supertxsplit[i]);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  for (i = 0; i < COPY_MODE_CONTEXTS; i++) {
 | 
			
		||||
    for (j = BLOCK_8X8; j < BLOCK_SIZES; j++) {
 | 
			
		||||
      fc->copy_noref_prob[i][j] =
 | 
			
		||||
          adapt_prob(pre_fc->copy_noref_prob[i][j], counts->copy_noref[i][j]);
 | 
			
		||||
    }
 | 
			
		||||
    adapt_probs(vp9_copy_mode_tree_l2, pre_fc->copy_mode_probs_l2[i],
 | 
			
		||||
                counts->copy_mode_l2[i], fc->copy_mode_probs_l2[i]);
 | 
			
		||||
    adapt_probs(vp9_copy_mode_tree, pre_fc->copy_mode_probs[i],
 | 
			
		||||
                counts->copy_mode[i], fc->copy_mode_probs[i]);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_default_lf_deltas(struct loopfilter *lf) {
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,30 @@ typedef struct frame_contexts {
 | 
			
		||||
  struct tx_probs tx_probs;
 | 
			
		||||
  vp9_prob skip_probs[SKIP_CONTEXTS];
 | 
			
		||||
  nmv_context nmvc;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  vp9_prob masked_interinter_prob[BLOCK_SIZES];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  vp9_prob interintra_prob[BLOCK_SIZES];
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  vp9_prob masked_interintra_prob[BLOCK_SIZES];
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  vp9_prob filterintra_prob[TX_SIZES][INTRA_MODES];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  vp9_prob ext_tx_prob;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  vp9_prob supertx_prob[TX_SIZES];
 | 
			
		||||
  vp9_prob supertxsplit_prob[TX_SIZES];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  vp9_prob copy_noref_prob[COPY_MODE_CONTEXTS][BLOCK_SIZES];
 | 
			
		||||
  vp9_prob copy_mode_probs_l2[COPY_MODE_CONTEXTS][1];
 | 
			
		||||
  vp9_prob copy_mode_probs[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 2];
 | 
			
		||||
#endif
 | 
			
		||||
} FRAME_CONTEXT;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
@@ -71,6 +95,31 @@ typedef struct {
 | 
			
		||||
  struct tx_counts tx;
 | 
			
		||||
  unsigned int skip[SKIP_CONTEXTS][2];
 | 
			
		||||
  nmv_context_counts mv;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  unsigned int masked_interinter[BLOCK_SIZES][2];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  unsigned int interintra[BLOCK_SIZES][2];
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  unsigned int masked_interintra[BLOCK_SIZES][2];
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  unsigned int filterintra[TX_SIZES][INTRA_MODES][2];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  unsigned int ext_tx[2];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  unsigned int supertx[TX_SIZES][2];
 | 
			
		||||
  unsigned int supertxsplit[TX_SIZES][2];
 | 
			
		||||
  unsigned int supertx_size[BLOCK_SIZES];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  unsigned int copy_noref[COPY_MODE_CONTEXTS][BLOCK_SIZES][2];
 | 
			
		||||
  unsigned int copy_mode_l2[COPY_MODE_CONTEXTS][2];
 | 
			
		||||
  unsigned int copy_mode[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 1];
 | 
			
		||||
#endif
 | 
			
		||||
} FRAME_COUNTS;
 | 
			
		||||
 | 
			
		||||
extern const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
 | 
			
		||||
@@ -83,6 +132,10 @@ extern const vp9_tree_index vp9_inter_mode_tree[TREE_SIZE(INTER_MODES)];
 | 
			
		||||
extern const vp9_tree_index vp9_partition_tree[TREE_SIZE(PARTITION_TYPES)];
 | 
			
		||||
extern const vp9_tree_index vp9_switchable_interp_tree
 | 
			
		||||
                                [TREE_SIZE(SWITCHABLE_FILTERS)];
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
extern const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)];
 | 
			
		||||
extern const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_setup_past_independence(struct VP9Common *cm);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -100,6 +100,14 @@ typedef enum {
 | 
			
		||||
  TX_TYPES = 4
 | 
			
		||||
} TX_TYPE;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NORM   = 0,
 | 
			
		||||
  ALT = 1,
 | 
			
		||||
  EXT_TX_TYPES = 2
 | 
			
		||||
} EXT_TX_TYPE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  UNKNOWN    = 0,
 | 
			
		||||
  BT_601     = 1,  // YUV
 | 
			
		||||
 
 | 
			
		||||
@@ -206,6 +206,13 @@ static const int mode_lf_lut[MB_MODE_COUNT] = {
 | 
			
		||||
  1, 1, 0, 1                     // INTER_MODES (ZEROMV == 0)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static int supertx_enabled_lpf(const MB_MODE_INFO *mbmi) {
 | 
			
		||||
  return mbmi->tx_size >
 | 
			
		||||
         MIN(b_width_log2(mbmi->sb_type), b_height_log2(mbmi->sb_type));
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
 | 
			
		||||
  int lvl;
 | 
			
		||||
 | 
			
		||||
@@ -572,6 +579,85 @@ static void build_masks(const loop_filter_info_n *const lfi_n,
 | 
			
		||||
    *int_4x4_uv |= (size_mask_uv[block_size] & 0xffff) << shift_uv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static void build_masks_supertx(const loop_filter_info_n *const lfi_n,
 | 
			
		||||
                                const MODE_INFO *mi, const int shift_y,
 | 
			
		||||
                                const int shift_uv,
 | 
			
		||||
                                LOOP_FILTER_MASK *lfm) {
 | 
			
		||||
  const MB_MODE_INFO *mbmi = &mi->mbmi;
 | 
			
		||||
  const TX_SIZE tx_size_y = mbmi->tx_size;
 | 
			
		||||
  const TX_SIZE tx_size_uv = get_uv_tx_size(mbmi);
 | 
			
		||||
  const BLOCK_SIZE block_size = 3 * (int)tx_size_y;
 | 
			
		||||
  const int filter_level = get_filter_level(lfi_n, mbmi);
 | 
			
		||||
  uint64_t *const left_y = &lfm->left_y[tx_size_y];
 | 
			
		||||
  uint64_t *const above_y = &lfm->above_y[tx_size_y];
 | 
			
		||||
  uint64_t *const int_4x4_y = &lfm->int_4x4_y;
 | 
			
		||||
  uint16_t *const left_uv = &lfm->left_uv[tx_size_uv];
 | 
			
		||||
  uint16_t *const above_uv = &lfm->above_uv[tx_size_uv];
 | 
			
		||||
  uint16_t *const int_4x4_uv = &lfm->int_4x4_uv;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  // If filter level is 0 we don't loop filter.
 | 
			
		||||
  if (!filter_level) {
 | 
			
		||||
    return;
 | 
			
		||||
  } else {
 | 
			
		||||
    const int w = num_8x8_blocks_wide_lookup[block_size];
 | 
			
		||||
    const int h = num_8x8_blocks_high_lookup[block_size];
 | 
			
		||||
    int index = shift_y;
 | 
			
		||||
    for (i = 0; i < h; i++) {
 | 
			
		||||
      vpx_memset(&lfm->lfl_y[index], filter_level, w);
 | 
			
		||||
      index += 8;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // These set 1 in the current block size for the block size edges.
 | 
			
		||||
  // For instance if the block size is 32x16,   we'll set :
 | 
			
		||||
  //    above =   1111
 | 
			
		||||
  //              0000
 | 
			
		||||
  //    and
 | 
			
		||||
  //    left  =   1000
 | 
			
		||||
  //          =   1000
 | 
			
		||||
  // NOTE : In this example the low bit is left most ( 1000 ) is stored as
 | 
			
		||||
  //        1,  not 8...
 | 
			
		||||
  //
 | 
			
		||||
  // U and v set things on a 16 bit scale.
 | 
			
		||||
  //
 | 
			
		||||
  *above_y |= above_prediction_mask[block_size] << shift_y;
 | 
			
		||||
  *above_uv |= above_prediction_mask_uv[block_size] << shift_uv;
 | 
			
		||||
  *left_y |= left_prediction_mask[block_size] << shift_y;
 | 
			
		||||
  *left_uv |= left_prediction_mask_uv[block_size] << shift_uv;
 | 
			
		||||
 | 
			
		||||
  // If the block has no coefficients and is not intra we skip applying
 | 
			
		||||
  // the loop filter on block edges.
 | 
			
		||||
  if (mbmi->skip && is_inter_block(mbmi))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  // Here we are adding a mask for the transform size.  The transform
 | 
			
		||||
  // size mask is set to be correct for a 64x64 prediction block size. We
 | 
			
		||||
  // mask to match the size of the block we are working on and then shift it
 | 
			
		||||
  // into place..
 | 
			
		||||
  *above_y |= (size_mask[block_size] &
 | 
			
		||||
               above_64x64_txform_mask[tx_size_y]) << shift_y;
 | 
			
		||||
  *above_uv |= (size_mask_uv[block_size] &
 | 
			
		||||
                above_64x64_txform_mask_uv[tx_size_uv]) << shift_uv;
 | 
			
		||||
 | 
			
		||||
  *left_y |= (size_mask[block_size] &
 | 
			
		||||
              left_64x64_txform_mask[tx_size_y]) << shift_y;
 | 
			
		||||
  *left_uv |= (size_mask_uv[block_size] &
 | 
			
		||||
               left_64x64_txform_mask_uv[tx_size_uv]) << shift_uv;
 | 
			
		||||
 | 
			
		||||
  // Here we are trying to determine what to do with the internal 4x4 block
 | 
			
		||||
  // boundaries.  These differ from the 4x4 boundaries on the outside edge of
 | 
			
		||||
  // an 8x8 in that the internal ones can be skipped and don't depend on
 | 
			
		||||
  // the prediction block size.
 | 
			
		||||
  if (tx_size_y == TX_4X4)
 | 
			
		||||
    *int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffff) << shift_y;
 | 
			
		||||
 | 
			
		||||
  if (tx_size_uv == TX_4X4)
 | 
			
		||||
    *int_4x4_uv |= (size_mask_uv[block_size] & 0xffff) << shift_uv;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// This function does the same thing as the one above with the exception that
 | 
			
		||||
// it only affects the y masks.   It exists because for blocks < 16x16 in size,
 | 
			
		||||
// we only update u and v masks on the first block.
 | 
			
		||||
@@ -615,6 +701,48 @@ static void build_y_mask(const loop_filter_info_n *const lfi_n,
 | 
			
		||||
    *int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffff) << shift_y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static void build_y_mask_supertx(const loop_filter_info_n *const lfi_n,
 | 
			
		||||
                                 const MODE_INFO *mi, const int shift_y,
 | 
			
		||||
                                 LOOP_FILTER_MASK *lfm) {
 | 
			
		||||
  const MB_MODE_INFO *mbmi = &mi->mbmi;
 | 
			
		||||
  const TX_SIZE tx_size_y = mbmi->tx_size;
 | 
			
		||||
  const BLOCK_SIZE block_size = 3 * (int)tx_size_y;
 | 
			
		||||
  const int filter_level = get_filter_level(lfi_n, mbmi);
 | 
			
		||||
  uint64_t *const left_y = &lfm->left_y[tx_size_y];
 | 
			
		||||
  uint64_t *const above_y = &lfm->above_y[tx_size_y];
 | 
			
		||||
  uint64_t *const int_4x4_y = &lfm->int_4x4_y;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (!filter_level) {
 | 
			
		||||
    return;
 | 
			
		||||
  } else {
 | 
			
		||||
    const int w = num_8x8_blocks_wide_lookup[block_size];
 | 
			
		||||
    const int h = num_8x8_blocks_high_lookup[block_size];
 | 
			
		||||
    int index = shift_y;
 | 
			
		||||
    for (i = 0; i < h; i++) {
 | 
			
		||||
      vpx_memset(&lfm->lfl_y[index], filter_level, w);
 | 
			
		||||
      index += 8;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *above_y |= above_prediction_mask[block_size] << shift_y;
 | 
			
		||||
  *left_y |= left_prediction_mask[block_size] << shift_y;
 | 
			
		||||
 | 
			
		||||
  if (mbmi->skip && is_inter_block(mbmi))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  *above_y |= (size_mask[block_size] &
 | 
			
		||||
               above_64x64_txform_mask[tx_size_y]) << shift_y;
 | 
			
		||||
 | 
			
		||||
  *left_y |= (size_mask[block_size] &
 | 
			
		||||
              left_64x64_txform_mask[tx_size_y]) << shift_y;
 | 
			
		||||
 | 
			
		||||
  if (tx_size_y == TX_4X4)
 | 
			
		||||
    *int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffff) << shift_y;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// This function sets up the bit masks for the entire 64x64 region represented
 | 
			
		||||
// by mi_row, mi_col.
 | 
			
		||||
// TODO(JBB): This function only works for yv12.
 | 
			
		||||
@@ -650,6 +778,9 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
 | 
			
		||||
                        cm->mi_rows - mi_row : MI_BLOCK_SIZE);
 | 
			
		||||
  const int max_cols = (mi_col + MI_BLOCK_SIZE > cm->mi_cols ?
 | 
			
		||||
                        cm->mi_cols - mi_col : MI_BLOCK_SIZE);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  int supertx;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  vp9_zero(*lfm);
 | 
			
		||||
 | 
			
		||||
@@ -687,20 +818,43 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
 | 
			
		||||
            build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
            break;
 | 
			
		||||
          case BLOCK_32X16:
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
            supertx = supertx_enabled_lpf(&mip[0]->mbmi);
 | 
			
		||||
            if (!supertx) {
 | 
			
		||||
#endif
 | 
			
		||||
            build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
            if (mi_32_row_offset + 2 >= max_rows)
 | 
			
		||||
              continue;
 | 
			
		||||
            mip2 = mip + mode_info_stride * 2;
 | 
			
		||||
            build_masks(lfi_n, mip2[0], shift_y + 16, shift_uv + 4, lfm);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
            } else {
 | 
			
		||||
              build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            break;
 | 
			
		||||
          case BLOCK_16X32:
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
            supertx = supertx_enabled_lpf(&mip[0]->mbmi);
 | 
			
		||||
            if (!supertx) {
 | 
			
		||||
#endif
 | 
			
		||||
            build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
            if (mi_32_col_offset + 2 >= max_cols)
 | 
			
		||||
              continue;
 | 
			
		||||
            mip2 = mip + 2;
 | 
			
		||||
            build_masks(lfi_n, mip2[0], shift_y + 2, shift_uv + 1, lfm);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
            } else {
 | 
			
		||||
              build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
            if (mip[0]->mbmi.tx_size == TX_32X32) {
 | 
			
		||||
              build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
            } else {
 | 
			
		||||
#endif
 | 
			
		||||
            for (idx_16 = 0; idx_16 < 4; mip += offset_16[idx_16], ++idx_16) {
 | 
			
		||||
              const int shift_y = shift_32_y[idx_32] + shift_16_y[idx_16];
 | 
			
		||||
              const int shift_uv = shift_32_uv[idx_32] + shift_16_uv[idx_16];
 | 
			
		||||
@@ -717,24 +871,56 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
 | 
			
		||||
                  build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  break;
 | 
			
		||||
                case BLOCK_16X8:
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  supertx = supertx_enabled_lpf(&mip[0]->mbmi);
 | 
			
		||||
                  if (!supertx) {
 | 
			
		||||
#endif
 | 
			
		||||
                  build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  if (mi_16_row_offset + 1 >= max_rows)
 | 
			
		||||
                    continue;
 | 
			
		||||
                  mip2 = mip + mode_info_stride;
 | 
			
		||||
                  build_y_mask(lfi_n, mip2[0], shift_y+8, lfm);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  } else {
 | 
			
		||||
                    build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  }
 | 
			
		||||
#endif
 | 
			
		||||
                  break;
 | 
			
		||||
                case BLOCK_8X16:
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  supertx = supertx_enabled_lpf(&mip[0]->mbmi);
 | 
			
		||||
                  if (!supertx) {
 | 
			
		||||
#endif
 | 
			
		||||
                  build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  if (mi_16_col_offset +1 >= max_cols)
 | 
			
		||||
                    continue;
 | 
			
		||||
                  mip2 = mip + 1;
 | 
			
		||||
                  build_y_mask(lfi_n, mip2[0], shift_y+1, lfm);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  } else {
 | 
			
		||||
                    build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  }
 | 
			
		||||
#endif
 | 
			
		||||
                  break;
 | 
			
		||||
                default: {
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  if (mip[0]->mbmi.tx_size == TX_16X16) {
 | 
			
		||||
                    build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  } else {
 | 
			
		||||
#endif
 | 
			
		||||
                  const int shift_y = shift_32_y[idx_32] +
 | 
			
		||||
                                      shift_16_y[idx_16] +
 | 
			
		||||
                                      shift_8_y[0];
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  supertx = supertx_enabled_lpf(&mip[0]->mbmi);
 | 
			
		||||
                  if (!supertx) {
 | 
			
		||||
#endif
 | 
			
		||||
                  build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  } else {
 | 
			
		||||
                    build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
 | 
			
		||||
                  }
 | 
			
		||||
#endif
 | 
			
		||||
                  mip += offset[0];
 | 
			
		||||
                  for (idx_8 = 1; idx_8 < 4; mip += offset[idx_8], ++idx_8) {
 | 
			
		||||
                    const int shift_y = shift_32_y[idx_32] +
 | 
			
		||||
@@ -748,12 +934,26 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
 | 
			
		||||
                    if (mi_8_col_offset >= max_cols ||
 | 
			
		||||
                        mi_8_row_offset >= max_rows)
 | 
			
		||||
                      continue;
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                    supertx = supertx_enabled_lpf(&mip[0]->mbmi);
 | 
			
		||||
                    if (!supertx)
 | 
			
		||||
#endif
 | 
			
		||||
                    build_y_mask(lfi_n, mip[0], shift_y, lfm);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                    else
 | 
			
		||||
                      build_y_mask_supertx(lfi_n, mip[0], shift_y, lfm);
 | 
			
		||||
#endif
 | 
			
		||||
                  }
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  }
 | 
			
		||||
#endif
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,181 +11,6 @@
 | 
			
		||||
 | 
			
		||||
#include "vp9/common/vp9_mvref_common.h"
 | 
			
		||||
 | 
			
		||||
#define MVREF_NEIGHBOURS 8
 | 
			
		||||
 | 
			
		||||
typedef struct position {
 | 
			
		||||
  int row;
 | 
			
		||||
  int col;
 | 
			
		||||
} POSITION;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  BOTH_ZERO = 0,
 | 
			
		||||
  ZERO_PLUS_PREDICTED = 1,
 | 
			
		||||
  BOTH_PREDICTED = 2,
 | 
			
		||||
  NEW_PLUS_NON_INTRA = 3,
 | 
			
		||||
  BOTH_NEW = 4,
 | 
			
		||||
  INTRA_PLUS_NON_INTRA = 5,
 | 
			
		||||
  BOTH_INTRA = 6,
 | 
			
		||||
  INVALID_CASE = 9
 | 
			
		||||
} motion_vector_context;
 | 
			
		||||
 | 
			
		||||
// This is used to figure out a context for the ref blocks. The code flattens
 | 
			
		||||
// an array that would have 3 possible counts (0, 1 & 2) for 3 choices by
 | 
			
		||||
// adding 9 for each intra block, 3 for each zero mv and 1 for each new
 | 
			
		||||
// motion vector. This single number is then converted into a context
 | 
			
		||||
// with a single lookup ( counter_to_context ).
 | 
			
		||||
static const int mode_2_counter[MB_MODE_COUNT] = {
 | 
			
		||||
  9,  // DC_PRED
 | 
			
		||||
  9,  // V_PRED
 | 
			
		||||
  9,  // H_PRED
 | 
			
		||||
  9,  // D45_PRED
 | 
			
		||||
  9,  // D135_PRED
 | 
			
		||||
  9,  // D117_PRED
 | 
			
		||||
  9,  // D153_PRED
 | 
			
		||||
  9,  // D207_PRED
 | 
			
		||||
  9,  // D63_PRED
 | 
			
		||||
  9,  // TM_PRED
 | 
			
		||||
  0,  // NEARESTMV
 | 
			
		||||
  0,  // NEARMV
 | 
			
		||||
  3,  // ZEROMV
 | 
			
		||||
  1,  // NEWMV
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// There are 3^3 different combinations of 3 counts that can be either 0,1 or
 | 
			
		||||
// 2. However the actual count can never be greater than 2 so the highest
 | 
			
		||||
// counter we need is 18. 9 is an invalid counter that's never used.
 | 
			
		||||
static const int counter_to_context[19] = {
 | 
			
		||||
  BOTH_PREDICTED,  // 0
 | 
			
		||||
  NEW_PLUS_NON_INTRA,  // 1
 | 
			
		||||
  BOTH_NEW,  // 2
 | 
			
		||||
  ZERO_PLUS_PREDICTED,  // 3
 | 
			
		||||
  NEW_PLUS_NON_INTRA,  // 4
 | 
			
		||||
  INVALID_CASE,  // 5
 | 
			
		||||
  BOTH_ZERO,  // 6
 | 
			
		||||
  INVALID_CASE,  // 7
 | 
			
		||||
  INVALID_CASE,  // 8
 | 
			
		||||
  INTRA_PLUS_NON_INTRA,  // 9
 | 
			
		||||
  INTRA_PLUS_NON_INTRA,  // 10
 | 
			
		||||
  INVALID_CASE,  // 11
 | 
			
		||||
  INTRA_PLUS_NON_INTRA,  // 12
 | 
			
		||||
  INVALID_CASE,  // 13
 | 
			
		||||
  INVALID_CASE,  // 14
 | 
			
		||||
  INVALID_CASE,  // 15
 | 
			
		||||
  INVALID_CASE,  // 16
 | 
			
		||||
  INVALID_CASE,  // 17
 | 
			
		||||
  BOTH_INTRA  // 18
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const POSITION mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
 | 
			
		||||
  // 4X4
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 4X8
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 8X4
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 8X8
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 8X16
 | 
			
		||||
  {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}},
 | 
			
		||||
  // 16X8
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}},
 | 
			
		||||
  // 16X16
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
 | 
			
		||||
  // 16X32
 | 
			
		||||
  {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}},
 | 
			
		||||
  // 32X16
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
 | 
			
		||||
  // 32X32
 | 
			
		||||
  {{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
 | 
			
		||||
  // 32X64
 | 
			
		||||
  {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}},
 | 
			
		||||
  // 64X32
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}},
 | 
			
		||||
  // 64X64
 | 
			
		||||
  {{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int idx_n_column_to_subblock[4][2] = {
 | 
			
		||||
  {1, 2},
 | 
			
		||||
  {1, 3},
 | 
			
		||||
  {3, 2},
 | 
			
		||||
  {3, 3}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// clamp_mv_ref
 | 
			
		||||
#define MV_BORDER (16 << 3)  // Allow 16 pels in 1/8th pel units
 | 
			
		||||
 | 
			
		||||
static void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) {
 | 
			
		||||
  clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER,
 | 
			
		||||
               xd->mb_to_right_edge + MV_BORDER,
 | 
			
		||||
               xd->mb_to_top_edge - MV_BORDER,
 | 
			
		||||
               xd->mb_to_bottom_edge + MV_BORDER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function returns either the appropriate sub block or block's mv
 | 
			
		||||
// on whether the block_size < 8x8 and we have check_sub_blocks set.
 | 
			
		||||
static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, int which_mv,
 | 
			
		||||
                                      int search_col, int block_idx) {
 | 
			
		||||
  return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8
 | 
			
		||||
          ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]]
 | 
			
		||||
              .as_mv[which_mv]
 | 
			
		||||
          : candidate->mbmi.mv[which_mv];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Performs mv sign inversion if indicated by the reference frame combination.
 | 
			
		||||
static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
 | 
			
		||||
                              const MV_REFERENCE_FRAME this_ref_frame,
 | 
			
		||||
                              const int *ref_sign_bias) {
 | 
			
		||||
  int_mv mv = mbmi->mv[ref];
 | 
			
		||||
  if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) {
 | 
			
		||||
    mv.as_mv.row *= -1;
 | 
			
		||||
    mv.as_mv.col *= -1;
 | 
			
		||||
  }
 | 
			
		||||
  return mv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This macro is used to add a motion vector mv_ref list if it isn't
 | 
			
		||||
// already in the list.  If it's the second motion vector it will also
 | 
			
		||||
// skip all additional processing and jump to done!
 | 
			
		||||
#define ADD_MV_REF_LIST(mv) \
 | 
			
		||||
  do { \
 | 
			
		||||
    if (refmv_count) { \
 | 
			
		||||
      if ((mv).as_int != mv_ref_list[0].as_int) { \
 | 
			
		||||
        mv_ref_list[refmv_count] = (mv); \
 | 
			
		||||
        goto Done; \
 | 
			
		||||
      } \
 | 
			
		||||
    } else { \
 | 
			
		||||
      mv_ref_list[refmv_count++] = (mv); \
 | 
			
		||||
    } \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
// If either reference frame is different, not INTRA, and they
 | 
			
		||||
// are different from each other scale and add the mv to our list.
 | 
			
		||||
#define IF_DIFF_REF_FRAME_ADD_MV(mbmi) \
 | 
			
		||||
  do { \
 | 
			
		||||
    if (is_inter_block(mbmi)) { \
 | 
			
		||||
      if ((mbmi)->ref_frame[0] != ref_frame) \
 | 
			
		||||
        ADD_MV_REF_LIST(scale_mv((mbmi), 0, ref_frame, ref_sign_bias)); \
 | 
			
		||||
      if (has_second_ref(mbmi) && \
 | 
			
		||||
          (mbmi)->ref_frame[1] != ref_frame && \
 | 
			
		||||
          (mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) \
 | 
			
		||||
        ADD_MV_REF_LIST(scale_mv((mbmi), 1, ref_frame, ref_sign_bias)); \
 | 
			
		||||
    } \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Checks that the given mi_row, mi_col and search point
 | 
			
		||||
// are inside the borders of the tile.
 | 
			
		||||
static INLINE int is_inside(const TileInfo *const tile,
 | 
			
		||||
                            int mi_col, int mi_row, int mi_rows,
 | 
			
		||||
                            const POSITION *mi_pos) {
 | 
			
		||||
  return !(mi_row + mi_pos->row < 0 ||
 | 
			
		||||
           mi_col + mi_pos->col < tile->mi_col_start ||
 | 
			
		||||
           mi_row + mi_pos->row >= mi_rows ||
 | 
			
		||||
           mi_col + mi_pos->col >= tile->mi_col_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function searches the neighbourhood of a given MB/SB
 | 
			
		||||
// to try and find candidate reference vectors.
 | 
			
		||||
static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
 | 
			
		||||
@@ -363,3 +188,176 @@ void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
      assert("Invalid block index.");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
static int compare_interinfo(MB_MODE_INFO *mbmi, MB_MODE_INFO *ref_mbmi) {
 | 
			
		||||
  if (mbmi == ref_mbmi) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    int is_same;
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    MV_REFERENCE_FRAME mbmi_ref1_backup = mbmi->ref_frame[1];
 | 
			
		||||
    MV_REFERENCE_FRAME refmbmi_ref1_backup = ref_mbmi->ref_frame[1];
 | 
			
		||||
 | 
			
		||||
    if (mbmi->ref_frame[1] == INTRA_FRAME)
 | 
			
		||||
      mbmi->ref_frame[1] = NONE;
 | 
			
		||||
    if (ref_mbmi->ref_frame[1] == INTRA_FRAME)
 | 
			
		||||
      ref_mbmi->ref_frame[1] = NONE;
 | 
			
		||||
#endif
 | 
			
		||||
    if (mbmi->ref_frame[0] == ref_mbmi->ref_frame[0] &&
 | 
			
		||||
        mbmi->ref_frame[1] == ref_mbmi->ref_frame[1]) {
 | 
			
		||||
      if (mbmi->ref_frame[1] > INTRA_FRAME)
 | 
			
		||||
        is_same = mbmi->mv[0].as_int == ref_mbmi->mv[0].as_int &&
 | 
			
		||||
                  mbmi->mv[1].as_int == ref_mbmi->mv[1].as_int &&
 | 
			
		||||
                  mbmi->interp_filter == ref_mbmi->interp_filter;
 | 
			
		||||
      else
 | 
			
		||||
        is_same = mbmi->mv[0].as_int == ref_mbmi->mv[0].as_int &&
 | 
			
		||||
                  mbmi->interp_filter == ref_mbmi->interp_filter;
 | 
			
		||||
    } else {
 | 
			
		||||
      is_same = 0;
 | 
			
		||||
    }
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    mbmi->ref_frame[1] = mbmi_ref1_backup;
 | 
			
		||||
    ref_mbmi->ref_frame[1] = refmbmi_ref1_backup;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return is_same;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int check_inside(VP9_COMMON *cm, int mi_row, int mi_col) {
 | 
			
		||||
  return mi_row >= 0 && mi_col >= 0 &&
 | 
			
		||||
         mi_row < cm->mi_rows && mi_col < cm->mi_cols;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_right_available(BLOCK_SIZE bsize, int mi_row, int mi_col) {
 | 
			
		||||
  int depth, max_depth = 4 - MIN(b_width_log2(bsize), b_height_log2(bsize));
 | 
			
		||||
  int block[4] = {0};
 | 
			
		||||
 | 
			
		||||
  if (bsize == BLOCK_64X64)
 | 
			
		||||
    return 1;
 | 
			
		||||
  mi_row = mi_row % 8;
 | 
			
		||||
  mi_col = mi_col % 8;
 | 
			
		||||
  for (depth = 1; depth <= max_depth; depth++) {
 | 
			
		||||
    block[depth] = (mi_row >> (3 - depth)) * 2 + (mi_col >> (3 - depth));
 | 
			
		||||
    mi_row = mi_row % (8 >> depth);
 | 
			
		||||
    mi_col = mi_col % (8 >> depth);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (b_width_log2(bsize) < b_height_log2(bsize)) {
 | 
			
		||||
    if (block[max_depth] == 0)
 | 
			
		||||
      return 1;
 | 
			
		||||
  } else if (b_width_log2(bsize) > b_height_log2(bsize)) {
 | 
			
		||||
    if (block[max_depth] > 0)
 | 
			
		||||
      return 0;
 | 
			
		||||
  } else {
 | 
			
		||||
    if (block[max_depth] == 0 || block[max_depth] == 2)
 | 
			
		||||
      return 1;
 | 
			
		||||
    else if (block[max_depth] == 3)
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (depth = max_depth - 1; depth > 0; depth--) {
 | 
			
		||||
    if (block[depth] == 0 || block[depth] == 2)
 | 
			
		||||
      return 1;
 | 
			
		||||
    else if (block[depth] == 3)
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_second_rec(int mi_row, int mi_col, BLOCK_SIZE bsize) {
 | 
			
		||||
  int bw = 4 << b_width_log2(bsize);
 | 
			
		||||
  int bh = 4 << b_height_log2(bsize);
 | 
			
		||||
 | 
			
		||||
  if (bw < bh)
 | 
			
		||||
    return (mi_col << 3) % (bw << 1) == 0 ? 0 : 1;
 | 
			
		||||
  else if (bh < bw)
 | 
			
		||||
    return (mi_row << 3) % (bh << 1) == 0 ? 0 : 2;
 | 
			
		||||
  else
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_construct_ref_inter_list(VP9_COMMON *cm,  MACROBLOCKD *xd,
 | 
			
		||||
                                 BLOCK_SIZE bsize, int mi_row, int mi_col,
 | 
			
		||||
                                 MB_MODE_INFO *ref_list[18]) {
 | 
			
		||||
  int bw = 4 << b_width_log2(bsize);
 | 
			
		||||
  int bh = 4 << b_height_log2(bsize);
 | 
			
		||||
  int row_offset, col_offset;
 | 
			
		||||
  int mi_offset;
 | 
			
		||||
  MB_MODE_INFO *ref_mbmi;
 | 
			
		||||
  int ref_index, ref_num = 0;
 | 
			
		||||
  int row_offset_cand[18], col_offset_cand[18];
 | 
			
		||||
  int offset_num = 0, i, switchflag;
 | 
			
		||||
  int is_sec_rec = is_second_rec(mi_row, mi_col, bsize);
 | 
			
		||||
 | 
			
		||||
  if (is_sec_rec != 2) {
 | 
			
		||||
    row_offset_cand[offset_num] = -1; col_offset_cand[offset_num] = 0;
 | 
			
		||||
    offset_num++;
 | 
			
		||||
  }
 | 
			
		||||
  if (is_sec_rec != 1) {
 | 
			
		||||
    row_offset_cand[offset_num] = bh / 16; col_offset_cand[offset_num] = -1;
 | 
			
		||||
    offset_num++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  row_offset = bh / 8 - 1;
 | 
			
		||||
  col_offset = 1;
 | 
			
		||||
  if (is_sec_rec < 2)
 | 
			
		||||
    switchflag = 1;
 | 
			
		||||
  else
 | 
			
		||||
    switchflag = 0;
 | 
			
		||||
  while ((is_sec_rec == 0 && ((row_offset >=0) || col_offset < (bw / 8 + 1))) ||
 | 
			
		||||
         (is_sec_rec == 1 && col_offset < (bw / 8 + 1)) ||
 | 
			
		||||
         (is_sec_rec == 2 && row_offset >=0)) {
 | 
			
		||||
    switch (switchflag) {
 | 
			
		||||
      case 0:
 | 
			
		||||
        if (row_offset >= 0) {
 | 
			
		||||
          if (row_offset != bh / 16) {
 | 
			
		||||
            row_offset_cand[offset_num] = row_offset;
 | 
			
		||||
            col_offset_cand[offset_num] = -1;
 | 
			
		||||
            offset_num++;
 | 
			
		||||
          }
 | 
			
		||||
          row_offset--;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case 1:
 | 
			
		||||
        if (col_offset < (bw / 8 + 1)) {
 | 
			
		||||
          row_offset_cand[offset_num] = -1;
 | 
			
		||||
          col_offset_cand[offset_num] = col_offset;
 | 
			
		||||
          offset_num++;
 | 
			
		||||
          col_offset++;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        assert(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (is_sec_rec == 0)
 | 
			
		||||
      switchflag = 1 - switchflag;
 | 
			
		||||
  }
 | 
			
		||||
  row_offset_cand[offset_num] = -1;
 | 
			
		||||
  col_offset_cand[offset_num] = -1;
 | 
			
		||||
  offset_num++;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < offset_num; i++) {
 | 
			
		||||
    row_offset = row_offset_cand[i];
 | 
			
		||||
    col_offset = col_offset_cand[i];
 | 
			
		||||
    if ((col_offset < (bw / 8) ||
 | 
			
		||||
        (col_offset == (bw / 8) && is_right_available(bsize, mi_row, mi_col)))
 | 
			
		||||
        && check_inside(cm, mi_row + row_offset, mi_col + col_offset)) {
 | 
			
		||||
      mi_offset = row_offset * cm->mi_stride + col_offset;
 | 
			
		||||
      ref_mbmi = &xd->mi[mi_offset]->mbmi;
 | 
			
		||||
      if (is_inter_block(ref_mbmi)) {
 | 
			
		||||
        for (ref_index = 0; ref_index < ref_num; ref_index++) {
 | 
			
		||||
          if (compare_interinfo(ref_mbmi, ref_list[ref_index]))
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (ref_index == ref_num) {
 | 
			
		||||
          ref_list[ref_num] = ref_mbmi;
 | 
			
		||||
          ref_num++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ref_num;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,181 @@ extern "C" {
 | 
			
		||||
#define RIGHT_BOTTOM_MARGIN ((VP9_ENC_BORDER_IN_PIXELS -\
 | 
			
		||||
                                VP9_INTERP_EXTEND) << 3)
 | 
			
		||||
 | 
			
		||||
#define MVREF_NEIGHBOURS 8
 | 
			
		||||
 | 
			
		||||
typedef struct position {
 | 
			
		||||
  int row;
 | 
			
		||||
  int col;
 | 
			
		||||
} POSITION;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  BOTH_ZERO = 0,
 | 
			
		||||
  ZERO_PLUS_PREDICTED = 1,
 | 
			
		||||
  BOTH_PREDICTED = 2,
 | 
			
		||||
  NEW_PLUS_NON_INTRA = 3,
 | 
			
		||||
  BOTH_NEW = 4,
 | 
			
		||||
  INTRA_PLUS_NON_INTRA = 5,
 | 
			
		||||
  BOTH_INTRA = 6,
 | 
			
		||||
  INVALID_CASE = 9
 | 
			
		||||
} motion_vector_context;
 | 
			
		||||
 | 
			
		||||
// This is used to figure out a context for the ref blocks. The code flattens
 | 
			
		||||
// an array that would have 3 possible counts (0, 1 & 2) for 3 choices by
 | 
			
		||||
// adding 9 for each intra block, 3 for each zero mv and 1 for each new
 | 
			
		||||
// motion vector. This single number is then converted into a context
 | 
			
		||||
// with a single lookup ( counter_to_context ).
 | 
			
		||||
static const int mode_2_counter[MB_MODE_COUNT] = {
 | 
			
		||||
  9,  // DC_PRED
 | 
			
		||||
  9,  // V_PRED
 | 
			
		||||
  9,  // H_PRED
 | 
			
		||||
  9,  // D45_PRED
 | 
			
		||||
  9,  // D135_PRED
 | 
			
		||||
  9,  // D117_PRED
 | 
			
		||||
  9,  // D153_PRED
 | 
			
		||||
  9,  // D207_PRED
 | 
			
		||||
  9,  // D63_PRED
 | 
			
		||||
  9,  // TM_PRED
 | 
			
		||||
  0,  // NEARESTMV
 | 
			
		||||
  0,  // NEARMV
 | 
			
		||||
  3,  // ZEROMV
 | 
			
		||||
  1,  // NEWMV
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// There are 3^3 different combinations of 3 counts that can be either 0,1 or
 | 
			
		||||
// 2. However the actual count can never be greater than 2 so the highest
 | 
			
		||||
// counter we need is 18. 9 is an invalid counter that's never used.
 | 
			
		||||
static const int counter_to_context[19] = {
 | 
			
		||||
  BOTH_PREDICTED,  // 0
 | 
			
		||||
  NEW_PLUS_NON_INTRA,  // 1
 | 
			
		||||
  BOTH_NEW,  // 2
 | 
			
		||||
  ZERO_PLUS_PREDICTED,  // 3
 | 
			
		||||
  NEW_PLUS_NON_INTRA,  // 4
 | 
			
		||||
  INVALID_CASE,  // 5
 | 
			
		||||
  BOTH_ZERO,  // 6
 | 
			
		||||
  INVALID_CASE,  // 7
 | 
			
		||||
  INVALID_CASE,  // 8
 | 
			
		||||
  INTRA_PLUS_NON_INTRA,  // 9
 | 
			
		||||
  INTRA_PLUS_NON_INTRA,  // 10
 | 
			
		||||
  INVALID_CASE,  // 11
 | 
			
		||||
  INTRA_PLUS_NON_INTRA,  // 12
 | 
			
		||||
  INVALID_CASE,  // 13
 | 
			
		||||
  INVALID_CASE,  // 14
 | 
			
		||||
  INVALID_CASE,  // 15
 | 
			
		||||
  INVALID_CASE,  // 16
 | 
			
		||||
  INVALID_CASE,  // 17
 | 
			
		||||
  BOTH_INTRA  // 18
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const POSITION mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
 | 
			
		||||
  // 4X4
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 4X8
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 8X4
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 8X8
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
 | 
			
		||||
  // 8X16
 | 
			
		||||
  {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}},
 | 
			
		||||
  // 16X8
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}},
 | 
			
		||||
  // 16X16
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
 | 
			
		||||
  // 16X32
 | 
			
		||||
  {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}},
 | 
			
		||||
  // 32X16
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
 | 
			
		||||
  // 32X32
 | 
			
		||||
  {{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
 | 
			
		||||
  // 32X64
 | 
			
		||||
  {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}},
 | 
			
		||||
  // 64X32
 | 
			
		||||
  {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}},
 | 
			
		||||
  // 64X64
 | 
			
		||||
  {{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int idx_n_column_to_subblock[4][2] = {
 | 
			
		||||
  {1, 2},
 | 
			
		||||
  {1, 3},
 | 
			
		||||
  {3, 2},
 | 
			
		||||
  {3, 3}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// clamp_mv_ref
 | 
			
		||||
#define MV_BORDER (16 << 3)  // Allow 16 pels in 1/8th pel units
 | 
			
		||||
 | 
			
		||||
static void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) {
 | 
			
		||||
  clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER,
 | 
			
		||||
               xd->mb_to_right_edge + MV_BORDER,
 | 
			
		||||
               xd->mb_to_top_edge - MV_BORDER,
 | 
			
		||||
               xd->mb_to_bottom_edge + MV_BORDER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function returns either the appropriate sub block or block's mv
 | 
			
		||||
// on whether the block_size < 8x8 and we have check_sub_blocks set.
 | 
			
		||||
static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, int which_mv,
 | 
			
		||||
                                      int search_col, int block_idx) {
 | 
			
		||||
  return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8
 | 
			
		||||
          ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]]
 | 
			
		||||
              .as_mv[which_mv]
 | 
			
		||||
          : candidate->mbmi.mv[which_mv];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Performs mv sign inversion if indicated by the reference frame combination.
 | 
			
		||||
static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
 | 
			
		||||
                              const MV_REFERENCE_FRAME this_ref_frame,
 | 
			
		||||
                              const int *ref_sign_bias) {
 | 
			
		||||
  int_mv mv = mbmi->mv[ref];
 | 
			
		||||
  if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) {
 | 
			
		||||
    mv.as_mv.row *= -1;
 | 
			
		||||
    mv.as_mv.col *= -1;
 | 
			
		||||
  }
 | 
			
		||||
  return mv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This macro is used to add a motion vector mv_ref list if it isn't
 | 
			
		||||
// already in the list.  If it's the second motion vector it will also
 | 
			
		||||
// skip all additional processing and jump to done!
 | 
			
		||||
#define ADD_MV_REF_LIST(mv) \
 | 
			
		||||
  do { \
 | 
			
		||||
    if (refmv_count) { \
 | 
			
		||||
      if ((mv).as_int != mv_ref_list[0].as_int) { \
 | 
			
		||||
        mv_ref_list[refmv_count] = (mv); \
 | 
			
		||||
        goto Done; \
 | 
			
		||||
      } \
 | 
			
		||||
    } else { \
 | 
			
		||||
      mv_ref_list[refmv_count++] = (mv); \
 | 
			
		||||
    } \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
// If either reference frame is different, not INTRA, and they
 | 
			
		||||
// are different from each other scale and add the mv to our list.
 | 
			
		||||
#define IF_DIFF_REF_FRAME_ADD_MV(mbmi) \
 | 
			
		||||
  do { \
 | 
			
		||||
    if (is_inter_block(mbmi)) { \
 | 
			
		||||
      if ((mbmi)->ref_frame[0] != ref_frame) \
 | 
			
		||||
        ADD_MV_REF_LIST(scale_mv((mbmi), 0, ref_frame, ref_sign_bias)); \
 | 
			
		||||
      if (has_second_ref(mbmi) && \
 | 
			
		||||
          (mbmi)->ref_frame[1] != ref_frame && \
 | 
			
		||||
          (mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) \
 | 
			
		||||
        ADD_MV_REF_LIST(scale_mv((mbmi), 1, ref_frame, ref_sign_bias)); \
 | 
			
		||||
    } \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Checks that the given mi_row, mi_col and search point
 | 
			
		||||
// are inside the borders of the tile.
 | 
			
		||||
static INLINE int is_inside(const TileInfo *const tile,
 | 
			
		||||
                            int mi_col, int mi_row, int mi_rows,
 | 
			
		||||
                            const POSITION *mi_pos) {
 | 
			
		||||
  return !(mi_row + mi_pos->row < 0 ||
 | 
			
		||||
           mi_col + mi_pos->col < tile->mi_col_start ||
 | 
			
		||||
           mi_row + mi_pos->row >= mi_rows ||
 | 
			
		||||
           mi_col + mi_pos->col >= tile->mi_col_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO(jingning): this mv clamping function should be block size dependent.
 | 
			
		||||
static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
 | 
			
		||||
  clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
 | 
			
		||||
@@ -45,6 +220,12 @@ void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
                                   int block, int ref, int mi_row, int mi_col,
 | 
			
		||||
                                   int_mv *nearest, int_mv *near);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
int vp9_construct_ref_inter_list(VP9_COMMON *cm,  MACROBLOCKD *xd,
 | 
			
		||||
                                 BLOCK_SIZE bsize, int mi_row, int mi_col,
 | 
			
		||||
                                 MB_MODE_INFO *ref_list[18]);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -212,6 +212,16 @@ typedef struct VP9Common {
 | 
			
		||||
 | 
			
		||||
  PARTITION_CONTEXT *above_seg_context;
 | 
			
		||||
  ENTROPY_CONTEXT *above_context;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  int use_masked_interinter;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  int use_interintra;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  int use_masked_interintra;
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
} VP9_COMMON;
 | 
			
		||||
 | 
			
		||||
static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
 | 
			
		||||
 
 | 
			
		||||
@@ -383,3 +383,47 @@ int vp9_get_segment_id(VP9_COMMON *cm, const uint8_t *segment_ids,
 | 
			
		||||
  assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
 | 
			
		||||
  return segment_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
int vp9_get_copy_mode_context(const MACROBLOCKD *xd) {
 | 
			
		||||
  const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
 | 
			
		||||
  const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
 | 
			
		||||
  const int has_above = above_mbmi != NULL;
 | 
			
		||||
  const int has_left = left_mbmi != NULL;
 | 
			
		||||
 | 
			
		||||
  if (has_above && has_left) {
 | 
			
		||||
    const int above_intra = !is_inter_block(above_mbmi);
 | 
			
		||||
    const int left_intra = !is_inter_block(left_mbmi);
 | 
			
		||||
 | 
			
		||||
    if (above_intra && left_intra) {
 | 
			
		||||
      return 4;
 | 
			
		||||
    } else if (above_intra || left_intra) {
 | 
			
		||||
      return 3;
 | 
			
		||||
    } else {
 | 
			
		||||
      const int above_predict = above_mbmi->copy_mode != NOREF;
 | 
			
		||||
      const int left_predict = left_mbmi->copy_mode != NOREF;
 | 
			
		||||
      if (above_predict && left_predict)
 | 
			
		||||
        return 0;
 | 
			
		||||
      else if (above_predict || left_predict)
 | 
			
		||||
        return 1;
 | 
			
		||||
      else
 | 
			
		||||
        return 2;
 | 
			
		||||
    }
 | 
			
		||||
  } else if (has_above || has_left) {
 | 
			
		||||
    const MB_MODE_INFO *const ref_mbmi = has_above ? above_mbmi : left_mbmi;
 | 
			
		||||
    const int ref_intra = !is_inter_block(ref_mbmi);
 | 
			
		||||
 | 
			
		||||
    if (ref_intra) {
 | 
			
		||||
      return 3;
 | 
			
		||||
    } else {
 | 
			
		||||
     const int ref_predict = ref_mbmi != NOREF;
 | 
			
		||||
      if (ref_predict)
 | 
			
		||||
        return 0;
 | 
			
		||||
      else
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -134,6 +134,10 @@ static INLINE unsigned int *get_tx_counts(TX_SIZE max_tx_size, int ctx,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
int vp9_get_copy_mode_context(const MACROBLOCKD *xd);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@
 | 
			
		||||
#include "vp9/common/vp9_quant_common.h"
 | 
			
		||||
#include "vp9/common/vp9_seg_common.h"
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
static const int16_t dc_qlookup[QINDEX_RANGE] = {
 | 
			
		||||
  4,       8,    8,    9,   10,   11,   12,   12,
 | 
			
		||||
  13,     14,   15,   16,   17,   18,   19,   19,
 | 
			
		||||
@@ -83,44 +82,6 @@ static const int16_t ac_qlookup[QINDEX_RANGE] = {
 | 
			
		||||
  1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void vp9_init_quant_tables(void) { }
 | 
			
		||||
#else
 | 
			
		||||
static int16_t dc_qlookup[QINDEX_RANGE];
 | 
			
		||||
static int16_t ac_qlookup[QINDEX_RANGE];
 | 
			
		||||
 | 
			
		||||
#define ACDC_MIN 8
 | 
			
		||||
 | 
			
		||||
// TODO(dkovalev) move to common and reuse
 | 
			
		||||
static double poly3(double a, double b, double c, double d, double x) {
 | 
			
		||||
  return a*x*x*x + b*x*x + c*x + d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_init_quant_tables() {
 | 
			
		||||
  int i, val = 4;
 | 
			
		||||
 | 
			
		||||
  // A "real" q of 1.0 forces lossless mode.
 | 
			
		||||
  // In practice non lossless Q's between 1.0 and 2.0 (represented here by
 | 
			
		||||
  // integer values from 5-7 give poor rd results (lower psnr and often
 | 
			
		||||
  // larger size than the lossless encode. To block out those "not very useful"
 | 
			
		||||
  // values we increment the ac and dc q lookup values by 4 after position 0.
 | 
			
		||||
  ac_qlookup[0] = val;
 | 
			
		||||
  dc_qlookup[0] = val;
 | 
			
		||||
  val += 4;
 | 
			
		||||
 | 
			
		||||
  for (i = 1; i < QINDEX_RANGE; i++) {
 | 
			
		||||
    const int ac_val = val;
 | 
			
		||||
 | 
			
		||||
    val = (int)(val * 1.01975);
 | 
			
		||||
    if (val == ac_val)
 | 
			
		||||
      ++val;
 | 
			
		||||
 | 
			
		||||
    ac_qlookup[i] = (int16_t)ac_val;
 | 
			
		||||
    dc_qlookup[i] = (int16_t)MAX(ACDC_MIN, poly3(0.000000305, -0.00065, 0.9,
 | 
			
		||||
                                                 0.5, ac_val));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int16_t vp9_dc_quant(int qindex, int delta) {
 | 
			
		||||
  return dc_qlookup[clamp(qindex + delta, 0, MAXQ)];
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,6 @@ extern "C" {
 | 
			
		||||
#define QINDEX_RANGE (MAXQ - MINQ + 1)
 | 
			
		||||
#define QINDEX_BITS 8
 | 
			
		||||
 | 
			
		||||
void vp9_init_quant_tables();
 | 
			
		||||
 | 
			
		||||
int16_t vp9_dc_quant(int qindex, int delta);
 | 
			
		||||
int16_t vp9_ac_quant(int qindex, int delta);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -139,9 +139,349 @@ MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv,
 | 
			
		||||
  return clamped_mv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
#define MASK_WEIGHT_BITS 6
 | 
			
		||||
 | 
			
		||||
static int get_masked_weight(int m) {
 | 
			
		||||
  #define SMOOTHER_LEN  32
 | 
			
		||||
  static const uint8_t smoothfn[2 * SMOOTHER_LEN + 1] = {
 | 
			
		||||
      0,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
      0,  0,  0,  0,  0,  1,  1,  1,
 | 
			
		||||
      1,  1,  2,  2,  3,  4,  5,  6,
 | 
			
		||||
      8,  9, 12, 14, 17, 21, 24, 28,
 | 
			
		||||
      32,
 | 
			
		||||
      36, 40, 43, 47, 50, 52, 55, 56,
 | 
			
		||||
      58, 59, 60, 61, 62, 62, 63, 63,
 | 
			
		||||
      63, 63, 63, 64, 64, 64, 64, 64,
 | 
			
		||||
      64, 64, 64, 64, 64, 64, 64, 64,
 | 
			
		||||
  };
 | 
			
		||||
  if (m < -SMOOTHER_LEN)
 | 
			
		||||
    return 0;
 | 
			
		||||
  else if (m > SMOOTHER_LEN)
 | 
			
		||||
    return (1 << MASK_WEIGHT_BITS);
 | 
			
		||||
  else
 | 
			
		||||
    return smoothfn[m + SMOOTHER_LEN];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_hard_mask(int m) {
 | 
			
		||||
  return 1 << MASK_WEIGHT_BITS * (m > 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
 | 
			
		||||
// The soft mask is obtained by computing f(x, y) and then calling
 | 
			
		||||
// get_masked_weight(f(x, y)).
 | 
			
		||||
static const int mask_params_sml[1 << MASK_BITS_SML][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_med_hgtw[1 << MASK_BITS_MED][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_med_hltw[1 << MASK_BITS_MED][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_med_heqw[1 << MASK_BITS_MED][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 1},
 | 
			
		||||
  { 0, -2, 0, 1},
 | 
			
		||||
  { 0,  2, 0, 3},
 | 
			
		||||
  { 0, -2, 0, 3},
 | 
			
		||||
  { 2,  0, 1, 0},
 | 
			
		||||
  {-2,  0, 1, 0},
 | 
			
		||||
  { 2,  0, 3, 0},
 | 
			
		||||
  {-2,  0, 3, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_big_hgtw[1 << MASK_BITS_BIG][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 1},
 | 
			
		||||
  { 0, -2, 0, 1},
 | 
			
		||||
  { 0,  2, 0, 2},
 | 
			
		||||
  { 0, -2, 0, 2},
 | 
			
		||||
  { 0,  2, 0, 3},
 | 
			
		||||
  { 0, -2, 0, 3},
 | 
			
		||||
  { 2,  0, 2, 0},
 | 
			
		||||
  {-2,  0, 2, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_big_hltw[1 << MASK_BITS_BIG][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 2},
 | 
			
		||||
  { 0, -2, 0, 2},
 | 
			
		||||
  { 2,  0, 1, 0},
 | 
			
		||||
  {-2,  0, 1, 0},
 | 
			
		||||
  { 2,  0, 2, 0},
 | 
			
		||||
  {-2,  0, 2, 0},
 | 
			
		||||
  { 2,  0, 3, 0},
 | 
			
		||||
  {-2,  0, 3, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_big_heqw[1 << MASK_BITS_BIG][4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 1},
 | 
			
		||||
  { 0, -2, 0, 1},
 | 
			
		||||
  { 0,  2, 0, 3},
 | 
			
		||||
  { 0, -2, 0, 3},
 | 
			
		||||
  { 2,  0, 1, 0},
 | 
			
		||||
  {-2,  0, 1, 0},
 | 
			
		||||
  { 2,  0, 3, 0},
 | 
			
		||||
  {-2,  0, 3, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int *get_mask_params(int mask_index,
 | 
			
		||||
                                  BLOCK_SIZE sb_type,
 | 
			
		||||
                                  int h, int w) {
 | 
			
		||||
  const int *a;
 | 
			
		||||
  const int mask_bits = get_mask_bits(sb_type);
 | 
			
		||||
 | 
			
		||||
  if (mask_index == MASK_NONE)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  if (mask_bits == MASK_BITS_SML) {
 | 
			
		||||
    a = mask_params_sml[mask_index];
 | 
			
		||||
  } else if (mask_bits == MASK_BITS_MED) {
 | 
			
		||||
    if (h > w)
 | 
			
		||||
      a = mask_params_med_hgtw[mask_index];
 | 
			
		||||
    else if (h < w)
 | 
			
		||||
      a = mask_params_med_hltw[mask_index];
 | 
			
		||||
    else
 | 
			
		||||
      a = mask_params_med_heqw[mask_index];
 | 
			
		||||
  } else if (mask_bits == MASK_BITS_BIG) {
 | 
			
		||||
    if (h > w)
 | 
			
		||||
      a = mask_params_big_hgtw[mask_index];
 | 
			
		||||
    else if (h < w)
 | 
			
		||||
      a = mask_params_big_hltw[mask_index];
 | 
			
		||||
    else
 | 
			
		||||
      a = mask_params_big_heqw[mask_index];
 | 
			
		||||
  } else {
 | 
			
		||||
    assert(0);
 | 
			
		||||
  }
 | 
			
		||||
  return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_generate_masked_weight(int mask_index,
 | 
			
		||||
                                BLOCK_SIZE sb_type,
 | 
			
		||||
                                int h, int w,
 | 
			
		||||
                                uint8_t *mask, int stride) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  const int *a = get_mask_params(mask_index, sb_type, h, w);
 | 
			
		||||
  if (!a) return;
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int x = (j - (a[2] * w) / 4);
 | 
			
		||||
      int y = (i - (a[3] * h) / 4);
 | 
			
		||||
      int m = a[0] * x + a[1] * y;
 | 
			
		||||
      mask[i * stride + j] = get_masked_weight(m);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
 | 
			
		||||
                            int h, int w, uint8_t *mask, int stride) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  const int *a = get_mask_params(mask_index, sb_type, h, w);
 | 
			
		||||
  if (!a) return;
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int x = (j - (a[2] * w) / 4);
 | 
			
		||||
      int y = (i - (a[3] * h) / 4);
 | 
			
		||||
      int m = a[0] * x + a[1] * y;
 | 
			
		||||
      mask[i * stride + j] = get_hard_mask(m);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void build_masked_compound(uint8_t *dst, int dst_stride,
 | 
			
		||||
                                  uint8_t *dst2, int dst2_stride,
 | 
			
		||||
                                  int mask_index, BLOCK_SIZE sb_type,
 | 
			
		||||
                                  int h, int w) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  uint8_t mask[4096];
 | 
			
		||||
  vp9_generate_masked_weight(mask_index, sb_type, h, w, mask, 64);
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int m = mask[i * 64 + j];
 | 
			
		||||
      dst[i * dst_stride + j] = (dst[i * dst_stride + j] * m +
 | 
			
		||||
                                 dst2[i * dst2_stride + j] *
 | 
			
		||||
                                 ((1 << MASK_WEIGHT_BITS) - m) +
 | 
			
		||||
                                 (1 << (MASK_WEIGHT_BITS - 1))) >>
 | 
			
		||||
                                 MASK_WEIGHT_BITS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void generate_masked_weight_extend(int mask_index, int plane,
 | 
			
		||||
                                   BLOCK_SIZE sb_type, int h, int w,
 | 
			
		||||
                                   int mask_offset_x, int mask_offset_y,
 | 
			
		||||
                                   uint8_t *mask, int stride) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  int subh = (plane ? 2 : 4) << b_height_log2(sb_type);
 | 
			
		||||
  int subw = (plane ? 2 : 4) << b_width_log2(sb_type);
 | 
			
		||||
  const int *a = get_mask_params(mask_index, sb_type, subh, subw);
 | 
			
		||||
  if (!a) return;
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int x = (j - (a[2] * subw) / 4 - mask_offset_x);
 | 
			
		||||
      int y = (i - (a[3] * subh) / 4 - mask_offset_y);
 | 
			
		||||
      int m = a[0] * x + a[1] * y;
 | 
			
		||||
      mask[i * stride + j] = get_masked_weight(m);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void build_masked_compound_extend(uint8_t *dst, int dst_stride,
 | 
			
		||||
                                         uint8_t *dst2, int dst2_stride,
 | 
			
		||||
                                         int plane,
 | 
			
		||||
                                         int mask_index, BLOCK_SIZE sb_type,
 | 
			
		||||
                                         int mask_offset_x, int mask_offset_y,
 | 
			
		||||
                                         int h, int w) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  uint8_t mask[4096];
 | 
			
		||||
  generate_masked_weight_extend(mask_index, plane, sb_type, h, w,
 | 
			
		||||
                                mask_offset_x, mask_offset_y, mask, 64);
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int m = mask[i * 64 + j];
 | 
			
		||||
      dst[i * dst_stride + j] = (dst[i * dst_stride + j] * m +
 | 
			
		||||
                                 dst2[i * dst2_stride + j] *
 | 
			
		||||
                                 ((1 << MASK_WEIGHT_BITS) - m) +
 | 
			
		||||
                                 (1 << (MASK_WEIGHT_BITS - 1))) >>
 | 
			
		||||
                                 MASK_WEIGHT_BITS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
 | 
			
		||||
                                   int bw, int bh,
 | 
			
		||||
                                   int x, int y, int w, int h,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                   int mask_offset_x, int mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                   int mi_x, int mi_y) {
 | 
			
		||||
  struct macroblockd_plane *const pd = &xd->plane[plane];
 | 
			
		||||
  const MODE_INFO *mi = xd->mi[0];
 | 
			
		||||
@@ -193,8 +533,27 @@ static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
 | 
			
		||||
    pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride
 | 
			
		||||
           + (scaled_mv.col >> SUBPEL_BITS);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    if (ref && get_mask_bits(mi->mbmi.sb_type)
 | 
			
		||||
        && mi->mbmi.use_masked_interinter) {
 | 
			
		||||
      uint8_t tmp_dst[4096];
 | 
			
		||||
      inter_predictor(pre, pre_buf->stride, tmp_dst, 64,
 | 
			
		||||
                     subpel_x, subpel_y, sf, w, h, 0, kernel, xs, ys);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
      build_masked_compound_extend(dst, dst_buf->stride, tmp_dst, 64, plane,
 | 
			
		||||
                                   mi->mbmi.mask_index, mi->mbmi.sb_type,
 | 
			
		||||
                                   mask_offset_x, mask_offset_y, h, w);
 | 
			
		||||
#else
 | 
			
		||||
      build_masked_compound(dst, dst_buf->stride, tmp_dst, 64,
 | 
			
		||||
                            mi->mbmi.mask_index, mi->mbmi.sb_type, h, w);
 | 
			
		||||
#endif
 | 
			
		||||
    } else {
 | 
			
		||||
#endif
 | 
			
		||||
    inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
 | 
			
		||||
                    subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -218,10 +577,18 @@ static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
 | 
			
		||||
      for (y = 0; y < num_4x4_h; ++y)
 | 
			
		||||
        for (x = 0; x < num_4x4_w; ++x)
 | 
			
		||||
           build_inter_predictors(xd, plane, i++, bw, bh,
 | 
			
		||||
                                  4 * x, 4 * y, 4, 4, mi_x, mi_y);
 | 
			
		||||
                                  4 * x, 4 * y, 4, 4,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                  0, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                                  mi_x, mi_y);
 | 
			
		||||
    } else {
 | 
			
		||||
      build_inter_predictors(xd, plane, 0, bw, bh,
 | 
			
		||||
                             0, 0, bw, bh, mi_x, mi_y);
 | 
			
		||||
                             0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             0, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -229,23 +596,323 @@ static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
 | 
			
		||||
void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
 | 
			
		||||
                                    BLOCK_SIZE bsize) {
 | 
			
		||||
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
 | 
			
		||||
      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
 | 
			
		||||
    vp9_build_interintra_predictors_sby(xd, xd->plane[0].dst.buf,
 | 
			
		||||
                                        xd->plane[0].dst.stride, bsize);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
 | 
			
		||||
                                     BLOCK_SIZE bsize) {
 | 
			
		||||
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
 | 
			
		||||
                                    MAX_MB_PLANE - 1);
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
 | 
			
		||||
      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
 | 
			
		||||
    vp9_build_interintra_predictors_sbuv(xd, xd->plane[1].dst.buf,
 | 
			
		||||
                                         xd->plane[2].dst.buf,
 | 
			
		||||
                                         xd->plane[1].dst.stride,
 | 
			
		||||
                                         xd->plane[2].dst.stride, bsize);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
 | 
			
		||||
                                   BLOCK_SIZE bsize) {
 | 
			
		||||
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
 | 
			
		||||
                                    MAX_MB_PLANE - 1);
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
 | 
			
		||||
      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
 | 
			
		||||
    vp9_build_interintra_predictors(xd, xd->plane[0].dst.buf,
 | 
			
		||||
                                    xd->plane[1].dst.buf, xd->plane[2].dst.buf,
 | 
			
		||||
                                    xd->plane[0].dst.stride,
 | 
			
		||||
                                    xd->plane[1].dst.stride,
 | 
			
		||||
                                    xd->plane[2].dst.stride, bsize);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static int get_masked_weight_supertx(int m) {
 | 
			
		||||
  #define SMOOTHER_LEN  32
 | 
			
		||||
  static const uint8_t smoothfn[2 * SMOOTHER_LEN + 1] = {
 | 
			
		||||
      0,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
      0,  0,  0,  0,  0,  1,  1,  1,
 | 
			
		||||
      1,  1,  2,  2,  3,  4,  5,  6,
 | 
			
		||||
      8,  9, 12, 14, 17, 21, 24, 28,
 | 
			
		||||
      32,
 | 
			
		||||
      36, 40, 43, 47, 50, 52, 55, 56,
 | 
			
		||||
      58, 59, 60, 61, 62, 62, 63, 63,
 | 
			
		||||
      63, 63, 63, 64, 64, 64, 64, 64,
 | 
			
		||||
      64, 64, 64, 64, 64, 64, 64, 64,
 | 
			
		||||
  };
 | 
			
		||||
  if (m < -SMOOTHER_LEN)
 | 
			
		||||
    return 0;
 | 
			
		||||
  else if (m > SMOOTHER_LEN)
 | 
			
		||||
    return 64;
 | 
			
		||||
  else
 | 
			
		||||
    return smoothfn[m + SMOOTHER_LEN];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const uint8_t mask_8[8] = {
 | 
			
		||||
  64, 64, 62, 52, 12,  2,  0,  0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint8_t mask_16[16] = {
 | 
			
		||||
  63, 62, 60, 58, 55, 50, 43, 36, 28, 21, 14, 9, 6, 4, 2, 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint8_t mask_32[32] = {
 | 
			
		||||
  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 61, 57, 52, 45, 36,
 | 
			
		||||
  28, 19, 12,  7,  3,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void generate_1dmask(int length, uint8_t *mask) {
 | 
			
		||||
  int i;
 | 
			
		||||
  switch (length) {
 | 
			
		||||
    case 8:
 | 
			
		||||
      vpx_memcpy(mask, mask_8, length);
 | 
			
		||||
      break;
 | 
			
		||||
    case 16:
 | 
			
		||||
      vpx_memcpy(mask, mask_16, length);
 | 
			
		||||
      break;
 | 
			
		||||
    case 32:
 | 
			
		||||
      vpx_memcpy(mask, mask_32, length);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
  }
 | 
			
		||||
  if (length > 16) {
 | 
			
		||||
    for (i = 0; i < length; ++i)
 | 
			
		||||
      mask[i] = get_masked_weight_supertx(-1 * (2 * i - length + 1));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_build_masked_inter_predictor_complex(uint8_t *dst, int dst_stride,
 | 
			
		||||
                                              uint8_t *dst2, int dst2_stride,
 | 
			
		||||
                                              int plane,
 | 
			
		||||
                                              int mi_row, int mi_col,
 | 
			
		||||
                                              int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                              BLOCK_SIZE bsize,
 | 
			
		||||
                                              BLOCK_SIZE top_bsize,
 | 
			
		||||
                                              PARTITION_TYPE partition) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  uint8_t mask[32];
 | 
			
		||||
  int top_w = 4 << b_width_log2(top_bsize),
 | 
			
		||||
      top_h = 4 << b_height_log2(top_bsize);
 | 
			
		||||
  int w = 4 << b_width_log2(bsize), h = 4 << b_height_log2(bsize);
 | 
			
		||||
  int w_offset = (mi_col - mi_col_ori) << 3,
 | 
			
		||||
      h_offset = (mi_row - mi_row_ori) << 3;
 | 
			
		||||
  int m;
 | 
			
		||||
 | 
			
		||||
  if (plane > 0) {
 | 
			
		||||
    top_w = top_w >> 1; top_h = top_h >> 1;
 | 
			
		||||
    w = w >> 1; h = h >> 1;
 | 
			
		||||
    w_offset = w_offset >> 1; h_offset = h_offset >> 1;
 | 
			
		||||
  }
 | 
			
		||||
  switch (partition) {
 | 
			
		||||
    case PARTITION_HORZ:
 | 
			
		||||
      generate_1dmask(h, mask + h_offset);
 | 
			
		||||
      vpx_memset(mask, 64, h_offset);
 | 
			
		||||
      vpx_memset(mask + h_offset + h, 0, top_h - h_offset - h);
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_VERT:
 | 
			
		||||
      generate_1dmask(w, mask + w_offset);
 | 
			
		||||
      vpx_memset(mask, 64, w_offset);
 | 
			
		||||
      vpx_memset(mask + w_offset + w, 0, top_w - w_offset - w);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
  }
 | 
			
		||||
  for (i = 0; i < top_h; ++i)
 | 
			
		||||
    for (j = 0; j < top_w; ++j) {
 | 
			
		||||
      m = partition == PARTITION_HORZ ? mask[i] : mask[j];
 | 
			
		||||
      if (m == 64)
 | 
			
		||||
        continue;
 | 
			
		||||
      if (m == 0)
 | 
			
		||||
        dst[i * dst_stride + j] = dst2[i * dst2_stride + j];
 | 
			
		||||
      else
 | 
			
		||||
        dst[i * dst_stride + j] = (dst[i * dst_stride + j] * m +
 | 
			
		||||
                                  dst2[i * dst2_stride + j] *
 | 
			
		||||
                                  (64 - m) + 32) >> 6;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
void vp9_build_inter_predictors_sb_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                          int mi_row, int mi_col,
 | 
			
		||||
                                          int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                          BLOCK_SIZE bsize) {
 | 
			
		||||
  int plane;
 | 
			
		||||
  const int mi_x = mi_col_ori * MI_SIZE;
 | 
			
		||||
  const int mi_y = mi_row_ori * MI_SIZE;
 | 
			
		||||
  const int mask_offset_x = (mi_col - mi_col_ori) * MI_SIZE;
 | 
			
		||||
  const int mask_offset_y = (mi_row - mi_row_ori) * MI_SIZE;
 | 
			
		||||
  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
 | 
			
		||||
    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize,
 | 
			
		||||
                                                        &xd->plane[plane]);
 | 
			
		||||
    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
 | 
			
		||||
    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
 | 
			
		||||
    const int bw = 4 * num_4x4_w;
 | 
			
		||||
    const int bh = 4 * num_4x4_h;
 | 
			
		||||
 | 
			
		||||
    if (xd->mi[0]->mbmi.sb_type < BLOCK_8X8) {
 | 
			
		||||
      int i = 0, x, y;
 | 
			
		||||
      assert(bsize == BLOCK_8X8);
 | 
			
		||||
      for (y = 0; y < num_4x4_h; ++y)
 | 
			
		||||
        for (x = 0; x < num_4x4_w; ++x)
 | 
			
		||||
           build_inter_predictors(xd, plane, i++, bw, bh, 4 * x, 4 * y, 4, 4,
 | 
			
		||||
                                  mask_offset_x, mask_offset_y, mi_x, mi_y);
 | 
			
		||||
    } else {
 | 
			
		||||
      build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
                             mask_offset_x, mask_offset_y, mi_x, mi_y);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_build_inter_predictors_sby_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                                  int mi_row, int mi_col,
 | 
			
		||||
                                                  int mi_row_ori,
 | 
			
		||||
                                                  int mi_col_ori,
 | 
			
		||||
                                                  BLOCK_SIZE top_bsize,
 | 
			
		||||
                                                  PARTITION_TYPE partition) {
 | 
			
		||||
  const int mi_x = mi_col_ori * MI_SIZE;
 | 
			
		||||
  const int mi_y = mi_row_ori * MI_SIZE;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  const int mask_offset_x = (mi_col - mi_col_ori) * MI_SIZE;
 | 
			
		||||
  const int mask_offset_y = (mi_row - mi_row_ori) * MI_SIZE;
 | 
			
		||||
#endif
 | 
			
		||||
  uint8_t *orig_dst;
 | 
			
		||||
  int orig_dst_stride;
 | 
			
		||||
  int bw = 4 << b_width_log2(top_bsize);
 | 
			
		||||
  int bh = 4 << b_height_log2(top_bsize);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf, 32 * 32);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf1, 32 * 32);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf2, 32 * 32);
 | 
			
		||||
 | 
			
		||||
  orig_dst = xd->plane[0].dst.buf;
 | 
			
		||||
  orig_dst_stride = xd->plane[0].dst.stride;
 | 
			
		||||
  build_inter_predictors(xd, 0, 0, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                         mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                         mi_x, mi_y);
 | 
			
		||||
 | 
			
		||||
  xd->plane[0].dst.buf = tmp_buf;
 | 
			
		||||
  xd->plane[0].dst.stride = 32;
 | 
			
		||||
  switch (partition) {
 | 
			
		||||
    case PARTITION_HORZ:
 | 
			
		||||
      build_inter_predictors(xd, 0, 2, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_VERT:
 | 
			
		||||
      build_inter_predictors(xd, 0, 1, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_SPLIT:
 | 
			
		||||
      build_inter_predictors(xd, 0, 1, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
      xd->plane[0].dst.buf = tmp_buf1;
 | 
			
		||||
      xd->plane[0].dst.stride = 32;
 | 
			
		||||
      build_inter_predictors(xd, 0, 2, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
      xd->plane[0].dst.buf = tmp_buf2;
 | 
			
		||||
      xd->plane[0].dst.stride = 32;
 | 
			
		||||
      build_inter_predictors(xd, 0, 3, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (partition != PARTITION_SPLIT) {
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(orig_dst, orig_dst_stride,
 | 
			
		||||
                                             tmp_buf, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             partition);
 | 
			
		||||
    xd->plane[0].dst.buf = orig_dst;
 | 
			
		||||
    xd->plane[0].dst.stride = orig_dst_stride;
 | 
			
		||||
  } else {
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(orig_dst, orig_dst_stride,
 | 
			
		||||
                                             tmp_buf, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             PARTITION_VERT);
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(tmp_buf1, 32,
 | 
			
		||||
                                             tmp_buf2, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             PARTITION_VERT);
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(orig_dst, orig_dst_stride,
 | 
			
		||||
                                             tmp_buf1, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             PARTITION_HORZ);
 | 
			
		||||
    xd->plane[0].dst.buf = orig_dst;
 | 
			
		||||
    xd->plane[0].dst.stride = orig_dst_stride;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_build_inter_predictors_sbuv_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                                   int mi_row, int mi_col,
 | 
			
		||||
#endif
 | 
			
		||||
                                                   int mi_row_ori,
 | 
			
		||||
                                                   int mi_col_ori,
 | 
			
		||||
                                                   BLOCK_SIZE top_bsize) {
 | 
			
		||||
  int plane;
 | 
			
		||||
  const int mi_x = mi_col_ori * MI_SIZE;
 | 
			
		||||
  const int mi_y = mi_row_ori * MI_SIZE;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  const int mask_offset_x = (mi_col - mi_col_ori) * MI_SIZE;
 | 
			
		||||
  const int mask_offset_y = (mi_row - mi_row_ori) * MI_SIZE;
 | 
			
		||||
#endif
 | 
			
		||||
  for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
 | 
			
		||||
    const BLOCK_SIZE plane_bsize = get_plane_block_size(top_bsize,
 | 
			
		||||
                                                        &xd->plane[plane]);
 | 
			
		||||
    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
 | 
			
		||||
    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
 | 
			
		||||
    const int bw = 4 * num_4x4_w;
 | 
			
		||||
    const int bh = 4 * num_4x4_h;
 | 
			
		||||
 | 
			
		||||
    build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                           mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                           mi_x, mi_y);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// TODO(jingning): This function serves as a placeholder for decoder prediction
 | 
			
		||||
// using on demand border extension. It should be moved to /decoder/ directory.
 | 
			
		||||
static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
 | 
			
		||||
                                       int bw, int bh,
 | 
			
		||||
                                       int x, int y, int w, int h,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                       int mask_offset_x, int mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                       int mi_x, int mi_y) {
 | 
			
		||||
  struct macroblockd_plane *const pd = &xd->plane[plane];
 | 
			
		||||
  const MODE_INFO *mi = xd->mi[0];
 | 
			
		||||
@@ -377,8 +1044,27 @@ static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    if (ref && get_mask_bits(mi->mbmi.sb_type)
 | 
			
		||||
        && mi->mbmi.use_masked_interinter) {
 | 
			
		||||
      uint8_t tmp_dst[4096];
 | 
			
		||||
      inter_predictor(buf_ptr, buf_stride, tmp_dst, 64,
 | 
			
		||||
                     subpel_x, subpel_y, sf, w, h, 0, kernel, xs, ys);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
      build_masked_compound_extend(dst, dst_buf->stride, tmp_dst, 64, plane,
 | 
			
		||||
                                   mi->mbmi.mask_index, mi->mbmi.sb_type,
 | 
			
		||||
                                   mask_offset_x, mask_offset_y, h, w);
 | 
			
		||||
#else
 | 
			
		||||
      build_masked_compound(dst, dst_buf->stride, tmp_dst, 64,
 | 
			
		||||
                            mi->mbmi.mask_index, mi->mbmi.sb_type, h, w);
 | 
			
		||||
#endif
 | 
			
		||||
    } else {
 | 
			
		||||
#endif
 | 
			
		||||
    inter_predictor(buf_ptr, buf_stride, dst, dst_buf->stride, subpel_x,
 | 
			
		||||
                    subpel_y, sf, w, h, ref, kernel, xs, ys);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -401,13 +1087,198 @@ void vp9_dec_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
 | 
			
		||||
      for (y = 0; y < num_4x4_h; ++y)
 | 
			
		||||
        for (x = 0; x < num_4x4_w; ++x)
 | 
			
		||||
          dec_build_inter_predictors(xd, plane, i++, bw, bh,
 | 
			
		||||
                                     4 * x, 4 * y, 4, 4, mi_x, mi_y);
 | 
			
		||||
                                     4 * x, 4 * y, 4, 4,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                     0, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                                     mi_x, mi_y);
 | 
			
		||||
    } else {
 | 
			
		||||
      dec_build_inter_predictors(xd, plane, 0, bw, bh,
 | 
			
		||||
                                 0, 0, bw, bh, mi_x, mi_y);
 | 
			
		||||
                                 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                 0, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                                 mi_x, mi_y);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
 | 
			
		||||
      is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
 | 
			
		||||
    vp9_build_interintra_predictors(xd, xd->plane[0].dst.buf,
 | 
			
		||||
                                    xd->plane[1].dst.buf, xd->plane[2].dst.buf,
 | 
			
		||||
                                    xd->plane[0].dst.stride,
 | 
			
		||||
                                    xd->plane[1].dst.stride,
 | 
			
		||||
                                    xd->plane[2].dst.stride, bsize);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
void vp9_dec_build_inter_predictors_sb_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                              int mi_row, int mi_col,
 | 
			
		||||
                                              int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                              BLOCK_SIZE bsize) {
 | 
			
		||||
  int plane;
 | 
			
		||||
  const int mi_x = mi_col_ori * MI_SIZE;
 | 
			
		||||
  const int mi_y = mi_row_ori * MI_SIZE;
 | 
			
		||||
  const int mask_offset_x = (mi_col - mi_col_ori) * MI_SIZE;
 | 
			
		||||
  const int mask_offset_y = (mi_row - mi_row_ori) * MI_SIZE;
 | 
			
		||||
  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
 | 
			
		||||
    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize,
 | 
			
		||||
                                                        &xd->plane[plane]);
 | 
			
		||||
    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
 | 
			
		||||
    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
 | 
			
		||||
    const int bw = 4 * num_4x4_w;
 | 
			
		||||
    const int bh = 4 * num_4x4_h;
 | 
			
		||||
 | 
			
		||||
    if (xd->mi[0]->mbmi.sb_type < BLOCK_8X8) {
 | 
			
		||||
      int i = 0, x, y;
 | 
			
		||||
      assert(bsize == BLOCK_8X8);
 | 
			
		||||
      for (y = 0; y < num_4x4_h; ++y)
 | 
			
		||||
        for (x = 0; x < num_4x4_w; ++x)
 | 
			
		||||
          dec_build_inter_predictors(xd, plane, i++, bw, bh, 4 * x, 4 * y, 4, 4,
 | 
			
		||||
                                     mask_offset_x, mask_offset_y, mi_x, mi_y);
 | 
			
		||||
    } else {
 | 
			
		||||
      dec_build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
                                 mask_offset_x, mask_offset_y, mi_x, mi_y);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_dec_build_inter_predictors_sby_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                                  int mi_row, int mi_col,
 | 
			
		||||
                                                  int mi_row_ori,
 | 
			
		||||
                                                  int mi_col_ori,
 | 
			
		||||
                                                  BLOCK_SIZE top_bsize,
 | 
			
		||||
                                                  PARTITION_TYPE partition) {
 | 
			
		||||
  const int mi_x = mi_col_ori * MI_SIZE;
 | 
			
		||||
  const int mi_y = mi_row_ori * MI_SIZE;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  const int mask_offset_x = (mi_col - mi_col_ori) * MI_SIZE;
 | 
			
		||||
  const int mask_offset_y = (mi_row - mi_row_ori) * MI_SIZE;
 | 
			
		||||
#endif
 | 
			
		||||
  uint8_t *orig_dst;
 | 
			
		||||
  int orig_dst_stride;
 | 
			
		||||
  int bw = 4 << b_width_log2(top_bsize);
 | 
			
		||||
  int bh = 4 << b_height_log2(top_bsize);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf, 32 * 32);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf1, 32 * 32);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf2, 32 * 32);
 | 
			
		||||
 | 
			
		||||
  orig_dst = xd->plane[0].dst.buf;
 | 
			
		||||
  orig_dst_stride = xd->plane[0].dst.stride;
 | 
			
		||||
  dec_build_inter_predictors(xd, 0, 0, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                             mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                             mi_x, mi_y);
 | 
			
		||||
 | 
			
		||||
  xd->plane[0].dst.buf = tmp_buf;
 | 
			
		||||
  xd->plane[0].dst.stride = 32;
 | 
			
		||||
  switch (partition) {
 | 
			
		||||
    case PARTITION_HORZ:
 | 
			
		||||
      dec_build_inter_predictors(xd, 0, 2, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                 mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                 mi_x, mi_y);
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_VERT:
 | 
			
		||||
      dec_build_inter_predictors(xd, 0, 1, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                 mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                 mi_x, mi_y);
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_SPLIT:
 | 
			
		||||
      dec_build_inter_predictors(xd, 0, 1, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                 mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                 mi_x, mi_y);
 | 
			
		||||
      xd->plane[0].dst.buf = tmp_buf1;
 | 
			
		||||
      xd->plane[0].dst.stride = 32;
 | 
			
		||||
      dec_build_inter_predictors(xd, 0, 2, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                 mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                 mi_x, mi_y);
 | 
			
		||||
      xd->plane[0].dst.buf = tmp_buf2;
 | 
			
		||||
      xd->plane[0].dst.stride = 32;
 | 
			
		||||
      dec_build_inter_predictors(xd, 0, 3, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                 mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                                 mi_x, mi_y);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (partition != PARTITION_SPLIT) {
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(orig_dst, orig_dst_stride,
 | 
			
		||||
                                             tmp_buf, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             partition);
 | 
			
		||||
    xd->plane[0].dst.buf = orig_dst;
 | 
			
		||||
    xd->plane[0].dst.stride = orig_dst_stride;
 | 
			
		||||
  } else {
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(orig_dst, orig_dst_stride,
 | 
			
		||||
                                             tmp_buf, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             PARTITION_VERT);
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(tmp_buf1, 32,
 | 
			
		||||
                                             tmp_buf2, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             PARTITION_VERT);
 | 
			
		||||
    vp9_build_masked_inter_predictor_complex(orig_dst, orig_dst_stride,
 | 
			
		||||
                                             tmp_buf1, 32,
 | 
			
		||||
                                             0, mi_row, mi_col,
 | 
			
		||||
                                             mi_row_ori, mi_col_ori,
 | 
			
		||||
                                             BLOCK_8X8, top_bsize,
 | 
			
		||||
                                             PARTITION_HORZ);
 | 
			
		||||
    xd->plane[0].dst.buf = orig_dst;
 | 
			
		||||
    xd->plane[0].dst.stride = orig_dst_stride;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_dec_build_inter_predictors_sbuv_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                                       int mi_row, int mi_col,
 | 
			
		||||
#endif
 | 
			
		||||
                                                       int mi_row_ori,
 | 
			
		||||
                                                       int mi_col_ori,
 | 
			
		||||
                                                       BLOCK_SIZE top_bsize) {
 | 
			
		||||
  int plane;
 | 
			
		||||
  const int mi_x = mi_col_ori * MI_SIZE;
 | 
			
		||||
  const int mi_y = mi_row_ori * MI_SIZE;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  const int mask_offset_x = (mi_col - mi_col_ori) * MI_SIZE;
 | 
			
		||||
  const int mask_offset_y = (mi_row - mi_row_ori) * MI_SIZE;
 | 
			
		||||
#endif
 | 
			
		||||
  for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
 | 
			
		||||
    const BLOCK_SIZE plane_bsize = get_plane_block_size(top_bsize,
 | 
			
		||||
                                                        &xd->plane[plane]);
 | 
			
		||||
    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
 | 
			
		||||
    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
 | 
			
		||||
    const int bw = 4 * num_4x4_w;
 | 
			
		||||
    const int bh = 4 * num_4x4_h;
 | 
			
		||||
 | 
			
		||||
    dec_build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                               mask_offset_x, mask_offset_y,
 | 
			
		||||
#endif
 | 
			
		||||
                               mi_x, mi_y);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
 | 
			
		||||
                          const YV12_BUFFER_CONFIG *src,
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,60 @@ void vp9_setup_pre_planes(MACROBLOCKD *xd, int idx,
 | 
			
		||||
                          const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
 | 
			
		||||
                          const struct scale_factors *sf);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
void vp9_generate_masked_weight(int mask_index, BLOCK_SIZE sb_type,
 | 
			
		||||
                              int h, int w, uint8_t *mask, int stride);
 | 
			
		||||
void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
 | 
			
		||||
                          int h, int w, uint8_t *mask, int stride);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void vp9_build_inter_predictors_sby_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                                  int mi_row, int mi_col,
 | 
			
		||||
                                                  int mi_row_ori,
 | 
			
		||||
                                                  int mi_col_ori,
 | 
			
		||||
                                                  BLOCK_SIZE top_bsize,
 | 
			
		||||
                                                  PARTITION_TYPE partition);
 | 
			
		||||
void vp9_build_inter_predictors_sbuv_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                                   int mi_row, int mi_col,
 | 
			
		||||
#endif
 | 
			
		||||
                                                   int mi_row_ori,
 | 
			
		||||
                                                   int mi_col_ori,
 | 
			
		||||
                                                   BLOCK_SIZE top_bsize);
 | 
			
		||||
void vp9_build_masked_inter_predictor_complex(uint8_t *dst, int dst_stride,
 | 
			
		||||
                                              uint8_t *dst2, int dst2_stride,
 | 
			
		||||
                                              int plane,
 | 
			
		||||
                                              int mi_row, int mi_col,
 | 
			
		||||
                                              int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                              BLOCK_SIZE bsize,
 | 
			
		||||
                                              BLOCK_SIZE top_bsize,
 | 
			
		||||
                                              PARTITION_TYPE partition);
 | 
			
		||||
void vp9_dec_build_inter_predictors_sby_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                                      int mi_row, int mi_col,
 | 
			
		||||
                                                      int mi_row_ori,
 | 
			
		||||
                                                      int mi_col_ori,
 | 
			
		||||
                                                      BLOCK_SIZE top_bsize,
 | 
			
		||||
                                                      PARTITION_TYPE p);
 | 
			
		||||
void vp9_dec_build_inter_predictors_sbuv_sub8x8_extend(MACROBLOCKD *xd,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                                       int mi_row, int mi_col,
 | 
			
		||||
#endif
 | 
			
		||||
                                                       int mi_row_ori,
 | 
			
		||||
                                                       int mi_col_ori,
 | 
			
		||||
                                                       BLOCK_SIZE top_bsize);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
void vp9_build_inter_predictors_sb_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                          int mi_row, int mi_col,
 | 
			
		||||
                                          int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                          BLOCK_SIZE bsize);
 | 
			
		||||
void vp9_dec_build_inter_predictors_sb_extend(MACROBLOCKD *xd,
 | 
			
		||||
                                              int mi_row, int mi_col,
 | 
			
		||||
                                              int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                              BLOCK_SIZE bsize);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -444,8 +444,227 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
static void filter_intra_predictors_4tap(uint8_t *ypred_ptr, int y_stride,
 | 
			
		||||
                                         int bs,
 | 
			
		||||
                                         const uint8_t *yabove_row,
 | 
			
		||||
                                         const uint8_t *yleft_col,
 | 
			
		||||
                                         int mode) {
 | 
			
		||||
  static const int prec_bits = 10;
 | 
			
		||||
  static const int round_val = 511;
 | 
			
		||||
 | 
			
		||||
  int k, r, c;
 | 
			
		||||
  int pred[33][33];
 | 
			
		||||
  int mean, ipred;
 | 
			
		||||
 | 
			
		||||
  int taps4_4[10][4] = {
 | 
			
		||||
      {735, 881, -537, -54},
 | 
			
		||||
      {1005, 519, -488, -11},
 | 
			
		||||
      {383, 990, -343, -6},
 | 
			
		||||
      {442, 805, -542, 319},
 | 
			
		||||
      {658, 616, -133, -116},
 | 
			
		||||
      {875, 442, -141, -151},
 | 
			
		||||
      {386, 741, -23, -80},
 | 
			
		||||
      {390, 1027, -446, 51},
 | 
			
		||||
      {679, 606, -523, 262},
 | 
			
		||||
      {903, 922, -778, -23}
 | 
			
		||||
  };
 | 
			
		||||
  int taps4_8[10][4] = {
 | 
			
		||||
      {648, 803, -444, 16},
 | 
			
		||||
      {972, 620, -576, 7},
 | 
			
		||||
      {561, 967, -499, -5},
 | 
			
		||||
      {585, 762, -468, 144},
 | 
			
		||||
      {596, 619, -182, -9},
 | 
			
		||||
      {895, 459, -176, -153},
 | 
			
		||||
      {557, 722, -126, -129},
 | 
			
		||||
      {601, 839, -523, 105},
 | 
			
		||||
      {562, 709, -499, 251},
 | 
			
		||||
      {803, 872, -695, 43}
 | 
			
		||||
  };
 | 
			
		||||
  int taps4_16[10][4] = {
 | 
			
		||||
      {423, 728, -347, 111},
 | 
			
		||||
      {963, 685, -665, 23},
 | 
			
		||||
      {281, 1024, -480, 216},
 | 
			
		||||
      {640, 596, -437, 78},
 | 
			
		||||
      {429, 669, -259, 99},
 | 
			
		||||
      {740, 646, -415, 23},
 | 
			
		||||
      {568, 771, -346, 40},
 | 
			
		||||
      {404, 833, -486, 209},
 | 
			
		||||
      {398, 712, -423, 307},
 | 
			
		||||
      {939, 935, -887, 17}
 | 
			
		||||
  };
 | 
			
		||||
  int taps4_32[10][4] = {
 | 
			
		||||
      {477, 737, -393, 150},
 | 
			
		||||
      {881, 630, -546, 67},
 | 
			
		||||
      {506, 984, -443, -20},
 | 
			
		||||
      {114, 459, -270, 528},
 | 
			
		||||
      {433, 528, 14, 3},
 | 
			
		||||
      {837, 470, -301, -30},
 | 
			
		||||
      {181, 777, 89, -107},
 | 
			
		||||
      {-29, 716, -232, 259},
 | 
			
		||||
      {589, 646, -495, 255},
 | 
			
		||||
      {740, 884, -728, 77}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const int c1 = (bs >= 32) ? taps4_32[mode][0] : ((bs >= 16) ?
 | 
			
		||||
      taps4_16[mode][0] : ((bs >= 8) ? taps4_8[mode][0] : taps4_4[mode][0]));
 | 
			
		||||
  const int c2 = (bs >= 32) ? taps4_32[mode][1] : ((bs >= 16) ?
 | 
			
		||||
      taps4_16[mode][1] : ((bs >= 8) ? taps4_8[mode][1] : taps4_4[mode][1]));
 | 
			
		||||
  const int c3 = (bs >= 32) ? taps4_32[mode][2] : ((bs >= 16) ?
 | 
			
		||||
      taps4_16[mode][2] : ((bs >= 8) ? taps4_8[mode][2] : taps4_4[mode][2]));
 | 
			
		||||
  const int c4 = (bs >= 32) ? taps4_32[mode][3] : ((bs >= 16) ?
 | 
			
		||||
      taps4_16[mode][3] : ((bs >= 8) ? taps4_8[mode][3] : taps4_4[mode][3]));
 | 
			
		||||
 | 
			
		||||
  k = 0;
 | 
			
		||||
  mean = 0;
 | 
			
		||||
  while (k < bs) {
 | 
			
		||||
    mean = mean + (int)yleft_col[k];
 | 
			
		||||
    mean = mean + (int)yabove_row[k];
 | 
			
		||||
    k++;
 | 
			
		||||
  }
 | 
			
		||||
  mean = (mean + bs) / (2 * bs);
 | 
			
		||||
 | 
			
		||||
  for (r = 0; r < bs; r++)
 | 
			
		||||
    pred[r + 1][0] = (int)yleft_col[r] - mean;
 | 
			
		||||
 | 
			
		||||
  for (c = 0; c < 2 * bs + 1; c++)
 | 
			
		||||
    pred[0][c] = (int)yabove_row[c - 1] - mean;
 | 
			
		||||
 | 
			
		||||
  for (r = 1; r < bs + 1; r++)
 | 
			
		||||
    for (c = 1; c < 2 * bs + 1 - r; c++) {
 | 
			
		||||
      ipred = c1 * pred[r - 1][c] + c2 * pred[r][c - 1]
 | 
			
		||||
                    + c3 * pred[r - 1][c - 1] + c4 * pred[r - 1][c + 1];
 | 
			
		||||
      pred[r][c] = ipred < 0 ? -((-ipred + round_val) >> prec_bits) :
 | 
			
		||||
                               ((ipred + round_val) >> prec_bits);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (r = 0; r < bs; r++) {
 | 
			
		||||
    for (c = 0; c < bs; c++) {
 | 
			
		||||
      ipred = pred[r + 1][c + 1] + mean;
 | 
			
		||||
      ypred_ptr[c] = clip_pixel(ipred);
 | 
			
		||||
    }
 | 
			
		||||
    ypred_ptr += y_stride;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void build_filter_intra_predictors(const MACROBLOCKD *xd,
 | 
			
		||||
                                          const uint8_t *ref, int ref_stride,
 | 
			
		||||
                                          uint8_t *dst, int dst_stride,
 | 
			
		||||
                                          PREDICTION_MODE mode, TX_SIZE tx_size,
 | 
			
		||||
                                          int up_available, int left_available,
 | 
			
		||||
                                          int right_available, int x, int y,
 | 
			
		||||
                                          int plane) {
 | 
			
		||||
  int i;
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
 | 
			
		||||
  uint8_t *above_row = above_data + 16;
 | 
			
		||||
  const uint8_t *const_above_row = above_row;
 | 
			
		||||
  const int bs = 4 << tx_size;
 | 
			
		||||
  int frame_width, frame_height;
 | 
			
		||||
  int x0, y0;
 | 
			
		||||
  const struct macroblockd_plane *const pd = &xd->plane[plane];
 | 
			
		||||
 | 
			
		||||
  // Get current frame pointer, width and height.
 | 
			
		||||
  if (plane == 0) {
 | 
			
		||||
    frame_width = xd->cur_buf->y_width;
 | 
			
		||||
    frame_height = xd->cur_buf->y_height;
 | 
			
		||||
  } else {
 | 
			
		||||
    frame_width = xd->cur_buf->uv_width;
 | 
			
		||||
    frame_height = xd->cur_buf->uv_height;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Get block position in current frame.
 | 
			
		||||
  x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
 | 
			
		||||
  y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
 | 
			
		||||
 | 
			
		||||
  vpx_memset(left_col, 129, 64);
 | 
			
		||||
 | 
			
		||||
  // left
 | 
			
		||||
  if (left_available) {
 | 
			
		||||
    if (xd->mb_to_bottom_edge < 0) {
 | 
			
		||||
      /* slower path if the block needs border extension */
 | 
			
		||||
      if (y0 + bs <= frame_height) {
 | 
			
		||||
        for (i = 0; i < bs; ++i)
 | 
			
		||||
          left_col[i] = ref[i * ref_stride - 1];
 | 
			
		||||
      } else {
 | 
			
		||||
        const int extend_bottom = frame_height - y0;
 | 
			
		||||
        for (i = 0; i < extend_bottom; ++i)
 | 
			
		||||
          left_col[i] = ref[i * ref_stride - 1];
 | 
			
		||||
        for (; i < bs; ++i)
 | 
			
		||||
          left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      /* faster path if the block does not need extension */
 | 
			
		||||
      for (i = 0; i < bs; ++i)
 | 
			
		||||
        left_col[i] = ref[i * ref_stride - 1];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // TODO(hkuang) do not extend 2*bs pixels for all modes.
 | 
			
		||||
  // above
 | 
			
		||||
  if (up_available) {
 | 
			
		||||
    const uint8_t *above_ref = ref - ref_stride;
 | 
			
		||||
    if (xd->mb_to_right_edge < 0) {
 | 
			
		||||
      /* slower path if the block needs border extension */
 | 
			
		||||
      if (x0 + 2 * bs <= frame_width) {
 | 
			
		||||
        if (right_available && bs == 4) {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, 2 * bs);
 | 
			
		||||
        } else {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, bs);
 | 
			
		||||
          vpx_memset(above_row + bs, above_row[bs - 1], bs);
 | 
			
		||||
        }
 | 
			
		||||
      } else if (x0 + bs <= frame_width) {
 | 
			
		||||
        const int r = frame_width - x0;
 | 
			
		||||
        if (right_available && bs == 4) {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, r);
 | 
			
		||||
          vpx_memset(above_row + r, above_row[r - 1],
 | 
			
		||||
                     x0 + 2 * bs - frame_width);
 | 
			
		||||
        } else {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, bs);
 | 
			
		||||
          vpx_memset(above_row + bs, above_row[bs - 1], bs);
 | 
			
		||||
        }
 | 
			
		||||
      } else if (x0 <= frame_width) {
 | 
			
		||||
        const int r = frame_width - x0;
 | 
			
		||||
        if (right_available && bs == 4) {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, r);
 | 
			
		||||
          vpx_memset(above_row + r, above_row[r - 1],
 | 
			
		||||
                     x0 + 2 * bs - frame_width);
 | 
			
		||||
        } else {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, r);
 | 
			
		||||
          vpx_memset(above_row + r, above_row[r - 1],
 | 
			
		||||
                     x0 + 2 * bs - frame_width);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      above_row[-1] = left_available ? above_ref[-1] : 129;
 | 
			
		||||
    } else {
 | 
			
		||||
      /* faster path if the block does not need extension */
 | 
			
		||||
      if (bs == 4 && right_available && left_available) {
 | 
			
		||||
        const_above_row = above_ref;
 | 
			
		||||
      } else {
 | 
			
		||||
        vpx_memcpy(above_row, above_ref, bs);
 | 
			
		||||
        if (bs == 4 && right_available)
 | 
			
		||||
          vpx_memcpy(above_row + bs, above_ref + bs, bs);
 | 
			
		||||
        else
 | 
			
		||||
          vpx_memset(above_row + bs, above_row[bs - 1], bs);
 | 
			
		||||
        above_row[-1] = left_available ? above_ref[-1] : 129;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    vpx_memset(above_row, 127, bs * 2);
 | 
			
		||||
    above_row[-1] = 127;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // predict
 | 
			
		||||
  filter_intra_predictors_4tap(dst, dst_stride, bs, const_above_row, left_col,
 | 
			
		||||
                               mode);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
 | 
			
		||||
                             TX_SIZE tx_size, PREDICTION_MODE mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                             int filterbit,
 | 
			
		||||
#endif
 | 
			
		||||
                             const uint8_t *ref, int ref_stride,
 | 
			
		||||
                             uint8_t *dst, int dst_stride,
 | 
			
		||||
                             int aoff, int loff, int plane) {
 | 
			
		||||
@@ -456,8 +675,708 @@ void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
 | 
			
		||||
  const int have_right = ((block_idx & wmask) != wmask);
 | 
			
		||||
  const int x = aoff * 4;
 | 
			
		||||
  const int y = loff * 4;
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  const int filterflag = is_filter_allowed(mode) && is_filter_enabled(tx_size)
 | 
			
		||||
                         && filterbit;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  assert(bwl >= 0);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  if (!filterflag) {
 | 
			
		||||
#endif
 | 
			
		||||
  build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
 | 
			
		||||
                         have_top, have_left, have_right, x, y, plane);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  } else {
 | 
			
		||||
    build_filter_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode,
 | 
			
		||||
                        tx_size, have_top, have_left, have_right, x, y, plane);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
#define MASK_WEIGHT_BITS_INTERINTRA 6
 | 
			
		||||
 | 
			
		||||
static int get_masked_weight_interintra(int m) {
 | 
			
		||||
  #define SMOOTHER_LEN_INTERINTRA  32
 | 
			
		||||
  static const uint8_t smoothfn[2 * SMOOTHER_LEN_INTERINTRA + 1] = {
 | 
			
		||||
      0,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
      0,  0,  0,  0,  0,  1,  1,  1,
 | 
			
		||||
      1,  1,  2,  2,  3,  4,  5,  6,
 | 
			
		||||
      8,  9, 12, 14, 17, 21, 24, 28,
 | 
			
		||||
      32,
 | 
			
		||||
      36, 40, 43, 47, 50, 52, 55, 56,
 | 
			
		||||
      58, 59, 60, 61, 62, 62, 63, 63,
 | 
			
		||||
      63, 63, 63, 64, 64, 64, 64, 64,
 | 
			
		||||
      64, 64, 64, 64, 64, 64, 64, 64,
 | 
			
		||||
  };
 | 
			
		||||
  if (m < -SMOOTHER_LEN_INTERINTRA)
 | 
			
		||||
    return 0;
 | 
			
		||||
  else if (m > SMOOTHER_LEN_INTERINTRA)
 | 
			
		||||
    return (1 << MASK_WEIGHT_BITS_INTERINTRA);
 | 
			
		||||
  else
 | 
			
		||||
    return smoothfn[m + SMOOTHER_LEN_INTERINTRA];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_hard_mask_interintra(int m) {
 | 
			
		||||
  return m > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
 | 
			
		||||
// The soft mask is obtained by computing f(x, y) and then calling
 | 
			
		||||
// get_masked_weight(f(x, y)).
 | 
			
		||||
static const int mask_params_sml_interintra[1 << MASK_BITS_SML_INTERINTRA]
 | 
			
		||||
                                            [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_med_hgtw_interintra[1 << MASK_BITS_MED_INTERINTRA]
 | 
			
		||||
                                                 [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_med_hltw_interintra[1 << MASK_BITS_MED_INTERINTRA]
 | 
			
		||||
                                                 [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_med_heqw_interintra[1 << MASK_BITS_MED_INTERINTRA]
 | 
			
		||||
                                                 [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 1},
 | 
			
		||||
  { 0, -2, 0, 1},
 | 
			
		||||
  { 0,  2, 0, 3},
 | 
			
		||||
  { 0, -2, 0, 3},
 | 
			
		||||
  { 2,  0, 1, 0},
 | 
			
		||||
  {-2,  0, 1, 0},
 | 
			
		||||
  { 2,  0, 3, 0},
 | 
			
		||||
  {-2,  0, 3, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_big_hgtw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
 | 
			
		||||
                                                 [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 1},
 | 
			
		||||
  { 0, -2, 0, 1},
 | 
			
		||||
  { 0,  2, 0, 2},
 | 
			
		||||
  { 0, -2, 0, 2},
 | 
			
		||||
  { 0,  2, 0, 3},
 | 
			
		||||
  { 0, -2, 0, 3},
 | 
			
		||||
  { 2,  0, 2, 0},
 | 
			
		||||
  {-2,  0, 2, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_big_hltw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
 | 
			
		||||
                                                 [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 2},
 | 
			
		||||
  { 0, -2, 0, 2},
 | 
			
		||||
  { 2,  0, 1, 0},
 | 
			
		||||
  {-2,  0, 1, 0},
 | 
			
		||||
  { 2,  0, 2, 0},
 | 
			
		||||
  {-2,  0, 2, 0},
 | 
			
		||||
  { 2,  0, 3, 0},
 | 
			
		||||
  {-2,  0, 3, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int mask_params_big_heqw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
 | 
			
		||||
                                                 [4] = {
 | 
			
		||||
  {-1,  2, 2, 2},
 | 
			
		||||
  { 1, -2, 2, 2},
 | 
			
		||||
  {-2,  1, 2, 2},
 | 
			
		||||
  { 2, -1, 2, 2},
 | 
			
		||||
  { 2,  1, 2, 2},
 | 
			
		||||
  {-2, -1, 2, 2},
 | 
			
		||||
  { 1,  2, 2, 2},
 | 
			
		||||
  {-1, -2, 2, 2},
 | 
			
		||||
 | 
			
		||||
  {-1,  2, 2, 1},
 | 
			
		||||
  { 1, -2, 2, 1},
 | 
			
		||||
  {-1,  2, 2, 3},
 | 
			
		||||
  { 1, -2, 2, 3},
 | 
			
		||||
  { 1,  2, 2, 1},
 | 
			
		||||
  {-1, -2, 2, 1},
 | 
			
		||||
  { 1,  2, 2, 3},
 | 
			
		||||
  {-1, -2, 2, 3},
 | 
			
		||||
 | 
			
		||||
  {-2,  1, 1, 2},
 | 
			
		||||
  { 2, -1, 1, 2},
 | 
			
		||||
  {-2,  1, 3, 2},
 | 
			
		||||
  { 2, -1, 3, 2},
 | 
			
		||||
  { 2,  1, 1, 2},
 | 
			
		||||
  {-2, -1, 1, 2},
 | 
			
		||||
  { 2,  1, 3, 2},
 | 
			
		||||
  {-2, -1, 3, 2},
 | 
			
		||||
 | 
			
		||||
  { 0,  2, 0, 1},
 | 
			
		||||
  { 0, -2, 0, 1},
 | 
			
		||||
  { 0,  2, 0, 3},
 | 
			
		||||
  { 0, -2, 0, 3},
 | 
			
		||||
  { 2,  0, 1, 0},
 | 
			
		||||
  {-2,  0, 1, 0},
 | 
			
		||||
  { 2,  0, 3, 0},
 | 
			
		||||
  {-2,  0, 3, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int *get_mask_params_interintra(int mask_index,
 | 
			
		||||
                                             BLOCK_SIZE sb_type,
 | 
			
		||||
                                             int h, int w) {
 | 
			
		||||
  const int *a;
 | 
			
		||||
  const int mask_bits = get_mask_bits_interintra(sb_type);
 | 
			
		||||
 | 
			
		||||
  if (mask_index == MASK_NONE_INTERINTRA)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  if (mask_bits == MASK_BITS_SML_INTERINTRA) {
 | 
			
		||||
    a = mask_params_sml_interintra[mask_index];
 | 
			
		||||
  } else if (mask_bits == MASK_BITS_MED_INTERINTRA) {
 | 
			
		||||
    if (h > w)
 | 
			
		||||
      a = mask_params_med_hgtw_interintra[mask_index];
 | 
			
		||||
    else if (h < w)
 | 
			
		||||
      a = mask_params_med_hltw_interintra[mask_index];
 | 
			
		||||
    else
 | 
			
		||||
      a = mask_params_med_heqw_interintra[mask_index];
 | 
			
		||||
  } else if (mask_bits == MASK_BITS_BIG_INTERINTRA) {
 | 
			
		||||
    if (h > w)
 | 
			
		||||
      a = mask_params_big_hgtw_interintra[mask_index];
 | 
			
		||||
    else if (h < w)
 | 
			
		||||
      a = mask_params_big_hltw_interintra[mask_index];
 | 
			
		||||
    else
 | 
			
		||||
      a = mask_params_big_heqw_interintra[mask_index];
 | 
			
		||||
  } else {
 | 
			
		||||
    assert(0);
 | 
			
		||||
  }
 | 
			
		||||
  return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_generate_masked_weight_interintra(int mask_index,
 | 
			
		||||
                                           BLOCK_SIZE sb_type,
 | 
			
		||||
                                           int h, int w,
 | 
			
		||||
                                           uint8_t *mask, int stride) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
 | 
			
		||||
  if (!a) return;
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int x = (j - (a[2] * w) / 4);
 | 
			
		||||
      int y = (i - (a[3] * h) / 4);
 | 
			
		||||
      int m = a[0] * x + a[1] * y;
 | 
			
		||||
      mask[i * stride + j] = get_masked_weight_interintra(m);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_generate_hard_mask_interintra(int mask_index, BLOCK_SIZE sb_type,
 | 
			
		||||
                            int h, int w, uint8_t *mask, int stride) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
  const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
 | 
			
		||||
  if (!a) return;
 | 
			
		||||
  for (i = 0; i < h; ++i)
 | 
			
		||||
    for (j = 0; j < w; ++j) {
 | 
			
		||||
      int x = (j - (a[2] * w) / 4);
 | 
			
		||||
      int y = (i - (a[3] * h) / 4);
 | 
			
		||||
      int m = a[0] * x + a[1] * y;
 | 
			
		||||
      mask[i * stride + j] = get_hard_mask_interintra(m);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void combine_interintra(PREDICTION_MODE mode,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
                               int use_masked_interintra,
 | 
			
		||||
                               int mask_index,
 | 
			
		||||
                               BLOCK_SIZE bsize,
 | 
			
		||||
#endif
 | 
			
		||||
                               uint8_t *comppred,
 | 
			
		||||
                               int compstride,
 | 
			
		||||
                               uint8_t *interpred,
 | 
			
		||||
                               int interstride,
 | 
			
		||||
                               uint8_t *intrapred,
 | 
			
		||||
                               int intrastride,
 | 
			
		||||
                               int bw, int bh) {
 | 
			
		||||
  static const int scale_bits = 8;
 | 
			
		||||
  static const int scale_max = 256;
 | 
			
		||||
  static const int scale_round = 127;
 | 
			
		||||
  static const int weights1d[64] = {
 | 
			
		||||
      128, 125, 122, 119, 116, 114, 111, 109,
 | 
			
		||||
      107, 105, 103, 101,  99,  97,  96,  94,
 | 
			
		||||
       93,  91,  90,  89,  88,  86,  85,  84,
 | 
			
		||||
       83,  82,  81,  81,  80,  79,  78,  78,
 | 
			
		||||
       77,  76,  76,  75,  75,  74,  74,  73,
 | 
			
		||||
       73,  72,  72,  71,  71,  71,  70,  70,
 | 
			
		||||
       70,  70,  69,  69,  69,  69,  68,  68,
 | 
			
		||||
       68,  68,  68,  67,  67,  67,  67,  67,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  int size = MAX(bw, bh);
 | 
			
		||||
  int size_scale = (size >= 64 ? 1 :
 | 
			
		||||
                    size == 32 ? 2 :
 | 
			
		||||
                    size == 16 ? 4 :
 | 
			
		||||
                    size == 8  ? 8 : 16);
 | 
			
		||||
  int i, j;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  if (use_masked_interintra && get_mask_bits_interintra(bsize)) {
 | 
			
		||||
    uint8_t mask[4096];
 | 
			
		||||
    vp9_generate_masked_weight_interintra(mask_index, bsize, bh, bw, mask, bw);
 | 
			
		||||
    for (i = 0; i < bh; ++i) {
 | 
			
		||||
      for (j = 0; j < bw; ++j) {
 | 
			
		||||
        int m = mask[i * bw + j];
 | 
			
		||||
        comppred[i * compstride + j] =
 | 
			
		||||
            (intrapred[i * intrastride + j] * m +
 | 
			
		||||
            interpred[i * interstride + j] *
 | 
			
		||||
            ((1 << MASK_WEIGHT_BITS_INTERINTRA) - m) +
 | 
			
		||||
            (1 << (MASK_WEIGHT_BITS_INTERINTRA - 1))) >>
 | 
			
		||||
            MASK_WEIGHT_BITS_INTERINTRA;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
    case V_PRED:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
          int scale = weights1d[i * size_scale];
 | 
			
		||||
            comppred[i * compstride + j] =
 | 
			
		||||
              ((scale_max - scale) * interpred[i * interstride + j] +
 | 
			
		||||
               scale * intrapred[i * intrastride + j] + scale_round)
 | 
			
		||||
               >> scale_bits;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
     break;
 | 
			
		||||
 | 
			
		||||
    case H_PRED:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
          int scale = weights1d[j * size_scale];
 | 
			
		||||
            comppred[i * compstride + j] =
 | 
			
		||||
              ((scale_max - scale) * interpred[i * interstride + j] +
 | 
			
		||||
               scale * intrapred[i * intrastride + j] + scale_round)
 | 
			
		||||
               >> scale_bits;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
     break;
 | 
			
		||||
 | 
			
		||||
    case D63_PRED:
 | 
			
		||||
    case D117_PRED:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
          int scale = (weights1d[i * size_scale] * 3 +
 | 
			
		||||
                       weights1d[j * size_scale]) >> 2;
 | 
			
		||||
            comppred[i * compstride + j] =
 | 
			
		||||
              ((scale_max - scale) * interpred[i * interstride + j] +
 | 
			
		||||
                  scale * intrapred[i * intrastride + j] + scale_round)
 | 
			
		||||
                  >> scale_bits;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
     break;
 | 
			
		||||
 | 
			
		||||
    case D207_PRED:
 | 
			
		||||
    case D153_PRED:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
          int scale = (weights1d[j * size_scale] * 3 +
 | 
			
		||||
                       weights1d[i * size_scale]) >> 2;
 | 
			
		||||
            comppred[i * compstride + j] =
 | 
			
		||||
              ((scale_max - scale) * interpred[i * interstride + j] +
 | 
			
		||||
                  scale * intrapred[i * intrastride + j] + scale_round)
 | 
			
		||||
                  >> scale_bits;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
     break;
 | 
			
		||||
 | 
			
		||||
    case D135_PRED:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
          int scale = weights1d[(i < j ? i : j) * size_scale];
 | 
			
		||||
            comppred[i * compstride + j] =
 | 
			
		||||
              ((scale_max - scale) * interpred[i * interstride + j] +
 | 
			
		||||
                  scale * intrapred[i * intrastride + j] + scale_round)
 | 
			
		||||
                  >> scale_bits;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
     break;
 | 
			
		||||
 | 
			
		||||
    case D45_PRED:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
          int scale = (weights1d[i * size_scale] +
 | 
			
		||||
                       weights1d[j * size_scale]) >> 1;
 | 
			
		||||
            comppred[i * compstride + j] =
 | 
			
		||||
              ((scale_max - scale) * interpred[i * interstride + j] +
 | 
			
		||||
                  scale * intrapred[i * intrastride + j] + scale_round)
 | 
			
		||||
                  >> scale_bits;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
     break;
 | 
			
		||||
 | 
			
		||||
    case TM_PRED:
 | 
			
		||||
    case DC_PRED:
 | 
			
		||||
    default:
 | 
			
		||||
      for (i = 0; i < bh; ++i) {
 | 
			
		||||
        for (j = 0; j < bw; ++j) {
 | 
			
		||||
            comppred[i * compstride + j] = (interpred[i * interstride + j] +
 | 
			
		||||
                intrapred[i * intrastride + j]) >> 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void build_intra_predictors_for_2nd_block_interintra
 | 
			
		||||
                                  (const MACROBLOCKD *xd, const uint8_t *ref,
 | 
			
		||||
                                   int ref_stride, uint8_t *dst, int dst_stride,
 | 
			
		||||
                                   PREDICTION_MODE mode, TX_SIZE tx_size,
 | 
			
		||||
                                   int up_available, int left_available,
 | 
			
		||||
                                   int right_available, int bwltbh,
 | 
			
		||||
                                   int x, int y, int plane) {
 | 
			
		||||
  int i;
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
 | 
			
		||||
  uint8_t *above_row = above_data + 16;
 | 
			
		||||
  const uint8_t *const_above_row = above_row;
 | 
			
		||||
  const int bs = 4 << tx_size;
 | 
			
		||||
  int frame_width, frame_height;
 | 
			
		||||
  int x0, y0;
 | 
			
		||||
  const struct macroblockd_plane *const pd = &xd->plane[plane];
 | 
			
		||||
  const uint8_t *ref_fi;
 | 
			
		||||
  int ref_stride_fi;
 | 
			
		||||
 | 
			
		||||
  // 127 127 127 .. 127 127 127 127 127 127
 | 
			
		||||
  // 129  A   B  ..  Y   Z
 | 
			
		||||
  // 129  C   D  ..  W   X
 | 
			
		||||
  // 129  E   F  ..  U   V
 | 
			
		||||
  // 129  G   H  ..  S   T   T   T   T   T
 | 
			
		||||
  // ..
 | 
			
		||||
 | 
			
		||||
  once(init_intra_pred_fn_ptrs);
 | 
			
		||||
 | 
			
		||||
  // Get current frame pointer, width and height.
 | 
			
		||||
  if (plane == 0) {
 | 
			
		||||
    frame_width = xd->cur_buf->y_width;
 | 
			
		||||
    frame_height = xd->cur_buf->y_height;
 | 
			
		||||
  } else {
 | 
			
		||||
    frame_width = xd->cur_buf->uv_width;
 | 
			
		||||
    frame_height = xd->cur_buf->uv_height;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Get block position in current frame.
 | 
			
		||||
  x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
 | 
			
		||||
  y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
 | 
			
		||||
 | 
			
		||||
  vpx_memset(left_col, 129, 64);
 | 
			
		||||
 | 
			
		||||
  // left
 | 
			
		||||
  if (left_available) {
 | 
			
		||||
    if (bwltbh) {
 | 
			
		||||
      ref_fi = ref;
 | 
			
		||||
      ref_stride_fi = ref_stride;
 | 
			
		||||
    } else {
 | 
			
		||||
      ref_fi = dst;
 | 
			
		||||
      ref_stride_fi = dst_stride;
 | 
			
		||||
    }
 | 
			
		||||
    if (xd->mb_to_bottom_edge < 0) {
 | 
			
		||||
      /* slower path if the block needs border extension */
 | 
			
		||||
      if (y0 + bs <= frame_height) {
 | 
			
		||||
        for (i = 0; i < bs; ++i)
 | 
			
		||||
          left_col[i] = ref_fi[i * ref_stride_fi - 1];
 | 
			
		||||
      } else {
 | 
			
		||||
        const int extend_bottom = frame_height - y0;
 | 
			
		||||
        assert(extend_bottom >= 0);
 | 
			
		||||
        for (i = 0; i < extend_bottom; ++i)
 | 
			
		||||
          left_col[i] = ref_fi[i * ref_stride_fi - 1];
 | 
			
		||||
        for (; i < bs; ++i)
 | 
			
		||||
          left_col[i] = ref_fi[(extend_bottom - 1) * ref_stride_fi - 1];
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      /* faster path if the block does not need extension */
 | 
			
		||||
      for (i = 0; i < bs; ++i)
 | 
			
		||||
        left_col[i] = ref_fi[i * ref_stride_fi - 1];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // TODO(hkuang) do not extend 2*bs pixels for all modes.
 | 
			
		||||
  // above
 | 
			
		||||
  if (up_available) {
 | 
			
		||||
    const uint8_t *above_ref;
 | 
			
		||||
    if (bwltbh) {
 | 
			
		||||
      ref_fi = dst;
 | 
			
		||||
      ref_stride_fi = dst_stride;
 | 
			
		||||
      above_row[-1] = left_available ? ref[-ref_stride-1] : 129;
 | 
			
		||||
    } else {
 | 
			
		||||
      ref_fi = ref;
 | 
			
		||||
      ref_stride_fi = ref_stride;
 | 
			
		||||
      above_row[-1] = ref[-ref_stride-1];
 | 
			
		||||
    }
 | 
			
		||||
    above_ref = ref_fi - ref_stride_fi;
 | 
			
		||||
    if (xd->mb_to_right_edge < 0) {
 | 
			
		||||
      /* slower path if the block needs border extension */
 | 
			
		||||
      if (x0 + 2 * bs <= frame_width) {
 | 
			
		||||
        if (right_available && bs == 4) {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, 2 * bs);
 | 
			
		||||
        } else {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, bs);
 | 
			
		||||
          vpx_memset(above_row + bs, above_row[bs - 1], bs);
 | 
			
		||||
        }
 | 
			
		||||
      } else if (x0 + bs <= frame_width) {
 | 
			
		||||
        const int r = frame_width - x0;
 | 
			
		||||
        if (right_available && bs == 4) {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, r);
 | 
			
		||||
          vpx_memset(above_row + r, above_row[r - 1],
 | 
			
		||||
                     x0 + 2 * bs - frame_width);
 | 
			
		||||
        } else {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, bs);
 | 
			
		||||
          vpx_memset(above_row + bs, above_row[bs - 1], bs);
 | 
			
		||||
        }
 | 
			
		||||
      } else if (x0 <= frame_width) {
 | 
			
		||||
        const int r = frame_width - x0;
 | 
			
		||||
        assert(r >= 0);
 | 
			
		||||
        if (right_available && bs == 4) {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, r);
 | 
			
		||||
          vpx_memset(above_row + r, above_row[r - 1],
 | 
			
		||||
                     x0 + 2 * bs - frame_width);
 | 
			
		||||
        } else {
 | 
			
		||||
          vpx_memcpy(above_row, above_ref, r);
 | 
			
		||||
          vpx_memset(above_row + r, above_row[r - 1],
 | 
			
		||||
                     x0 + 2 * bs - frame_width);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      /* faster path if the block does not need extension */
 | 
			
		||||
      if (bs == 4 && right_available && left_available) {
 | 
			
		||||
        const_above_row = above_ref;
 | 
			
		||||
      } else {
 | 
			
		||||
        vpx_memcpy(above_row, above_ref, bs);
 | 
			
		||||
        if (bs == 4 && right_available)
 | 
			
		||||
          vpx_memcpy(above_row + bs, above_ref + bs, bs);
 | 
			
		||||
        else
 | 
			
		||||
          vpx_memset(above_row + bs, above_row[bs - 1], bs);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    vpx_memset(above_row, 127, bs * 2);
 | 
			
		||||
    above_row[-1] = 127;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // predict
 | 
			
		||||
  if (mode == DC_PRED) {
 | 
			
		||||
    dc_pred[left_available][up_available][tx_size](dst, dst_stride,
 | 
			
		||||
                                                   const_above_row, left_col);
 | 
			
		||||
  } else {
 | 
			
		||||
    pred[mode][tx_size](dst, dst_stride, const_above_row, left_col);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Break down rectangular intra prediction for joint spatio-temporal prediction
 | 
			
		||||
// into two square intra predictions.
 | 
			
		||||
static void build_intra_predictors_for_interintra(MACROBLOCKD *xd,
 | 
			
		||||
                                           uint8_t *src, int src_stride,
 | 
			
		||||
                                           uint8_t *pred_ptr, int stride,
 | 
			
		||||
                                           PREDICTION_MODE mode,
 | 
			
		||||
                                           int bw, int bh,
 | 
			
		||||
                                           int up_available, int left_available,
 | 
			
		||||
                                           int right_available, int plane) {
 | 
			
		||||
  if (bw == bh) {
 | 
			
		||||
    build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
 | 
			
		||||
                           mode, intra_size_log2_for_interintra(bw),
 | 
			
		||||
                           up_available, left_available, right_available,
 | 
			
		||||
                           0, 0, plane);
 | 
			
		||||
  } else if (bw < bh) {
 | 
			
		||||
    uint8_t *src_bottom = src + bw * src_stride;
 | 
			
		||||
    uint8_t *pred_ptr_bottom = pred_ptr + bw * stride;
 | 
			
		||||
    build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
 | 
			
		||||
                           mode, intra_size_log2_for_interintra(bw),
 | 
			
		||||
                           up_available, left_available, right_available,
 | 
			
		||||
                           0, 0, plane);
 | 
			
		||||
    build_intra_predictors_for_2nd_block_interintra(xd, src_bottom, src_stride,
 | 
			
		||||
                           pred_ptr_bottom, stride,
 | 
			
		||||
                           mode, intra_size_log2_for_interintra(bw),
 | 
			
		||||
                           up_available, left_available, 0, 1,
 | 
			
		||||
                           0, bw, plane);
 | 
			
		||||
  } else {
 | 
			
		||||
    uint8_t *src_right = src + bh;
 | 
			
		||||
    uint8_t *pred_ptr_right = pred_ptr + bh;
 | 
			
		||||
    build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
 | 
			
		||||
                           mode, intra_size_log2_for_interintra(bh),
 | 
			
		||||
                           up_available, left_available, 1,
 | 
			
		||||
                           0, 0, plane);
 | 
			
		||||
    build_intra_predictors_for_2nd_block_interintra(xd, src_right, src_stride,
 | 
			
		||||
                           pred_ptr_right, stride,
 | 
			
		||||
                           mode, intra_size_log2_for_interintra(bh),
 | 
			
		||||
                           up_available, left_available, right_available, 0,
 | 
			
		||||
                           bh, 0, plane);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
 | 
			
		||||
                                         uint8_t *ypred,
 | 
			
		||||
                                         int ystride,
 | 
			
		||||
                                         BLOCK_SIZE bsize) {
 | 
			
		||||
  int bw = 4 << b_width_log2(bsize);
 | 
			
		||||
  int bh = 4 << b_height_log2(bsize);
 | 
			
		||||
  uint8_t intrapredictor[4096];
 | 
			
		||||
  build_intra_predictors_for_interintra(
 | 
			
		||||
      xd, xd->plane[0].dst.buf, xd->plane[0].dst.stride,
 | 
			
		||||
      intrapredictor, bw,
 | 
			
		||||
      xd->mi[0]->mbmi.interintra_mode, bw, bh,
 | 
			
		||||
      xd->up_available, xd->left_available, 0, 0);
 | 
			
		||||
  combine_interintra(xd->mi[0]->mbmi.interintra_mode,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
                     xd->mi[0]->mbmi.use_masked_interintra,
 | 
			
		||||
                     xd->mi[0]->mbmi.interintra_mask_index,
 | 
			
		||||
                     bsize,
 | 
			
		||||
#endif
 | 
			
		||||
                     xd->plane[0].dst.buf, xd->plane[0].dst.stride,
 | 
			
		||||
                     ypred, ystride, intrapredictor, bw, bw, bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
 | 
			
		||||
                                          uint8_t *upred,
 | 
			
		||||
                                          uint8_t *vpred,
 | 
			
		||||
                                          int ustride, int vstride,
 | 
			
		||||
                                          BLOCK_SIZE bsize) {
 | 
			
		||||
  int bwl = b_width_log2(bsize), bw = 2 << bwl;
 | 
			
		||||
  int bhl = b_height_log2(bsize), bh = 2 << bhl;
 | 
			
		||||
  uint8_t uintrapredictor[1024];
 | 
			
		||||
  uint8_t vintrapredictor[1024];
 | 
			
		||||
  build_intra_predictors_for_interintra(
 | 
			
		||||
      xd, xd->plane[1].dst.buf, xd->plane[1].dst.stride,
 | 
			
		||||
      uintrapredictor, bw,
 | 
			
		||||
      xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
 | 
			
		||||
      xd->up_available, xd->left_available, 0, 1);
 | 
			
		||||
  build_intra_predictors_for_interintra(
 | 
			
		||||
      xd, xd->plane[2].dst.buf, xd->plane[1].dst.stride,
 | 
			
		||||
      vintrapredictor, bw,
 | 
			
		||||
      xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
 | 
			
		||||
      xd->up_available, xd->left_available, 0, 2);
 | 
			
		||||
  combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
                     xd->mi[0]->mbmi.use_masked_interintra,
 | 
			
		||||
                     xd->mi[0]->mbmi.interintra_uv_mask_index,
 | 
			
		||||
                     bsize,
 | 
			
		||||
#endif
 | 
			
		||||
                     xd->plane[1].dst.buf, xd->plane[1].dst.stride,
 | 
			
		||||
                     upred, ustride, uintrapredictor, bw, bw, bh);
 | 
			
		||||
  combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
                     xd->mi[0]->mbmi.use_masked_interintra,
 | 
			
		||||
                     xd->mi[0]->mbmi.interintra_uv_mask_index,
 | 
			
		||||
                     bsize,
 | 
			
		||||
#endif
 | 
			
		||||
                     xd->plane[2].dst.buf, xd->plane[2].dst.stride,
 | 
			
		||||
                     vpred, vstride, vintrapredictor, bw, bw, bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_build_interintra_predictors(MACROBLOCKD *xd,
 | 
			
		||||
                                     uint8_t *ypred,
 | 
			
		||||
                                     uint8_t *upred,
 | 
			
		||||
                                     uint8_t *vpred,
 | 
			
		||||
                                     int ystride, int ustride, int vstride,
 | 
			
		||||
                                     BLOCK_SIZE bsize) {
 | 
			
		||||
  vp9_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
 | 
			
		||||
  vp9_build_interintra_predictors_sbuv(xd, upred, vpred,
 | 
			
		||||
                                       ustride, vstride, bsize);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,37 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
 | 
			
		||||
                             TX_SIZE tx_size, PREDICTION_MODE mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                             int filterbit,
 | 
			
		||||
#endif
 | 
			
		||||
                             const uint8_t *ref, int ref_stride,
 | 
			
		||||
                             uint8_t *dst, int dst_stride,
 | 
			
		||||
                             int aoff, int loff, int plane);
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
void vp9_build_interintra_predictors(MACROBLOCKD *xd,
 | 
			
		||||
                                     uint8_t *ypred,
 | 
			
		||||
                                     uint8_t *upred,
 | 
			
		||||
                                     uint8_t *vpred,
 | 
			
		||||
                                     int ystride,
 | 
			
		||||
                                     int ustride,
 | 
			
		||||
                                     int vstride,
 | 
			
		||||
                                     BLOCK_SIZE bsize);
 | 
			
		||||
void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
 | 
			
		||||
                                         uint8_t *ypred,
 | 
			
		||||
                                         int ystride,
 | 
			
		||||
                                         BLOCK_SIZE bsize);
 | 
			
		||||
void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
 | 
			
		||||
                                          uint8_t *upred,
 | 
			
		||||
                                          uint8_t *vpred,
 | 
			
		||||
                                          int ustride, int vstride,
 | 
			
		||||
                                          BLOCK_SIZE bsize);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
void vp9_generate_masked_weight_interintra(int mask_index,
 | 
			
		||||
                                           BLOCK_SIZE sb_type,
 | 
			
		||||
                                           int h, int w,
 | 
			
		||||
                                           uint8_t *mask, int stride);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -506,6 +506,125 @@ specialize qw/vp9_sub_pixel_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
 | 
			
		||||
add_proto qw/unsigned int vp9_sub_pixel_avg_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, const uint8_t *second_pred";
 | 
			
		||||
specialize qw/vp9_sub_pixel_avg_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
 | 
			
		||||
 | 
			
		||||
if ((vpx_config("CONFIG_MASKED_INTERINTER") eq "yes") || ((vpx_config("CONFIG_INTERINTRA") eq "yes") && (vpx_config("CONFIG_MASKED_INTERINTRA") eq "yes"))) {
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance32x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masdctked_variance16x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance64x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance32x64/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance32x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance64x64/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance16x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance16x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance8x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance8x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance8x4/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance4x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_variance4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_variance4x4/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance64x64/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance32x64/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance64x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance32x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance16x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance32x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance16x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance8x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance16x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance8x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance8x4/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance4x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_masked_sub_pixel_variance4x4/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad64x64/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad32x64/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad64x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad32x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad16x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad32x32/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad16x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad16x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad8x16/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad8x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad8x4/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad4x8/;
 | 
			
		||||
 | 
			
		||||
add_proto qw/unsigned int vp9_masked_sad4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int  ref_stride, const uint8_t *mask, int mask_stride";
 | 
			
		||||
specialize qw/vp9_masked_sad4x4/;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# TODO(jingning): need to convert 8x4/4x8 functions into mmx/sse form
 | 
			
		||||
add_proto qw/unsigned int vp9_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse";
 | 
			
		||||
specialize qw/vp9_sub_pixel_variance8x4/, "$sse2_x86inc", "$ssse3_x86inc";
 | 
			
		||||
 
 | 
			
		||||
@@ -46,8 +46,8 @@ static INLINE int vp9_is_valid_scale(const struct scale_factors *sf) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INLINE int vp9_is_scaled(const struct scale_factors *sf) {
 | 
			
		||||
  return sf->x_scale_fp != REF_NO_SCALE ||
 | 
			
		||||
         sf->y_scale_fp != REF_NO_SCALE;
 | 
			
		||||
  return vp9_is_valid_scale(sf) &&
 | 
			
		||||
         (sf->x_scale_fp != REF_NO_SCALE || sf->y_scale_fp != REF_NO_SCALE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 
 | 
			
		||||
@@ -254,11 +254,24 @@ static void predict_and_reconstruct_intra_block(int plane, int block,
 | 
			
		||||
                                            : mi->mbmi.uv_mode;
 | 
			
		||||
  int x, y;
 | 
			
		||||
  uint8_t *dst;
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  int fbit;
 | 
			
		||||
  if (plane == 0)
 | 
			
		||||
    if (mi->mbmi.sb_type < BLOCK_8X8)
 | 
			
		||||
      fbit = mi->b_filter_info[block];
 | 
			
		||||
    else
 | 
			
		||||
      fbit = is_filter_enabled(tx_size) ? mi->mbmi.filterbit : 0;
 | 
			
		||||
  else
 | 
			
		||||
    fbit = is_filter_enabled(tx_size) ? mi->mbmi.uv_filterbit : 0;
 | 
			
		||||
#endif
 | 
			
		||||
  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
 | 
			
		||||
  dst = &pd->dst.buf[4 * y * pd->dst.stride + 4 * x];
 | 
			
		||||
 | 
			
		||||
  vp9_predict_intra_block(xd, block >> (tx_size << 1),
 | 
			
		||||
                          b_width_log2(plane_bsize), tx_size, mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                          fbit,
 | 
			
		||||
#endif
 | 
			
		||||
                          dst, pd->dst.stride, dst, pd->dst.stride,
 | 
			
		||||
                          x, y, plane);
 | 
			
		||||
 | 
			
		||||
@@ -322,6 +335,84 @@ static MB_MODE_INFO *set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
  return &xd->mi[0]->mbmi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static void set_offsets_extend(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                               const TileInfo *const tile,
 | 
			
		||||
                               BLOCK_SIZE top_bsize,
 | 
			
		||||
                               int mi_row, int mi_col,
 | 
			
		||||
                               int mi_row_ori, int mi_col_ori) {
 | 
			
		||||
  const int bw = num_8x8_blocks_wide_lookup[top_bsize];
 | 
			
		||||
  const int bh = num_8x8_blocks_high_lookup[top_bsize];
 | 
			
		||||
  const int offset = mi_row * cm->mi_stride + mi_col;
 | 
			
		||||
 | 
			
		||||
  xd->mi = cm->mi_grid_visible + offset;
 | 
			
		||||
  xd->mi[0] = &cm->mi[offset];
 | 
			
		||||
 | 
			
		||||
  set_mi_row_col(xd, tile, mi_row_ori, bh, mi_col_ori, bw,
 | 
			
		||||
                 cm->mi_rows, cm->mi_cols);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_mb_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                           const TileInfo *const tile,
 | 
			
		||||
                           BLOCK_SIZE bsize, int mi_row, int mi_col) {
 | 
			
		||||
  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->mi_stride + mi_col;
 | 
			
		||||
  int x, y;
 | 
			
		||||
 | 
			
		||||
  xd->mi = cm->mi_grid_visible + offset;
 | 
			
		||||
  xd->mi[0] = &cm->mi[offset];
 | 
			
		||||
  xd->mi[0]->mbmi.sb_type = bsize;
 | 
			
		||||
  for (y = 0; y < y_mis; ++y)
 | 
			
		||||
    for (x = !y; x < x_mis; ++x)
 | 
			
		||||
      xd->mi[y * cm->mi_stride + x] = xd->mi[0];
 | 
			
		||||
 | 
			
		||||
  set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_offsets_topblock(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                                 const TileInfo *const tile,
 | 
			
		||||
                                 BLOCK_SIZE bsize, int mi_row, int mi_col) {
 | 
			
		||||
  const int bw = num_8x8_blocks_wide_lookup[bsize];
 | 
			
		||||
  const int bh = num_8x8_blocks_high_lookup[bsize];
 | 
			
		||||
  const int offset = mi_row * cm->mi_stride + mi_col;
 | 
			
		||||
 | 
			
		||||
  xd->mi = cm->mi_grid_visible + offset;
 | 
			
		||||
  xd->mi[0] = &cm->mi[offset];
 | 
			
		||||
 | 
			
		||||
  set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);
 | 
			
		||||
 | 
			
		||||
  vp9_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_param_topblock(VP9_COMMON *const cm,  MACROBLOCKD *const xd,
 | 
			
		||||
                              BLOCK_SIZE bsize, int mi_row, int mi_col,
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
                              int txfm,
 | 
			
		||||
#endif
 | 
			
		||||
                              int skip) {
 | 
			
		||||
  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->mi_stride + mi_col;
 | 
			
		||||
  int x, y;
 | 
			
		||||
 | 
			
		||||
  xd->mi = cm->mi_grid_visible + offset;
 | 
			
		||||
  xd->mi[0] = &cm->mi[offset];
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < y_mis; ++y)
 | 
			
		||||
    for (x = 0; x < x_mis; ++x) {
 | 
			
		||||
      xd->mi[y * cm->mi_stride + x]->mbmi.skip = skip;
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      xd->mi[y * cm->mi_stride + x]->mbmi.ext_txfrm = txfm;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                    int idx, int mi_row, int mi_col) {
 | 
			
		||||
  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
@@ -335,14 +426,246 @@ static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
  xd->corrupted |= ref_buffer->buf->corrupted;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static void dec_predict_b_extend(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                                 const TileInfo *const tile,
 | 
			
		||||
                                 int mi_row, int mi_col,
 | 
			
		||||
                                 int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                 BLOCK_SIZE top_bsize) {
 | 
			
		||||
  set_offsets_extend(cm, xd, tile, top_bsize, mi_row, mi_col,
 | 
			
		||||
                     mi_row_ori, mi_col_ori);
 | 
			
		||||
 | 
			
		||||
  set_ref(cm, xd, 0, mi_row_ori, mi_col_ori);
 | 
			
		||||
  if (has_second_ref(&xd->mi[0]->mbmi))
 | 
			
		||||
    set_ref(cm, xd, 1, mi_row_ori, mi_col_ori);
 | 
			
		||||
  xd->mi[0]->mbmi.tx_size = b_width_log2(top_bsize);
 | 
			
		||||
#if !CONFIG_MASKED_INTERINTER
 | 
			
		||||
  vp9_dec_build_inter_predictors_sb(xd, mi_row_ori, mi_col_ori, top_bsize);
 | 
			
		||||
#else
 | 
			
		||||
  vp9_dec_build_inter_predictors_sb_extend(xd, mi_row, mi_col,
 | 
			
		||||
                                           mi_row_ori, mi_col_ori, top_bsize);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dec_predict_b_sub8x8_extend(VP9_COMMON *const cm,
 | 
			
		||||
                                        MACROBLOCKD *const xd,
 | 
			
		||||
                                        const TileInfo *const tile,
 | 
			
		||||
                                        int mi_row, int mi_col,
 | 
			
		||||
                                        int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                        BLOCK_SIZE top_bsize,
 | 
			
		||||
                                        PARTITION_TYPE partition) {
 | 
			
		||||
  set_offsets_extend(cm, xd, tile, top_bsize, mi_row, mi_col,
 | 
			
		||||
                     mi_row_ori, mi_col_ori);
 | 
			
		||||
 | 
			
		||||
  set_ref(cm, xd, 0, mi_row_ori, mi_col_ori);
 | 
			
		||||
  if (has_second_ref(&xd->mi[0]->mbmi))
 | 
			
		||||
    set_ref(cm, xd, 1, mi_row_ori, mi_col_ori);
 | 
			
		||||
  xd->mi[0]->mbmi.tx_size = b_width_log2(top_bsize);
 | 
			
		||||
  vp9_dec_build_inter_predictors_sby_sub8x8_extend(xd, mi_row, mi_col,
 | 
			
		||||
                                                   mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                   top_bsize, partition);
 | 
			
		||||
  vp9_dec_build_inter_predictors_sbuv_sub8x8_extend(xd,
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
                                                    mi_row, mi_col,
 | 
			
		||||
#endif
 | 
			
		||||
                                                    mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                    top_bsize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dec_predict_sb_complex(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                                   const TileInfo *const tile,
 | 
			
		||||
                                   int mi_row, int mi_col,
 | 
			
		||||
                                   int mi_row_ori, int mi_col_ori,
 | 
			
		||||
                                   BLOCK_SIZE bsize, BLOCK_SIZE top_bsize,
 | 
			
		||||
                                   uint8_t *dst_buf[3], int dst_stride[3]) {
 | 
			
		||||
  const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
 | 
			
		||||
  PARTITION_TYPE partition;
 | 
			
		||||
  BLOCK_SIZE subsize;
 | 
			
		||||
  MB_MODE_INFO *mbmi;
 | 
			
		||||
  int i, offset = mi_row * cm->mi_stride + mi_col;
 | 
			
		||||
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf1, MAX_MB_PLANE * 32 * 32);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf2, MAX_MB_PLANE * 32 * 32);
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf3, MAX_MB_PLANE * 32 * 32);
 | 
			
		||||
  uint8_t *dst_buf1[3] = {tmp_buf1, tmp_buf1 + 32 * 32, tmp_buf1 + 2 * 32 * 32};
 | 
			
		||||
  uint8_t *dst_buf2[3] = {tmp_buf2, tmp_buf2 + 32 * 32, tmp_buf2 + 2 * 32 * 32};
 | 
			
		||||
  uint8_t *dst_buf3[3] = {tmp_buf3, tmp_buf3 + 32 * 32, tmp_buf3 + 2 * 32 * 32};
 | 
			
		||||
  int dst_stride1[3] = {32, 32, 32};
 | 
			
		||||
  int dst_stride2[3] = {32, 32, 32};
 | 
			
		||||
  int dst_stride3[3] = {32, 32, 32};
 | 
			
		||||
 | 
			
		||||
  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  xd->mi = cm->mi_grid_visible + offset;
 | 
			
		||||
  xd->mi[0] = &cm->mi[offset];
 | 
			
		||||
  mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
  partition = partition_lookup[bsl][mbmi->sb_type];
 | 
			
		||||
  subsize = get_subsize(bsize, partition);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
    xd->plane[i].dst.buf = dst_buf[i];
 | 
			
		||||
    xd->plane[i].dst.stride = dst_stride[i];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (partition) {
 | 
			
		||||
    case PARTITION_NONE:
 | 
			
		||||
      assert(bsize < top_bsize);
 | 
			
		||||
      dec_predict_b_extend(cm, xd, tile, mi_row, mi_col, mi_row_ori, mi_col_ori,
 | 
			
		||||
                           top_bsize);
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_HORZ:
 | 
			
		||||
      if (bsize > BLOCK_8X8) {
 | 
			
		||||
        dec_predict_b_extend(cm, xd, tile, mi_row, mi_col, mi_row_ori,
 | 
			
		||||
                             mi_col_ori, top_bsize);
 | 
			
		||||
      } else {
 | 
			
		||||
        dec_predict_b_sub8x8_extend(cm, xd, tile, mi_row, mi_col,
 | 
			
		||||
                                    mi_row_ori, mi_col_ori,
 | 
			
		||||
                                    top_bsize, partition);
 | 
			
		||||
      }
 | 
			
		||||
      if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
 | 
			
		||||
        for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
          xd->plane[i].dst.buf = tmp_buf1 + i * 32 * 32;
 | 
			
		||||
          xd->plane[i].dst.stride = 32;
 | 
			
		||||
        }
 | 
			
		||||
        dec_predict_b_extend(cm, xd, tile, mi_row + hbs, mi_col,
 | 
			
		||||
                             mi_row_ori, mi_col_ori, top_bsize);
 | 
			
		||||
        for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
          xd->plane[i].dst.buf = dst_buf[i];
 | 
			
		||||
          xd->plane[i].dst.stride = dst_stride[i];
 | 
			
		||||
          vp9_build_masked_inter_predictor_complex(dst_buf[i], dst_stride[i],
 | 
			
		||||
                                                   dst_buf1[i], dst_stride1[i],
 | 
			
		||||
                                                   i,
 | 
			
		||||
                                                   mi_row, mi_col,
 | 
			
		||||
                                                   mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                   bsize, top_bsize,
 | 
			
		||||
                                                   PARTITION_HORZ);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_VERT:
 | 
			
		||||
      if (bsize > BLOCK_8X8) {
 | 
			
		||||
        dec_predict_b_extend(cm, xd, tile, mi_row, mi_col, mi_row_ori,
 | 
			
		||||
                             mi_col_ori, top_bsize);
 | 
			
		||||
      } else {
 | 
			
		||||
        dec_predict_b_sub8x8_extend(cm, xd, tile, mi_row, mi_col,
 | 
			
		||||
                                    mi_row_ori, mi_col_ori,
 | 
			
		||||
                                    top_bsize, partition);
 | 
			
		||||
      }
 | 
			
		||||
      if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
 | 
			
		||||
        for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
          xd->plane[i].dst.buf = tmp_buf1 + i * 32 * 32;
 | 
			
		||||
          xd->plane[i].dst.stride = 32;
 | 
			
		||||
        }
 | 
			
		||||
        dec_predict_b_extend(cm, xd, tile, mi_row, mi_col + hbs, mi_row_ori,
 | 
			
		||||
                             mi_col_ori, top_bsize);
 | 
			
		||||
        for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
          xd->plane[i].dst.buf = dst_buf[i];
 | 
			
		||||
          xd->plane[i].dst.stride = dst_stride[i];
 | 
			
		||||
          vp9_build_masked_inter_predictor_complex(dst_buf[i], dst_stride[i],
 | 
			
		||||
                                                   dst_buf1[i], dst_stride1[i],
 | 
			
		||||
                                                   i,
 | 
			
		||||
                                                   mi_row, mi_col,
 | 
			
		||||
                                                   mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                   bsize, top_bsize,
 | 
			
		||||
                                                   PARTITION_VERT);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PARTITION_SPLIT:
 | 
			
		||||
      if (bsize == BLOCK_8X8) {
 | 
			
		||||
        dec_predict_b_sub8x8_extend(cm, xd, tile, mi_row, mi_col,
 | 
			
		||||
                                    mi_row_ori, mi_col_ori,
 | 
			
		||||
                                    top_bsize, partition);
 | 
			
		||||
      } else {
 | 
			
		||||
        dec_predict_sb_complex(cm, xd, tile, mi_row, mi_col,
 | 
			
		||||
                               mi_row_ori, mi_col_ori, subsize, top_bsize,
 | 
			
		||||
                               dst_buf, dst_stride);
 | 
			
		||||
        if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols)
 | 
			
		||||
          dec_predict_sb_complex(cm, xd, tile, mi_row, mi_col + hbs,
 | 
			
		||||
                                 mi_row_ori, mi_col_ori, subsize, top_bsize,
 | 
			
		||||
                                 dst_buf1, dst_stride1);
 | 
			
		||||
        if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols)
 | 
			
		||||
          dec_predict_sb_complex(cm, xd, tile, mi_row + hbs, mi_col,
 | 
			
		||||
                                 mi_row_ori, mi_col_ori, subsize, top_bsize,
 | 
			
		||||
                                 dst_buf2, dst_stride2);
 | 
			
		||||
        if (mi_row + hbs < cm->mi_rows && mi_col + hbs < cm->mi_cols)
 | 
			
		||||
          dec_predict_sb_complex(cm, xd, tile, mi_row + hbs, mi_col + hbs,
 | 
			
		||||
                                 mi_row_ori, mi_col_ori, subsize, top_bsize,
 | 
			
		||||
                                 dst_buf3, dst_stride3);
 | 
			
		||||
        for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
          if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols) {
 | 
			
		||||
            vp9_build_masked_inter_predictor_complex(dst_buf[i], dst_stride[i],
 | 
			
		||||
                                                     dst_buf1[i],
 | 
			
		||||
                                                     dst_stride1[i],
 | 
			
		||||
                                                     i, mi_row, mi_col,
 | 
			
		||||
                                                     mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                     bsize, top_bsize,
 | 
			
		||||
                                                     PARTITION_VERT);
 | 
			
		||||
            if (mi_row + hbs < cm->mi_rows) {
 | 
			
		||||
              vp9_build_masked_inter_predictor_complex(dst_buf2[i],
 | 
			
		||||
                                                       dst_stride2[i],
 | 
			
		||||
                                                       dst_buf3[i],
 | 
			
		||||
                                                       dst_stride3[i],
 | 
			
		||||
                                                       i, mi_row, mi_col,
 | 
			
		||||
                                                       mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                       bsize, top_bsize,
 | 
			
		||||
                                                       PARTITION_VERT);
 | 
			
		||||
              vp9_build_masked_inter_predictor_complex(dst_buf[i],
 | 
			
		||||
                                                       dst_stride[i],
 | 
			
		||||
                                                       dst_buf2[i],
 | 
			
		||||
                                                       dst_stride2[i],
 | 
			
		||||
                                                       i, mi_row, mi_col,
 | 
			
		||||
                                                       mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                       bsize, top_bsize,
 | 
			
		||||
                                                       PARTITION_HORZ);
 | 
			
		||||
            }
 | 
			
		||||
          } else if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols) {
 | 
			
		||||
            vp9_build_masked_inter_predictor_complex(dst_buf[i],
 | 
			
		||||
                                                     dst_stride[i],
 | 
			
		||||
                                                     dst_buf2[i],
 | 
			
		||||
                                                     dst_stride2[i],
 | 
			
		||||
                                                     i, mi_row, mi_col,
 | 
			
		||||
                                                     mi_row_ori, mi_col_ori,
 | 
			
		||||
                                                     bsize, top_bsize,
 | 
			
		||||
                                                     PARTITION_HORZ);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void decode_block(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                         const TileInfo *const tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                         int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                         int mi_row, int mi_col,
 | 
			
		||||
                         vp9_reader *r, BLOCK_SIZE bsize) {
 | 
			
		||||
  const int less8x8 = bsize < BLOCK_8X8;
 | 
			
		||||
#if !CONFIG_SUPERTX
 | 
			
		||||
  MB_MODE_INFO *mbmi = set_offsets(cm, xd, tile, bsize, mi_row, mi_col);
 | 
			
		||||
  vp9_read_mode_info(cm, xd, tile, mi_row, mi_col, r);
 | 
			
		||||
#else
 | 
			
		||||
  MB_MODE_INFO *mbmi;
 | 
			
		||||
  if (!supertx_enabled) {
 | 
			
		||||
    mbmi = set_offsets(cm, xd, tile, bsize, mi_row, mi_col);
 | 
			
		||||
  } else {
 | 
			
		||||
    set_mb_offsets(cm, xd, tile, bsize, mi_row, mi_col);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  vp9_read_mode_info(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                     supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                     mi_row, mi_col, r);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (!supertx_enabled) {
 | 
			
		||||
#endif
 | 
			
		||||
  if (less8x8)
 | 
			
		||||
    bsize = BLOCK_8X8;
 | 
			
		||||
 | 
			
		||||
@@ -376,6 +699,9 @@ static void decode_block(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
        mbmi->skip = 1;  // skip loopfilter
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  xd->corrupted |= vp9_reader_has_error(r);
 | 
			
		||||
}
 | 
			
		||||
@@ -406,45 +732,161 @@ static PARTITION_TYPE read_partition(VP9_COMMON *cm, MACROBLOCKD *xd, int hbs,
 | 
			
		||||
 | 
			
		||||
static void decode_partition(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
                             const TileInfo *const tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                             int read_token, int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                             int mi_row, int mi_col,
 | 
			
		||||
                             vp9_reader* r, BLOCK_SIZE bsize) {
 | 
			
		||||
  const int hbs = num_8x8_blocks_wide_lookup[bsize] / 2;
 | 
			
		||||
  PARTITION_TYPE partition;
 | 
			
		||||
  BLOCK_SIZE subsize;
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  int skip = 0;
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  int txfm = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  partition = read_partition(cm, xd, hbs, mi_row, mi_col, bsize, r);
 | 
			
		||||
  subsize = get_subsize(bsize, partition);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (cm->frame_type != KEY_FRAME &&
 | 
			
		||||
      partition != PARTITION_NONE &&
 | 
			
		||||
      bsize <= BLOCK_32X32 &&
 | 
			
		||||
      !supertx_enabled) {
 | 
			
		||||
    TX_SIZE supertx_size = b_width_log2(bsize);
 | 
			
		||||
    if (partition == PARTITION_SPLIT) {
 | 
			
		||||
      supertx_enabled = vp9_read(r, cm->fc.supertxsplit_prob[supertx_size]);
 | 
			
		||||
      cm->counts.supertxsplit[supertx_size][supertx_enabled]++;
 | 
			
		||||
    } else {
 | 
			
		||||
      supertx_enabled = vp9_read(r, cm->fc.supertx_prob[supertx_size]);
 | 
			
		||||
      cm->counts.supertx[supertx_size][supertx_enabled]++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (supertx_enabled && read_token) {
 | 
			
		||||
    int offset = mi_row * cm->mi_stride + mi_col;
 | 
			
		||||
    xd->mi = cm->mi_grid_visible + offset;
 | 
			
		||||
    xd->mi[0] = &cm->mi[offset];
 | 
			
		||||
    set_mi_row_col(xd, tile, mi_row, num_8x8_blocks_high_lookup[bsize],
 | 
			
		||||
                   mi_col, num_8x8_blocks_wide_lookup[bsize],
 | 
			
		||||
                   cm->mi_rows, cm->mi_cols);
 | 
			
		||||
    set_skip_context(xd, mi_row, mi_col);
 | 
			
		||||
    // Here we assume mbmi->segment_id = 0
 | 
			
		||||
    skip = read_skip(cm, xd, 0, r);
 | 
			
		||||
    if (skip)
 | 
			
		||||
      reset_skip_context(xd, bsize);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
    if (bsize <= BLOCK_16X16 && !skip) {
 | 
			
		||||
      txfm = vp9_read(r, cm->fc.ext_tx_prob);
 | 
			
		||||
      if (!cm->frame_parallel_decoding_mode)
 | 
			
		||||
        ++cm->counts.ext_tx[txfm];
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  if (subsize < BLOCK_8X8) {
 | 
			
		||||
    decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
 | 
			
		||||
    decode_block(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                 supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                 mi_row, mi_col, r, subsize);
 | 
			
		||||
  } else {
 | 
			
		||||
    switch (partition) {
 | 
			
		||||
      case PARTITION_NONE:
 | 
			
		||||
        decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
 | 
			
		||||
        decode_block(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                     supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                     mi_row, mi_col, r, subsize);
 | 
			
		||||
        break;
 | 
			
		||||
      case PARTITION_HORZ:
 | 
			
		||||
        decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
 | 
			
		||||
        decode_block(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                     supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                     mi_row, mi_col, r, subsize);
 | 
			
		||||
        if (mi_row + hbs < cm->mi_rows)
 | 
			
		||||
          decode_block(cm, xd, tile, mi_row + hbs, mi_col, r, subsize);
 | 
			
		||||
          decode_block(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row + hbs, mi_col, r, subsize);
 | 
			
		||||
        break;
 | 
			
		||||
      case PARTITION_VERT:
 | 
			
		||||
        decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
 | 
			
		||||
        decode_block(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                     supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                     mi_row, mi_col, r, subsize);
 | 
			
		||||
        if (mi_col + hbs < cm->mi_cols)
 | 
			
		||||
          decode_block(cm, xd, tile, mi_row, mi_col + hbs, r, subsize);
 | 
			
		||||
          decode_block(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row, mi_col + hbs, r, subsize);
 | 
			
		||||
        break;
 | 
			
		||||
      case PARTITION_SPLIT:
 | 
			
		||||
        decode_partition(cm, xd, tile, mi_row,       mi_col,       r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile, mi_row,       mi_col + hbs, r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile, mi_row + hbs, mi_col,       r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile, mi_row + hbs, mi_col + hbs, r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                         !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                         mi_row,       mi_col,       r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                         !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                         mi_row,       mi_col + hbs, r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                         !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                         mi_row + hbs, mi_col,       r, subsize);
 | 
			
		||||
        decode_partition(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                         !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                         mi_row + hbs, mi_col + hbs, r, subsize);
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        assert(0 && "Invalid partition type");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (supertx_enabled && read_token) {
 | 
			
		||||
    uint8_t *dst_buf[3];
 | 
			
		||||
    int dst_stride[3], i;
 | 
			
		||||
 | 
			
		||||
    vp9_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
 | 
			
		||||
    for (i = 0; i < MAX_MB_PLANE; i++) {
 | 
			
		||||
      dst_buf[i] = xd->plane[i].dst.buf;
 | 
			
		||||
      dst_stride[i] = xd->plane[i].dst.stride;
 | 
			
		||||
    }
 | 
			
		||||
    dec_predict_sb_complex(cm, xd, tile, mi_row, mi_col, mi_row, mi_col,
 | 
			
		||||
                           bsize, bsize, dst_buf, dst_stride);
 | 
			
		||||
 | 
			
		||||
    if (!skip) {
 | 
			
		||||
      int eobtotal = 0;
 | 
			
		||||
      struct inter_args arg = { cm, xd, r, &eobtotal };
 | 
			
		||||
      set_offsets_topblock(cm, xd, tile, bsize, mi_row, mi_col);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      xd->mi[0]->mbmi.ext_txfrm = txfm;
 | 
			
		||||
#endif
 | 
			
		||||
      vp9_foreach_transformed_block(xd, bsize, reconstruct_inter_block, &arg);
 | 
			
		||||
      if (!(subsize < BLOCK_8X8) && eobtotal == 0)
 | 
			
		||||
        skip = 1;
 | 
			
		||||
    }
 | 
			
		||||
    set_param_topblock(cm, xd, bsize, mi_row, mi_col,
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
                       txfm,
 | 
			
		||||
#endif
 | 
			
		||||
                       skip);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // update partition context
 | 
			
		||||
  if (bsize >= BLOCK_8X8 &&
 | 
			
		||||
      (bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
 | 
			
		||||
@@ -685,6 +1127,10 @@ static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
 | 
			
		||||
  while (max_ones-- && vp9_rb_read_bit(rb))
 | 
			
		||||
    cm->log2_tile_cols++;
 | 
			
		||||
 | 
			
		||||
  if (cm->log2_tile_cols > 6)
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
 | 
			
		||||
                       "Invalid number of tile columns");
 | 
			
		||||
 | 
			
		||||
  // rows
 | 
			
		||||
  cm->log2_tile_rows = vp9_rb_read_bit(rb);
 | 
			
		||||
  if (cm->log2_tile_rows)
 | 
			
		||||
@@ -838,7 +1284,11 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
 | 
			
		||||
        vp9_zero(tile_data->xd.left_seg_context);
 | 
			
		||||
        for (mi_col = tile.mi_col_start; mi_col < tile.mi_col_end;
 | 
			
		||||
             mi_col += MI_BLOCK_SIZE) {
 | 
			
		||||
          decode_partition(tile_data->cm, &tile_data->xd, &tile, mi_row, mi_col,
 | 
			
		||||
          decode_partition(tile_data->cm, &tile_data->xd, &tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                           1, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                           mi_row, mi_col,
 | 
			
		||||
                           &tile_data->bit_reader, BLOCK_64X64);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
@@ -892,6 +1342,9 @@ static int tile_worker_hook(void *arg1, void *arg2) {
 | 
			
		||||
    for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
 | 
			
		||||
         mi_col += MI_BLOCK_SIZE) {
 | 
			
		||||
      decode_partition(tile_data->cm, &tile_data->xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       1, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row, mi_col, &tile_data->bit_reader, BLOCK_64X64);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -1077,7 +1530,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
 | 
			
		||||
    // Show an existing frame directly.
 | 
			
		||||
    const int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
 | 
			
		||||
 | 
			
		||||
    if (cm->frame_bufs[frame_to_show].ref_count < 1)
 | 
			
		||||
    if (frame_to_show < 0 || cm->frame_bufs[frame_to_show].ref_count < 1)
 | 
			
		||||
      vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
 | 
			
		||||
                         "Buffer %d does not contain a decoded frame",
 | 
			
		||||
                         frame_to_show);
 | 
			
		||||
@@ -1242,6 +1695,62 @@ static int read_compressed_header(VP9Decoder *pbi, const uint8_t *data,
 | 
			
		||||
        vp9_diff_update_prob(&r, &fc->partition_prob[j][i]);
 | 
			
		||||
 | 
			
		||||
    read_mv_probs(nmvc, cm->allow_high_precision_mv, &r);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
    vp9_diff_update_prob(&r, &fc->ext_tx_prob);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    if (cm->reference_mode != SINGLE_REFERENCE) {
 | 
			
		||||
      cm->use_masked_interinter = vp9_read_bit(&r);
 | 
			
		||||
      if (cm->use_masked_interinter) {
 | 
			
		||||
        for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
          if (get_mask_bits(i))
 | 
			
		||||
            vp9_diff_update_prob(&r, &fc->masked_interinter_prob[i]);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      cm->use_masked_interinter = 0;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    if (cm->reference_mode != COMPOUND_REFERENCE) {
 | 
			
		||||
      cm->use_interintra = vp9_read_bit(&r);
 | 
			
		||||
      if (cm->use_interintra) {
 | 
			
		||||
        for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
          if (is_interintra_allowed(i)) {
 | 
			
		||||
            vp9_diff_update_prob(&r, &fc->interintra_prob[i]);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
        cm->use_masked_interintra = vp9_read_bit(&r);
 | 
			
		||||
        if (cm->use_masked_interintra) {
 | 
			
		||||
          for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
            if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
 | 
			
		||||
              vp9_diff_update_prob(&r, &fc->masked_interintra_prob[i]);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        cm->use_masked_interintra = 0;
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      cm->use_interintra = 0;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
      cm->use_masked_interintra = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
    for (j = 0; j < COPY_MODE_CONTEXTS; j++) {
 | 
			
		||||
      for (i = 0; i < 1; i++)
 | 
			
		||||
        vp9_diff_update_prob(&r, &fc->copy_mode_probs_l2[j][i]);
 | 
			
		||||
      for (i = 0; i < 2; i++)
 | 
			
		||||
        vp9_diff_update_prob(&r, &fc->copy_mode_probs[j][i]);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return vp9_reader_has_error(&r);
 | 
			
		||||
@@ -1293,6 +1802,10 @@ static void debug_check_frame_counts(const VP9_COMMON *const cm) {
 | 
			
		||||
  assert(!memcmp(&cm->counts.tx, &zero_counts.tx, sizeof(cm->counts.tx)));
 | 
			
		||||
  assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
 | 
			
		||||
  assert(!memcmp(&cm->counts.mv, &zero_counts.mv, sizeof(cm->counts.mv)));
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  assert(!memcmp(cm->counts.ext_tx, zero_counts.ext_tx,
 | 
			
		||||
                 sizeof(cm->counts.ext_tx)));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif  // NDEBUG
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,36 @@ static PREDICTION_MODE read_inter_mode(VP9_COMMON *cm, vp9_reader *r, int ctx) {
 | 
			
		||||
  return NEARESTMV + mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
static COPY_MODE read_copy_mode(VP9_COMMON *cm, vp9_reader *r,
 | 
			
		||||
                                int num_candidate, int ctx) {
 | 
			
		||||
  COPY_MODE mode;
 | 
			
		||||
 | 
			
		||||
  switch (num_candidate) {
 | 
			
		||||
    case 0:
 | 
			
		||||
      assert(0);
 | 
			
		||||
      break;
 | 
			
		||||
    case 1:
 | 
			
		||||
      mode = REF0;
 | 
			
		||||
      break;
 | 
			
		||||
    case 2:
 | 
			
		||||
      mode = REF0 + vp9_read_tree(r, vp9_copy_mode_tree_l2,
 | 
			
		||||
                                  cm->fc.copy_mode_probs_l2[ctx]);
 | 
			
		||||
      if (!cm->frame_parallel_decoding_mode)
 | 
			
		||||
          ++cm->counts.copy_mode_l2[ctx][mode - REF0];
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      mode = REF0 + vp9_read_tree(r, vp9_copy_mode_tree,
 | 
			
		||||
                                  cm->fc.copy_mode_probs[ctx]);
 | 
			
		||||
      if (!cm->frame_parallel_decoding_mode)
 | 
			
		||||
          ++cm->counts.copy_mode[ctx][mode - REF0];
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return mode;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int read_segment_id(vp9_reader *r, const struct segmentation *seg) {
 | 
			
		||||
  return vp9_read_tree(r, vp9_segment_tree, seg->tree_probs);
 | 
			
		||||
}
 | 
			
		||||
@@ -144,7 +174,11 @@ static int read_inter_segment_id(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 | 
			
		||||
  return segment_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
 | 
			
		||||
#else
 | 
			
		||||
static int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
 | 
			
		||||
#endif
 | 
			
		||||
                     int segment_id, vp9_reader *r) {
 | 
			
		||||
  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
 | 
			
		||||
    return 1;
 | 
			
		||||
@@ -175,29 +209,85 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm,
 | 
			
		||||
 | 
			
		||||
  switch (bsize) {
 | 
			
		||||
    case BLOCK_4X4:
 | 
			
		||||
#if !CONFIG_FILTERINTRA
 | 
			
		||||
      for (i = 0; i < 4; ++i)
 | 
			
		||||
#else
 | 
			
		||||
      for (i = 0; i < 4; ++i) {
 | 
			
		||||
#endif
 | 
			
		||||
        mi->bmi[i].as_mode =
 | 
			
		||||
            read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, i));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
        if (is_filter_allowed(mi->bmi[i].as_mode))
 | 
			
		||||
          mi->b_filter_info[i] =
 | 
			
		||||
              vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
 | 
			
		||||
        else
 | 
			
		||||
          mi->b_filter_info[i] = 0;
 | 
			
		||||
      }
 | 
			
		||||
      mbmi->filterbit = mi->b_filter_info[3];
 | 
			
		||||
#endif
 | 
			
		||||
      mbmi->mode = mi->bmi[3].as_mode;
 | 
			
		||||
      break;
 | 
			
		||||
    case BLOCK_4X8:
 | 
			
		||||
      mi->bmi[0].as_mode = mi->bmi[2].as_mode =
 | 
			
		||||
          read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[0].as_mode))
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[2] =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
 | 
			
		||||
      else
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
 | 
			
		||||
#endif
 | 
			
		||||
      mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
 | 
			
		||||
          read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 1));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[1].as_mode))
 | 
			
		||||
        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
 | 
			
		||||
      else
 | 
			
		||||
        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    case BLOCK_8X4:
 | 
			
		||||
      mi->bmi[0].as_mode = mi->bmi[1].as_mode =
 | 
			
		||||
          read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[0].as_mode))
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[1] =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
 | 
			
		||||
      else
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
 | 
			
		||||
#endif
 | 
			
		||||
      mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
 | 
			
		||||
          read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 2));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[2].as_mode))
 | 
			
		||||
        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
 | 
			
		||||
      else
 | 
			
		||||
        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      mbmi->mode = read_intra_mode(r,
 | 
			
		||||
                                   get_y_mode_probs(mi, above_mi, left_mi, 0));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_enabled(mbmi->tx_size) && is_filter_allowed(mbmi->mode))
 | 
			
		||||
        mbmi->filterbit = vp9_read(r,
 | 
			
		||||
                            cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
 | 
			
		||||
      else
 | 
			
		||||
        mbmi->filterbit = 0;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  if (is_filter_enabled(get_uv_tx_size(mbmi)) &&
 | 
			
		||||
      is_filter_allowed(mbmi->uv_mode))
 | 
			
		||||
    mbmi->uv_filterbit = vp9_read(r,
 | 
			
		||||
        cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
 | 
			
		||||
  else
 | 
			
		||||
    mbmi->uv_filterbit = 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_mv_component(vp9_reader *r,
 | 
			
		||||
@@ -335,25 +425,97 @@ static void read_intra_block_mode_info(VP9_COMMON *const cm, MODE_INFO *mi,
 | 
			
		||||
 | 
			
		||||
  switch (bsize) {
 | 
			
		||||
    case BLOCK_4X4:
 | 
			
		||||
#if !CONFIG_FILTERINTRA
 | 
			
		||||
      for (i = 0; i < 4; ++i)
 | 
			
		||||
#else
 | 
			
		||||
      for (i = 0; i < 4; ++i) {
 | 
			
		||||
#endif
 | 
			
		||||
        mi->bmi[i].as_mode = read_intra_mode_y(cm, r, 0);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
        if (is_filter_allowed(mi->bmi[i].as_mode)) {
 | 
			
		||||
          mi->b_filter_info[i] =
 | 
			
		||||
              vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
 | 
			
		||||
          cm->counts.filterintra[0][mi->bmi[i].as_mode]
 | 
			
		||||
                                   [mi->b_filter_info[i]]++;
 | 
			
		||||
        } else {
 | 
			
		||||
          mi->b_filter_info[i] = 0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      mbmi->filterbit = mi->b_filter_info[3];
 | 
			
		||||
#endif
 | 
			
		||||
      mbmi->mode = mi->bmi[3].as_mode;
 | 
			
		||||
      break;
 | 
			
		||||
    case BLOCK_4X8:
 | 
			
		||||
      mi->bmi[0].as_mode = mi->bmi[2].as_mode = read_intra_mode_y(cm, r, 0);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[0].as_mode)) {
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[2] =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
 | 
			
		||||
        cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
 | 
			
		||||
      } else {
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
 | 
			
		||||
          read_intra_mode_y(cm, r, 0);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[1].as_mode)) {
 | 
			
		||||
        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
 | 
			
		||||
        cm->counts.filterintra[0][mi->bmi[1].as_mode][mi->b_filter_info[1]]++;
 | 
			
		||||
      } else {
 | 
			
		||||
        mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    case BLOCK_8X4:
 | 
			
		||||
      mi->bmi[0].as_mode = mi->bmi[1].as_mode = read_intra_mode_y(cm, r, 0);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[0].as_mode)) {
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[1] =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
 | 
			
		||||
        cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
 | 
			
		||||
      } else {
 | 
			
		||||
        mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
 | 
			
		||||
          read_intra_mode_y(cm, r, 0);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mi->bmi[2].as_mode)) {
 | 
			
		||||
        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
 | 
			
		||||
            vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
 | 
			
		||||
        cm->counts.filterintra[0][mi->bmi[2].as_mode][mi->b_filter_info[2]]++;
 | 
			
		||||
      } else {
 | 
			
		||||
        mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      mbmi->mode = read_intra_mode_y(cm, r, size_group_lookup[bsize]);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size)) {
 | 
			
		||||
        mbmi->filterbit = vp9_read(r,
 | 
			
		||||
            cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
 | 
			
		||||
        cm->counts.filterintra[mbmi->tx_size][mbmi->mode][mbmi->filterbit]++;
 | 
			
		||||
      } else {
 | 
			
		||||
        mbmi->filterbit = 0;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mbmi->uv_mode = read_intra_mode_uv(cm, r, mbmi->mode);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  if (is_filter_allowed(mbmi->uv_mode) &&
 | 
			
		||||
      is_filter_enabled(get_uv_tx_size(mbmi))) {
 | 
			
		||||
    mbmi->uv_filterbit = vp9_read(r,
 | 
			
		||||
        cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
 | 
			
		||||
    cm->counts.filterintra[get_uv_tx_size(mbmi)]
 | 
			
		||||
                           [mbmi->uv_mode][mbmi->uv_filterbit]++;
 | 
			
		||||
  } else {
 | 
			
		||||
    mbmi->uv_filterbit = 0;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INLINE int is_mv_valid(const MV *mv) {
 | 
			
		||||
@@ -422,6 +584,9 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
 | 
			
		||||
                                       MACROBLOCKD *const xd,
 | 
			
		||||
                                       const TileInfo *const tile,
 | 
			
		||||
                                       MODE_INFO *const mi,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_EXT_TX
 | 
			
		||||
                                       int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                                       int mi_row, int mi_col, vp9_reader *r) {
 | 
			
		||||
  MB_MODE_INFO *const mbmi = &mi->mbmi;
 | 
			
		||||
  const BLOCK_SIZE bsize = mbmi->sb_type;
 | 
			
		||||
@@ -464,6 +629,37 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
 | 
			
		||||
                      ? read_switchable_interp_filter(cm, xd, r)
 | 
			
		||||
                      : cm->interp_filter;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    if ((cm->use_interintra) &&
 | 
			
		||||
        is_interintra_allowed(bsize) &&
 | 
			
		||||
        is_inter_mode(mbmi->mode) &&
 | 
			
		||||
        (mbmi->ref_frame[1] <= INTRA_FRAME)) {
 | 
			
		||||
      mbmi->ref_frame[1] = vp9_read(r, cm->fc.interintra_prob[bsize]) ?
 | 
			
		||||
                           INTRA_FRAME : NONE;
 | 
			
		||||
      cm->counts.interintra[bsize][mbmi->ref_frame[1] == INTRA_FRAME]++;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
      mbmi->use_masked_interintra = 0;
 | 
			
		||||
#endif
 | 
			
		||||
      if (mbmi->ref_frame[1] == INTRA_FRAME) {
 | 
			
		||||
        mbmi->interintra_mode =
 | 
			
		||||
            read_intra_mode_y(cm, r, size_group_lookup[bsize]);
 | 
			
		||||
        mbmi->interintra_uv_mode = mbmi->interintra_mode;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
        if (cm->use_masked_interintra && get_mask_bits_interintra(bsize)) {
 | 
			
		||||
          mbmi->use_masked_interintra = vp9_read(r,
 | 
			
		||||
                                          cm->fc.masked_interintra_prob[bsize]);
 | 
			
		||||
          cm->counts.masked_interintra[bsize][mbmi->use_masked_interintra]++;
 | 
			
		||||
          if (mbmi->use_masked_interintra) {
 | 
			
		||||
            mbmi->interintra_mask_index = vp9_read_literal(r,
 | 
			
		||||
                                               get_mask_bits_interintra(bsize));
 | 
			
		||||
            mbmi->interintra_uv_mask_index = mbmi->interintra_mask_index;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (bsize < BLOCK_8X8) {
 | 
			
		||||
    const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];  // 1 or 2
 | 
			
		||||
    const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];  // 1 or 2
 | 
			
		||||
@@ -508,35 +704,160 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
 | 
			
		||||
    xd->corrupted |= !assign_mv(cm, mbmi->mode, mbmi->mv, nearestmv,
 | 
			
		||||
                                nearestmv, nearmv, is_compound, allow_hp, r);
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  mbmi->use_masked_interinter = 0;
 | 
			
		||||
  if (cm->use_masked_interinter &&
 | 
			
		||||
      cm->reference_mode != SINGLE_REFERENCE &&
 | 
			
		||||
      is_inter_mode(mbmi->mode) &&
 | 
			
		||||
      get_mask_bits(bsize) &&
 | 
			
		||||
      mbmi->ref_frame[1] > INTRA_FRAME) {
 | 
			
		||||
    mbmi->use_masked_interinter =
 | 
			
		||||
        vp9_read(r, cm->fc.masked_interinter_prob[bsize]);
 | 
			
		||||
    cm->counts.masked_interinter[bsize][mbmi->use_masked_interinter]++;
 | 
			
		||||
    if (mbmi->use_masked_interinter) {
 | 
			
		||||
      mbmi->mask_index = vp9_read_literal(r, get_mask_bits(bsize));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void read_inter_frame_mode_info(VP9_COMMON *const cm,
 | 
			
		||||
                                       MACROBLOCKD *const xd,
 | 
			
		||||
                                       const TileInfo *const tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                                       int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                                       int mi_row, int mi_col, vp9_reader *r) {
 | 
			
		||||
  MODE_INFO *const mi = xd->mi[0];
 | 
			
		||||
  MB_MODE_INFO *const mbmi = &mi->mbmi;
 | 
			
		||||
  int inter_block;
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  int num_candidate = 0;
 | 
			
		||||
  MB_MODE_INFO *inter_ref_list[18] = {NULL};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  mbmi->mv[0].as_int = 0;
 | 
			
		||||
  mbmi->mv[1].as_int = 0;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  if (mbmi->sb_type >= BLOCK_8X8)
 | 
			
		||||
    num_candidate = vp9_construct_ref_inter_list(cm, xd, mbmi->sb_type,
 | 
			
		||||
                                               mi_row, mi_col, inter_ref_list);
 | 
			
		||||
  if (mbmi->sb_type >= BLOCK_8X8 && num_candidate > 0) {
 | 
			
		||||
    int ctx = vp9_get_copy_mode_context(xd);
 | 
			
		||||
    int is_copy = vp9_read(r, cm->fc.copy_noref_prob[ctx][mbmi->sb_type]);
 | 
			
		||||
 | 
			
		||||
    ++cm->counts.copy_noref[ctx][mbmi->sb_type][is_copy];
 | 
			
		||||
    if (!is_copy) {
 | 
			
		||||
      mbmi->copy_mode = NOREF;
 | 
			
		||||
    } else {
 | 
			
		||||
      mbmi->copy_mode = read_copy_mode(cm, r, num_candidate, ctx);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    mbmi->copy_mode = NOREF;
 | 
			
		||||
  }
 | 
			
		||||
  if (mbmi->copy_mode != NOREF) {
 | 
			
		||||
    BLOCK_SIZE bsize_backup = mbmi->sb_type;
 | 
			
		||||
    int skip_backup = mbmi->skip;
 | 
			
		||||
    COPY_MODE copy_mode_backup = mbmi->copy_mode;
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
    TX_SIZE tx_size_backup = mbmi->tx_size;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
    EXT_TX_TYPE ext_txfrm_backup = mbmi->ext_txfrm;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    inter_block = 1;
 | 
			
		||||
    *mbmi = *inter_ref_list[mbmi->copy_mode - REF0];
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    mbmi->use_masked_interinter = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    if (mbmi->ref_frame[1] == INTRA_FRAME)
 | 
			
		||||
      mbmi->ref_frame[1] = NONE;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
    mbmi->tx_size = tx_size_backup;
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
    mbmi->ext_txfrm = ext_txfrm_backup;
 | 
			
		||||
#endif
 | 
			
		||||
    mbmi->sb_type = bsize_backup;
 | 
			
		||||
    mbmi->mode = NEARESTMV;
 | 
			
		||||
    mbmi->skip = skip_backup;
 | 
			
		||||
    mbmi->copy_mode = copy_mode_backup;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (!supertx_enabled) {
 | 
			
		||||
#endif
 | 
			
		||||
  mbmi->segment_id = read_inter_segment_id(cm, xd, mi_row, mi_col, r);
 | 
			
		||||
  mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  if (mbmi->copy_mode == NOREF)
 | 
			
		||||
#endif
 | 
			
		||||
  inter_block = read_is_inter_block(cm, xd, mbmi->segment_id, r);
 | 
			
		||||
  mbmi->tx_size = read_tx_size(cm, xd, cm->tx_mode, mbmi->sb_type,
 | 
			
		||||
                               !mbmi->skip || !inter_block, r);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  if (inter_block &&
 | 
			
		||||
      mbmi->tx_size <= TX_16X16 &&
 | 
			
		||||
      mbmi->sb_type >= BLOCK_8X8 &&
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
      !supertx_enabled &&
 | 
			
		||||
#endif
 | 
			
		||||
      !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) &&
 | 
			
		||||
      !mbmi->skip) {
 | 
			
		||||
    mbmi->ext_txfrm = vp9_read(r, cm->fc.ext_tx_prob);
 | 
			
		||||
    if (!cm->frame_parallel_decoding_mode)
 | 
			
		||||
      ++cm->counts.ext_tx[mbmi->ext_txfrm];
 | 
			
		||||
  } else {
 | 
			
		||||
    mbmi->ext_txfrm = NORM;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  } else {
 | 
			
		||||
    const int ctx = vp9_get_intra_inter_context(xd);
 | 
			
		||||
    mbmi->segment_id = 0;
 | 
			
		||||
    inter_block = 1;
 | 
			
		||||
    if (!cm->frame_parallel_decoding_mode)
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
      if (mbmi->copy_mode == NOREF)
 | 
			
		||||
#endif
 | 
			
		||||
      ++cm->counts.intra_inter[ctx][1];
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  if (mbmi->copy_mode == NOREF) {
 | 
			
		||||
#endif
 | 
			
		||||
  if (inter_block)
 | 
			
		||||
    read_inter_block_mode_info(cm, xd, tile, mi, mi_row, mi_col, r);
 | 
			
		||||
    read_inter_block_mode_info(cm, xd, tile, mi,
 | 
			
		||||
#if CONFIG_SUPERTX && CONFIG_EXT_TX
 | 
			
		||||
                               supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                               mi_row, mi_col, r);
 | 
			
		||||
  else
 | 
			
		||||
    read_intra_block_mode_info(cm, mi, r);
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
                        const TileInfo *const tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                        int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                        int mi_row, int mi_col, vp9_reader *r) {
 | 
			
		||||
  if (frame_is_intra_only(cm))
 | 
			
		||||
    read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
 | 
			
		||||
  else
 | 
			
		||||
    read_inter_frame_mode_info(cm, xd, tile, mi_row, mi_col, r);
 | 
			
		||||
    read_inter_frame_mode_info(cm, xd, tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                               supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                               mi_row, mi_col, r);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,16 @@ struct TileInfo;
 | 
			
		||||
 | 
			
		||||
void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
                        const struct TileInfo *const tile,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                        int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                        int mi_row, int mi_col, vp9_reader *r);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
 | 
			
		||||
              int segment_id, vp9_reader *r);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,6 @@ static void initialize_dec() {
 | 
			
		||||
 | 
			
		||||
  if (!init_done) {
 | 
			
		||||
    vp9_init_neighbors();
 | 
			
		||||
    vp9_init_quant_tables();
 | 
			
		||||
    init_done = 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -244,8 +243,8 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
 | 
			
		||||
 | 
			
		||||
  // Check if the previous frame was a frame without any references to it.
 | 
			
		||||
  // Release frame buffer if not decoding in frame parallel mode.
 | 
			
		||||
  if (!pbi->frame_parallel_decode && cm->new_fb_idx >= 0 &&
 | 
			
		||||
         cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
 | 
			
		||||
  if (!pbi->frame_parallel_decode && cm->new_fb_idx >= 0
 | 
			
		||||
      && cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
 | 
			
		||||
    cm->release_fb_cb(cm->cb_priv,
 | 
			
		||||
                      &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
 | 
			
		||||
  cm->new_fb_idx = get_free_fb(cm);
 | 
			
		||||
@@ -260,10 +259,10 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
 | 
			
		||||
    // TODO(jkoleszar): Error concealment is undefined and non-normative
 | 
			
		||||
    // at this point, but if it becomes so, [0] may not always be the correct
 | 
			
		||||
    // thing to do here.
 | 
			
		||||
    if (cm->frame_refs[0].idx != INT_MAX)
 | 
			
		||||
    if (cm->frame_refs[0].idx != INT_MAX && cm->frame_refs[0].buf != NULL)
 | 
			
		||||
      cm->frame_refs[0].buf->corrupted = 1;
 | 
			
		||||
 | 
			
		||||
    if (cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
 | 
			
		||||
    if (cm->new_fb_idx > 0 && cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
 | 
			
		||||
      cm->frame_bufs[cm->new_fb_idx].ref_count--;
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,23 @@ typedef struct VP9LfSyncData {
 | 
			
		||||
  int sync_range;
 | 
			
		||||
} VP9LfSync;
 | 
			
		||||
 | 
			
		||||
// WorkerData for the FrameWorker thread. It contains all the information of
 | 
			
		||||
// the worker and decode structures for decoding a frame.
 | 
			
		||||
typedef struct FrameWorkerData {
 | 
			
		||||
  struct VP9Decoder *pbi;
 | 
			
		||||
  const uint8_t *data;
 | 
			
		||||
  const uint8_t *data_end;
 | 
			
		||||
  size_t data_size;
 | 
			
		||||
  void *user_priv;
 | 
			
		||||
  int result;
 | 
			
		||||
  int worker_id;
 | 
			
		||||
 | 
			
		||||
  // scratch_buffer is used in frame parallel mode only.
 | 
			
		||||
  // It is used to make a copy of the compressed data.
 | 
			
		||||
  uint8_t *scratch_buffer;
 | 
			
		||||
  size_t scratch_buffer_size;
 | 
			
		||||
} FrameWorkerData;
 | 
			
		||||
 | 
			
		||||
// Allocate memory for loopfilter row synchronization.
 | 
			
		||||
void vp9_loop_filter_alloc(struct VP9Common *cm, VP9LfSync *lf_sync,
 | 
			
		||||
                           int rows, int width);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
#include "vp9/decoder/vp9_read_bit_buffer.h"
 | 
			
		||||
 | 
			
		||||
size_t vp9_rb_bytes_read(struct vp9_read_bit_buffer *rb) {
 | 
			
		||||
  return rb->bit_offset / CHAR_BIT + (rb->bit_offset % CHAR_BIT > 0);
 | 
			
		||||
  return (rb->bit_offset + CHAR_BIT - 1) / CHAR_BIT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_rb_read_bit(struct vp9_read_bit_buffer *rb) {
 | 
			
		||||
 
 | 
			
		||||
@@ -38,12 +38,32 @@ static struct vp9_token intra_mode_encodings[INTRA_MODES];
 | 
			
		||||
static struct vp9_token switchable_interp_encodings[SWITCHABLE_FILTERS];
 | 
			
		||||
static struct vp9_token partition_encodings[PARTITION_TYPES];
 | 
			
		||||
static struct vp9_token inter_mode_encodings[INTER_MODES];
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
static struct vp9_token copy_mode_encodings_l2[2];
 | 
			
		||||
static struct vp9_token copy_mode_encodings[COPY_MODE_COUNT - 1];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
static int vp9_check_supertx(VP9_COMMON *cm, int mi_row, int mi_col,
 | 
			
		||||
                             BLOCK_SIZE bsize) {
 | 
			
		||||
  MODE_INFO **mi;
 | 
			
		||||
 | 
			
		||||
  mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
 | 
			
		||||
 | 
			
		||||
  return mi[0]->mbmi.tx_size == bsize_to_tx_size(bsize) &&
 | 
			
		||||
         mi[0]->mbmi.sb_type < bsize;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_entropy_mode_init() {
 | 
			
		||||
  vp9_tokens_from_tree(intra_mode_encodings, vp9_intra_mode_tree);
 | 
			
		||||
  vp9_tokens_from_tree(switchable_interp_encodings, vp9_switchable_interp_tree);
 | 
			
		||||
  vp9_tokens_from_tree(partition_encodings, vp9_partition_tree);
 | 
			
		||||
  vp9_tokens_from_tree(inter_mode_encodings, vp9_inter_mode_tree);
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  vp9_tokens_from_tree(copy_mode_encodings_l2, vp9_copy_mode_tree_l2);
 | 
			
		||||
  vp9_tokens_from_tree(copy_mode_encodings, vp9_copy_mode_tree);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_intra_mode(vp9_writer *w, PREDICTION_MODE mode,
 | 
			
		||||
@@ -58,6 +78,21 @@ static void write_inter_mode(vp9_writer *w, PREDICTION_MODE mode,
 | 
			
		||||
                  &inter_mode_encodings[INTER_OFFSET(mode)]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
static void write_copy_mode(VP9_COMMON *cm, vp9_writer *w, COPY_MODE mode,
 | 
			
		||||
                            int inter_ref_count, int copy_mode_context) {
 | 
			
		||||
  if (inter_ref_count == 2) {
 | 
			
		||||
    vp9_write_token(w, vp9_copy_mode_tree_l2,
 | 
			
		||||
                    cm->fc.copy_mode_probs_l2[copy_mode_context],
 | 
			
		||||
                    ©_mode_encodings_l2[mode - REF0]);
 | 
			
		||||
  } else if (inter_ref_count > 2) {
 | 
			
		||||
    vp9_write_token(w, vp9_copy_mode_tree,
 | 
			
		||||
                    cm->fc.copy_mode_probs[copy_mode_context],
 | 
			
		||||
                    ©_mode_encodings[mode - REF0]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void encode_unsigned_max(struct vp9_write_bit_buffer *wb,
 | 
			
		||||
                                int data, int max) {
 | 
			
		||||
  vp9_wb_write_literal(wb, data, get_unsigned_bits(max));
 | 
			
		||||
@@ -225,6 +260,9 @@ static void write_ref_frames(const VP9_COMP *cpi, vp9_writer *w) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                                int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                                vp9_writer *w) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  const nmv_context *nmvc = &cm->fc.nmvc;
 | 
			
		||||
@@ -239,7 +277,19 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 | 
			
		||||
  const int is_inter = is_inter_block(mbmi);
 | 
			
		||||
  const int is_compound = has_second_ref(mbmi);
 | 
			
		||||
  int skip, ref;
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  int copy_mode_context = vp9_get_copy_mode_context(xd);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  if (bsize >= BLOCK_8X8 && mbmi->inter_ref_count > 0) {
 | 
			
		||||
      vp9_write(w, mbmi->copy_mode != NOREF,
 | 
			
		||||
                cm->fc.copy_noref_prob[copy_mode_context][bsize]);
 | 
			
		||||
      if (mbmi->copy_mode != NOREF)
 | 
			
		||||
        write_copy_mode(cm, w, mbmi->copy_mode, mbmi->inter_ref_count,
 | 
			
		||||
                        copy_mode_context);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  if (seg->update_map) {
 | 
			
		||||
    if (seg->temporal_update) {
 | 
			
		||||
      const int pred_flag = mbmi->seg_id_predicted;
 | 
			
		||||
@@ -252,20 +302,57 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (!supertx_enabled)
 | 
			
		||||
#endif
 | 
			
		||||
  skip = write_skip(cpi, segment_id, mi, w);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  else
 | 
			
		||||
    skip = mbmi->skip;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (!supertx_enabled) {
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  if (mbmi->copy_mode == NOREF)
 | 
			
		||||
#endif
 | 
			
		||||
  if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
 | 
			
		||||
    vp9_write(w, is_inter, vp9_get_intra_inter_prob(cm, xd));
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
      !supertx_enabled &&
 | 
			
		||||
#endif
 | 
			
		||||
      !(is_inter &&
 | 
			
		||||
        (skip || vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)))) {
 | 
			
		||||
    write_selected_tx_size(cpi, mbmi->tx_size, bsize, w);
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
    if (is_inter &&
 | 
			
		||||
        mbmi->tx_size <= TX_16X16 &&
 | 
			
		||||
        bsize >= BLOCK_8X8 &&
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
        !supertx_enabled &&
 | 
			
		||||
#endif
 | 
			
		||||
        !mbmi->skip &&
 | 
			
		||||
        !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
 | 
			
		||||
      vp9_write(w, mbmi->ext_txfrm, cm->fc.ext_tx_prob);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (!is_inter) {
 | 
			
		||||
    if (bsize >= BLOCK_8X8) {
 | 
			
		||||
      write_intra_mode(w, mode, cm->fc.y_mode_prob[size_group_lookup[bsize]]);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (is_filter_allowed(mode) && is_filter_enabled(mbmi->tx_size)) {
 | 
			
		||||
        vp9_write(w, mbmi->filterbit,
 | 
			
		||||
                  cm->fc.filterintra_prob[mbmi->tx_size][mode]);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
    } else {
 | 
			
		||||
      int idx, idy;
 | 
			
		||||
      const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
 | 
			
		||||
@@ -274,11 +361,28 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 | 
			
		||||
        for (idx = 0; idx < 2; idx += num_4x4_w) {
 | 
			
		||||
          const PREDICTION_MODE b_mode = mi->bmi[idy * 2 + idx].as_mode;
 | 
			
		||||
          write_intra_mode(w, b_mode, cm->fc.y_mode_prob[0]);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
          if (is_filter_allowed(b_mode)) {
 | 
			
		||||
            vp9_write(w, mi->b_filter_info[idy * 2 + idx],
 | 
			
		||||
                      cm->fc.filterintra_prob[0][b_mode]);
 | 
			
		||||
          }
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    write_intra_mode(w, mbmi->uv_mode, cm->fc.uv_mode_prob[mode]);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
    if (is_filter_allowed(mbmi->uv_mode) &&
 | 
			
		||||
        is_filter_enabled(get_uv_tx_size(mbmi))) {
 | 
			
		||||
      vp9_write(w, mbmi->uv_filterbit,
 | 
			
		||||
                cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
#if !CONFIG_COPY_CODING
 | 
			
		||||
  } else {
 | 
			
		||||
#else
 | 
			
		||||
  } else if (mbmi->copy_mode == NOREF) {
 | 
			
		||||
#endif
 | 
			
		||||
    const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
 | 
			
		||||
    const vp9_prob *const inter_probs = cm->fc.inter_mode_probs[mode_ctx];
 | 
			
		||||
    write_ref_frames(cpi, w);
 | 
			
		||||
@@ -300,6 +404,32 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 | 
			
		||||
      assert(mbmi->interp_filter == cm->interp_filter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    if ((cm->use_interintra) &&
 | 
			
		||||
        cpi->common.reference_mode != COMPOUND_REFERENCE &&
 | 
			
		||||
        is_interintra_allowed(bsize) &&
 | 
			
		||||
        is_inter_mode(mode) &&
 | 
			
		||||
        (mbmi->ref_frame[1] <= INTRA_FRAME)) {
 | 
			
		||||
        vp9_write(w, mbmi->ref_frame[1] == INTRA_FRAME,
 | 
			
		||||
                  cm->fc.interintra_prob[bsize]);
 | 
			
		||||
        if (mbmi->ref_frame[1] == INTRA_FRAME) {
 | 
			
		||||
          write_intra_mode(w, mbmi->interintra_mode,
 | 
			
		||||
                           cm->fc.y_mode_prob[size_group_lookup[bsize]]);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
        if (get_mask_bits_interintra(bsize) &&
 | 
			
		||||
            cm->use_masked_interintra) {
 | 
			
		||||
          vp9_write(w, mbmi->use_masked_interintra,
 | 
			
		||||
                    cm->fc.masked_interintra_prob[bsize]);
 | 
			
		||||
          if (mbmi->use_masked_interintra) {
 | 
			
		||||
            vp9_write_literal(w, mbmi->interintra_mask_index,
 | 
			
		||||
                              get_mask_bits_interintra(bsize));
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (bsize < BLOCK_8X8) {
 | 
			
		||||
      const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
 | 
			
		||||
      const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
 | 
			
		||||
@@ -326,6 +456,18 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 | 
			
		||||
                        allow_hp);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  if (cm->use_masked_interinter &&
 | 
			
		||||
      cm->reference_mode != SINGLE_REFERENCE &&
 | 
			
		||||
      is_inter_mode(mode) &&
 | 
			
		||||
      get_mask_bits(mbmi->sb_type) &&
 | 
			
		||||
      mbmi->ref_frame[1] > INTRA_FRAME) {
 | 
			
		||||
    vp9_write(w, mbmi->use_masked_interinter,
 | 
			
		||||
              cm->fc.masked_interinter_prob[bsize]);
 | 
			
		||||
    if (mbmi->use_masked_interinter)
 | 
			
		||||
      vp9_write_literal(w, mbmi->mask_index, get_mask_bits(mbmi->sb_type));
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -350,6 +492,11 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO **mi_8x8,
 | 
			
		||||
 | 
			
		||||
  if (bsize >= BLOCK_8X8) {
 | 
			
		||||
    write_intra_mode(w, mbmi->mode, get_y_mode_probs(mi, above_mi, left_mi, 0));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
    if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
 | 
			
		||||
      vp9_write(w, mbmi->filterbit,
 | 
			
		||||
                cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
 | 
			
		||||
#endif
 | 
			
		||||
  } else {
 | 
			
		||||
    const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
 | 
			
		||||
    const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
 | 
			
		||||
@@ -360,15 +507,29 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO **mi_8x8,
 | 
			
		||||
        const int block = idy * 2 + idx;
 | 
			
		||||
        write_intra_mode(w, mi->bmi[block].as_mode,
 | 
			
		||||
                         get_y_mode_probs(mi, above_mi, left_mi, block));
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
        if (is_filter_allowed(mi->bmi[block].as_mode))
 | 
			
		||||
          vp9_write(w, mi->b_filter_info[block],
 | 
			
		||||
                    cm->fc.filterintra_prob[0][mi->bmi[block].as_mode]);
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  write_intra_mode(w, mbmi->uv_mode, vp9_kf_uv_mode_prob[mbmi->mode]);
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  if (is_filter_allowed(mbmi->uv_mode) &&
 | 
			
		||||
      is_filter_enabled(get_uv_tx_size(mbmi)))
 | 
			
		||||
    vp9_write(w, mbmi->uv_filterbit,
 | 
			
		||||
              cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_modes_b(VP9_COMP *cpi, const TileInfo *const tile,
 | 
			
		||||
                          vp9_writer *w, TOKENEXTRA **tok, TOKENEXTRA *tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                          int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                          int mi_row, int mi_col) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 | 
			
		||||
@@ -384,11 +545,21 @@ static void write_modes_b(VP9_COMP *cpi, const TileInfo *const tile,
 | 
			
		||||
  if (frame_is_intra_only(cm)) {
 | 
			
		||||
    write_mb_modes_kf(cpi, xd->mi, w);
 | 
			
		||||
  } else {
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
    pack_inter_mode_mvs(cpi, m, supertx_enabled, w);
 | 
			
		||||
#else
 | 
			
		||||
    pack_inter_mode_mvs(cpi, m, w);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (!supertx_enabled) {
 | 
			
		||||
#endif
 | 
			
		||||
  assert(*tok < tok_end);
 | 
			
		||||
  pack_mb_tokens(w, tok, tok_end);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_partition(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
@@ -415,6 +586,9 @@ static void write_partition(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
static void write_modes_sb(VP9_COMP *cpi,
 | 
			
		||||
                           const TileInfo *const tile,
 | 
			
		||||
                           vp9_writer *w, TOKENEXTRA **tok, TOKENEXTRA *tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                           int pack_token, int supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                           int mi_row, int mi_col, BLOCK_SIZE bsize) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 | 
			
		||||
@@ -431,36 +605,105 @@ static void write_modes_sb(VP9_COMP *cpi,
 | 
			
		||||
  partition = partition_lookup[bsl][m->mbmi.sb_type];
 | 
			
		||||
  write_partition(cm, xd, bs, mi_row, mi_col, partition, bsize, w);
 | 
			
		||||
  subsize = get_subsize(bsize, partition);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
 | 
			
		||||
  set_mi_row_col(xd, tile,
 | 
			
		||||
                 mi_row, num_8x8_blocks_high_lookup[bsize],
 | 
			
		||||
                 mi_col, num_8x8_blocks_wide_lookup[bsize],
 | 
			
		||||
                 cm->mi_rows, cm->mi_cols);
 | 
			
		||||
  if (!supertx_enabled && cm->frame_type != KEY_FRAME &&
 | 
			
		||||
      partition != PARTITION_NONE && bsize <= BLOCK_32X32) {
 | 
			
		||||
    TX_SIZE supertx_size = bsize_to_tx_size(bsize);  // b_width_log2(bsize);
 | 
			
		||||
    vp9_prob prob = partition == PARTITION_SPLIT ?
 | 
			
		||||
                    cm->fc.supertxsplit_prob[supertx_size] :
 | 
			
		||||
                    cm->fc.supertx_prob[supertx_size];
 | 
			
		||||
    supertx_enabled = (xd->mi[0]->mbmi.tx_size == supertx_size);
 | 
			
		||||
    vp9_write(w, supertx_enabled, prob);
 | 
			
		||||
    if (supertx_enabled) {
 | 
			
		||||
      vp9_write(w, xd->mi[0]->mbmi.skip, vp9_get_skip_prob(cm, xd));
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (supertx_size <= TX_16X16 && !xd->mi[0]->mbmi.skip)
 | 
			
		||||
        vp9_write(w, xd->mi[0]->mbmi.ext_txfrm, cm->fc.ext_tx_prob);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  if (subsize < BLOCK_8X8) {
 | 
			
		||||
    write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
 | 
			
		||||
    write_modes_b(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                  supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                  mi_row, mi_col);
 | 
			
		||||
  } else {
 | 
			
		||||
    switch (partition) {
 | 
			
		||||
      case PARTITION_NONE:
 | 
			
		||||
        write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
 | 
			
		||||
        write_modes_b(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                      supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                      mi_row, mi_col);
 | 
			
		||||
        break;
 | 
			
		||||
      case PARTITION_HORZ:
 | 
			
		||||
        write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
 | 
			
		||||
        write_modes_b(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                      supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                      mi_row, mi_col);
 | 
			
		||||
        if (mi_row + bs < cm->mi_rows)
 | 
			
		||||
          write_modes_b(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col);
 | 
			
		||||
          write_modes_b(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                        supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                        mi_row + bs, mi_col);
 | 
			
		||||
        break;
 | 
			
		||||
      case PARTITION_VERT:
 | 
			
		||||
        write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
 | 
			
		||||
        write_modes_b(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                      supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                      mi_row, mi_col);
 | 
			
		||||
        if (mi_col + bs < cm->mi_cols)
 | 
			
		||||
          write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs);
 | 
			
		||||
          write_modes_b(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                        supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                        mi_row, mi_col + bs);
 | 
			
		||||
        break;
 | 
			
		||||
      case PARTITION_SPLIT:
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, subsize);
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs,
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row, mi_col, subsize);
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row, mi_col + bs,
 | 
			
		||||
                       subsize);
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col,
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row + bs, mi_col,
 | 
			
		||||
                       subsize);
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col + bs,
 | 
			
		||||
        write_modes_sb(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                       !supertx_enabled, supertx_enabled,
 | 
			
		||||
#endif
 | 
			
		||||
                       mi_row + bs, mi_col + bs,
 | 
			
		||||
                       subsize);
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        assert(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
  if (partition != PARTITION_NONE && supertx_enabled && pack_token) {
 | 
			
		||||
    assert(*tok < tok_end);
 | 
			
		||||
    pack_mb_tokens(w, tok, tok_end);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // update partition context
 | 
			
		||||
  if (bsize >= BLOCK_8X8 &&
 | 
			
		||||
@@ -478,7 +721,11 @@ static void write_modes(VP9_COMP *cpi,
 | 
			
		||||
    vp9_zero(cpi->mb.e_mbd.left_seg_context);
 | 
			
		||||
    for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
 | 
			
		||||
         mi_col += MI_BLOCK_SIZE)
 | 
			
		||||
      write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col,
 | 
			
		||||
      write_modes_sb(cpi, tile, w, tok, tok_end,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                     1, 0,
 | 
			
		||||
#endif
 | 
			
		||||
                     mi_row, mi_col,
 | 
			
		||||
                     BLOCK_64X64);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -890,14 +1137,8 @@ static void write_tile_info(VP9_COMMON *cm, struct vp9_write_bit_buffer *wb) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_refresh_mask(VP9_COMP *cpi) {
 | 
			
		||||
    // Should the GF or ARF be updated using the transmitted frame or buffer
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
 | 
			
		||||
        !cpi->refresh_alt_ref_frame) {
 | 
			
		||||
#else
 | 
			
		||||
    if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame &&
 | 
			
		||||
        !cpi->use_svc) {
 | 
			
		||||
#endif
 | 
			
		||||
    if (!cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
 | 
			
		||||
        cpi->rc.is_src_frame_alt_ref && !cpi->use_svc) {
 | 
			
		||||
      // Preserve the previously existing golden frame and update the frame in
 | 
			
		||||
      // the alt ref slot instead. This is highly specific to the use of
 | 
			
		||||
      // alt-ref as a forward reference, and this needs to be generalized as
 | 
			
		||||
@@ -910,15 +1151,10 @@ static int get_refresh_mask(VP9_COMP *cpi) {
 | 
			
		||||
             (cpi->refresh_golden_frame << cpi->alt_fb_idx);
 | 
			
		||||
    } else {
 | 
			
		||||
      int arf_idx = cpi->alt_fb_idx;
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
      // Determine which ARF buffer to use to encode this ARF frame.
 | 
			
		||||
      if (cpi->multi_arf_enabled) {
 | 
			
		||||
        int sn = cpi->sequence_number;
 | 
			
		||||
        arf_idx = (cpi->frame_coding_order[sn] < 0) ?
 | 
			
		||||
            cpi->arf_buffer_idx[sn + 1] :
 | 
			
		||||
            cpi->arf_buffer_idx[sn];
 | 
			
		||||
      if ((cpi->pass == 2) && cpi->multi_arf_allowed) {
 | 
			
		||||
        const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
 | 
			
		||||
        arf_idx = gf_group->arf_update_idx[gf_group->index];
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
 | 
			
		||||
             (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
 | 
			
		||||
             (cpi->refresh_alt_ref_frame << arf_idx);
 | 
			
		||||
@@ -1187,6 +1423,104 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) {
 | 
			
		||||
                       cm->counts.partition[i], PARTITION_TYPES, &header_bc);
 | 
			
		||||
 | 
			
		||||
    vp9_write_nmv_probs(cm, cm->allow_high_precision_mv, &header_bc);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
    vp9_cond_prob_diff_update(&header_bc, &fc->ext_tx_prob, cm->counts.ext_tx);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    if (cm->reference_mode != SINGLE_REFERENCE) {
 | 
			
		||||
      if (!cpi->dummy_packing && cm->use_masked_interinter) {
 | 
			
		||||
        cm->use_masked_interinter = 0;
 | 
			
		||||
        for (i = 0; i < BLOCK_SIZES; i++)
 | 
			
		||||
          if (get_mask_bits(i) && (cm->counts.masked_interinter[i][1] > 0)) {
 | 
			
		||||
            cm->use_masked_interinter = 1;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
      vp9_write_bit(&header_bc, cm->use_masked_interinter);
 | 
			
		||||
      if (cm->use_masked_interinter) {
 | 
			
		||||
        for (i = 0; i < BLOCK_SIZES; i++)
 | 
			
		||||
          if (get_mask_bits(i))
 | 
			
		||||
            vp9_cond_prob_diff_update(&header_bc,
 | 
			
		||||
                                      &fc->masked_interinter_prob[i],
 | 
			
		||||
                                      cm->counts.masked_interinter[i]);
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_zero(cm->counts.masked_interinter);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (!cpi->dummy_packing)
 | 
			
		||||
        cm->use_masked_interinter = 0;
 | 
			
		||||
      vp9_zero(cm->counts.masked_interinter);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    if (cm->reference_mode != COMPOUND_REFERENCE) {
 | 
			
		||||
      if (!cpi->dummy_packing && cm->use_interintra) {
 | 
			
		||||
        cm->use_interintra = 0;
 | 
			
		||||
        for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
          if (is_interintra_allowed(i) && (cm->counts.interintra[i][1] > 0)) {
 | 
			
		||||
            cm->use_interintra = 1;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      vp9_write_bit(&header_bc, cm->use_interintra);
 | 
			
		||||
      if (cm->use_interintra) {
 | 
			
		||||
        for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
          if (is_interintra_allowed(i)) {
 | 
			
		||||
            vp9_cond_prob_diff_update(&header_bc,
 | 
			
		||||
                                      &fc->interintra_prob[i],
 | 
			
		||||
                                      cm->counts.interintra[i]);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
        if (!cpi->dummy_packing && cm->use_masked_interintra) {
 | 
			
		||||
          cm->use_masked_interintra = 0;
 | 
			
		||||
          for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
            if (is_interintra_allowed(i) && get_mask_bits_interintra(i) &&
 | 
			
		||||
                (cm->counts.masked_interintra[i][1] > 0)) {
 | 
			
		||||
              cm->use_masked_interintra = 1;
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        vp9_write_bit(&header_bc, cm->use_masked_interintra);
 | 
			
		||||
        if (cm->use_masked_interintra) {
 | 
			
		||||
          for (i = 0; i < BLOCK_SIZES; i++) {
 | 
			
		||||
            if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
 | 
			
		||||
              vp9_cond_prob_diff_update(&header_bc,
 | 
			
		||||
                                        &fc->masked_interintra_prob[i],
 | 
			
		||||
                                        cm->counts.masked_interintra[i]);
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          vp9_zero(cm->counts.masked_interintra);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_zero(cm->counts.interintra);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (!cpi->dummy_packing)
 | 
			
		||||
        cm->use_interintra = 0;
 | 
			
		||||
      vp9_zero(cm->counts.interintra);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
      if (!cpi->dummy_packing)
 | 
			
		||||
        cm->use_masked_interintra = 0;
 | 
			
		||||
      vp9_zero(cm->counts.masked_interintra);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
    for (i = 0; i < COPY_MODE_CONTEXTS; i++) {
 | 
			
		||||
      prob_diff_update(vp9_copy_mode_tree_l2, cm->fc.copy_mode_probs_l2[i],
 | 
			
		||||
                       cm->counts.copy_mode_l2[i], 2, &header_bc);
 | 
			
		||||
      prob_diff_update(vp9_copy_mode_tree, cm->fc.copy_mode_probs[i],
 | 
			
		||||
                       cm->counts.copy_mode[i], 3, &header_bc);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vp9_stop_encode(&header_bc);
 | 
			
		||||
 
 | 
			
		||||
@@ -93,8 +93,6 @@ struct macroblock {
 | 
			
		||||
 | 
			
		||||
  int encode_breakout;
 | 
			
		||||
 | 
			
		||||
  int in_active_map;
 | 
			
		||||
 | 
			
		||||
  // note that token_costs is the cost when eob node is skipped
 | 
			
		||||
  vp9_coeff_cost token_costs[TX_SIZES];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,10 @@
 | 
			
		||||
 *  be found in the AUTHORS file in the root of the source tree.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "vp9/encoder/vp9_denoiser.h"
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include "vpx_scale/yv12config.h"
 | 
			
		||||
#include "vpx/vpx_integer.h"
 | 
			
		||||
#include "vp9/encoder/vp9_denoiser.h"
 | 
			
		||||
 | 
			
		||||
static const int widths[]  = {4, 4, 8, 8,  8, 16, 16, 16, 32, 32, 32, 64, 64};
 | 
			
		||||
static const int heights[] = {4, 8, 4, 8, 16,  8, 16, 32, 16, 32, 64, 32, 64};
 | 
			
		||||
@@ -20,30 +20,180 @@ int vp9_denoiser_filter() {
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_denoise(VP9_DENOISER *denoiser,
 | 
			
		||||
                          MACROBLOCK *mb, MODE_INFO **grid,
 | 
			
		||||
static int update_running_avg(const uint8_t *mc_avg, int mc_avg_stride,
 | 
			
		||||
                              uint8_t *avg, int avg_stride,
 | 
			
		||||
                              const uint8_t *sig, int sig_stride,
 | 
			
		||||
                              int increase_denoising, BLOCK_SIZE bs) {
 | 
			
		||||
  int r, c;
 | 
			
		||||
  int diff, adj, absdiff;
 | 
			
		||||
  int shift_inc1 = 0, shift_inc2 = 1;
 | 
			
		||||
  int adj_val[] = {3, 4, 6};
 | 
			
		||||
  int total_adj = 0;
 | 
			
		||||
 | 
			
		||||
  if (increase_denoising) {
 | 
			
		||||
    shift_inc1 = 1;
 | 
			
		||||
    shift_inc2 = 2;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (r = 0; r < heights[bs]; ++r) {
 | 
			
		||||
    for (c = 0; c < widths[bs]; ++c) {
 | 
			
		||||
      diff = mc_avg[c] - sig[c];
 | 
			
		||||
      absdiff = abs(diff);
 | 
			
		||||
 | 
			
		||||
      if (absdiff <= 3 + shift_inc1) {
 | 
			
		||||
        avg[c] = mc_avg[c];
 | 
			
		||||
        total_adj += diff;
 | 
			
		||||
      } else {
 | 
			
		||||
        switch (absdiff) {
 | 
			
		||||
          case 4: case 5: case 6: case 7:
 | 
			
		||||
            adj = adj_val[0];
 | 
			
		||||
            break;
 | 
			
		||||
          case 8: case 9: case 10: case 11:
 | 
			
		||||
          case 12: case 13: case 14: case 15:
 | 
			
		||||
            adj = adj_val[1];
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            adj = adj_val[2];
 | 
			
		||||
        }
 | 
			
		||||
        if (diff > 0) {
 | 
			
		||||
          avg[c] = MIN(UINT8_MAX, sig[c] + adj);
 | 
			
		||||
          total_adj += adj;
 | 
			
		||||
        } else {
 | 
			
		||||
          avg[c] = MAX(0, sig[c] - adj);
 | 
			
		||||
          total_adj -= adj;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    sig += sig_stride;
 | 
			
		||||
    avg += avg_stride;
 | 
			
		||||
    mc_avg += mc_avg_stride;
 | 
			
		||||
  }
 | 
			
		||||
  return total_adj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t *block_start(uint8_t *framebuf, int stride,
 | 
			
		||||
                            int mi_row, int mi_col) {
 | 
			
		||||
  return framebuf + (stride * mi_row * 8) + (mi_col * 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void copy_block(uint8_t *dest, int dest_stride,
 | 
			
		||||
                uint8_t *src, int src_stride, BLOCK_SIZE bs) {
 | 
			
		||||
  int r, c;
 | 
			
		||||
  for (r = 0; r < heights[bs]; ++r) {
 | 
			
		||||
    for (c = 0; c < widths[bs]; ++c) {
 | 
			
		||||
      dest[c] = src[c];
 | 
			
		||||
    }
 | 
			
		||||
    dest += dest_stride;
 | 
			
		||||
    src += src_stride;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
 | 
			
		||||
                          int mi_row, int mi_col, BLOCK_SIZE bs) {
 | 
			
		||||
  return;
 | 
			
		||||
  int decision = COPY_BLOCK;
 | 
			
		||||
 | 
			
		||||
  YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
 | 
			
		||||
  YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
 | 
			
		||||
  uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col);
 | 
			
		||||
  uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride,
 | 
			
		||||
                                          mi_row, mi_col);
 | 
			
		||||
  struct buf_2d src = mb->plane[0].src;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  update_running_avg(mc_avg_start, mc_avg.y_stride, avg_start, avg.y_stride,
 | 
			
		||||
                     mb->plane[0].src.buf, mb->plane[0].src.stride, 0, bs);
 | 
			
		||||
 | 
			
		||||
  if (decision == FILTER_BLOCK) {
 | 
			
		||||
    // TODO(tkopp)
 | 
			
		||||
  }
 | 
			
		||||
  if (decision == COPY_BLOCK) {
 | 
			
		||||
    copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) {
 | 
			
		||||
  int r, c;
 | 
			
		||||
  const uint8_t *srcbuf = src.y_buffer;
 | 
			
		||||
  uint8_t *destbuf = dest.y_buffer;
 | 
			
		||||
  assert(dest.y_width == src.y_width);
 | 
			
		||||
  assert(dest.y_height == src.y_height);
 | 
			
		||||
 | 
			
		||||
  for (r = 0; r < dest.y_height; ++r) {
 | 
			
		||||
    for (c = 0; c < dest.y_width; ++c) {
 | 
			
		||||
      destbuf[c] = srcbuf[c];
 | 
			
		||||
    }
 | 
			
		||||
    destbuf += dest.y_stride;
 | 
			
		||||
    srcbuf += src.y_stride;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
 | 
			
		||||
                                    YV12_BUFFER_CONFIG src,
 | 
			
		||||
                                    FRAME_TYPE frame_type,
 | 
			
		||||
                                    int refresh_alt_ref_frame,
 | 
			
		||||
                                    int refresh_golden_frame,
 | 
			
		||||
                                    int refresh_last_frame) {
 | 
			
		||||
  return;
 | 
			
		||||
  if (frame_type == KEY_FRAME) {
 | 
			
		||||
    int i;
 | 
			
		||||
    copy_frame(denoiser->running_avg_y[LAST_FRAME], src);
 | 
			
		||||
    for (i = 2; i < MAX_REF_FRAMES - 1; i++) {
 | 
			
		||||
      copy_frame(denoiser->running_avg_y[i],
 | 
			
		||||
                 denoiser->running_avg_y[LAST_FRAME]);
 | 
			
		||||
    }
 | 
			
		||||
  } else {  /* For non key frames */
 | 
			
		||||
    if (refresh_alt_ref_frame) {
 | 
			
		||||
      copy_frame(denoiser->running_avg_y[ALTREF_FRAME],
 | 
			
		||||
                 denoiser->running_avg_y[INTRA_FRAME]);
 | 
			
		||||
    }
 | 
			
		||||
    if (refresh_golden_frame) {
 | 
			
		||||
      copy_frame(denoiser->running_avg_y[GOLDEN_FRAME],
 | 
			
		||||
                 denoiser->running_avg_y[INTRA_FRAME]);
 | 
			
		||||
    }
 | 
			
		||||
    if (refresh_last_frame) {
 | 
			
		||||
      copy_frame(denoiser->running_avg_y[LAST_FRAME],
 | 
			
		||||
                 denoiser->running_avg_y[INTRA_FRAME]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_update_frame_stats() {
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
 | 
			
		||||
                       int border) {
 | 
			
		||||
                       int ssx, int ssy, int border) {
 | 
			
		||||
  int i, fail;
 | 
			
		||||
  assert(denoiser != NULL);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < MAX_REF_FRAMES; ++i) {
 | 
			
		||||
    fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
 | 
			
		||||
                                  ssx, ssy, border);
 | 
			
		||||
    if (fail) {
 | 
			
		||||
      vp9_denoiser_free(denoiser);
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
 | 
			
		||||
                                ssx, ssy, border);
 | 
			
		||||
  if (fail) {
 | 
			
		||||
    vp9_denoiser_free(denoiser);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_free(VP9_DENOISER *denoiser) {
 | 
			
		||||
  return;
 | 
			
		||||
  int i;
 | 
			
		||||
  if (denoiser == NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  for (i = 0; i < MAX_REF_FRAMES; ++i) {
 | 
			
		||||
    if (&denoiser->running_avg_y[i] != NULL) {
 | 
			
		||||
      vp9_free_frame_buffer(&denoiser->running_avg_y[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (&denoiser->mc_running_avg_y != NULL) {
 | 
			
		||||
    vp9_free_frame_buffer(&denoiser->mc_running_avg_y);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
#define VP9_ENCODER_DENOISER_H_
 | 
			
		||||
 | 
			
		||||
#include "vp9/encoder/vp9_block.h"
 | 
			
		||||
#include "vpx_scale/yv12config.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
@@ -23,24 +24,24 @@ enum vp9_denoiser_decision {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct vp9_denoiser {
 | 
			
		||||
  struct buf_2d running_avg_y;
 | 
			
		||||
  struct buf_2d mc_running_avg_y;
 | 
			
		||||
  YV12_BUFFER_CONFIG running_avg_y[MAX_REF_FRAMES];
 | 
			
		||||
  YV12_BUFFER_CONFIG mc_running_avg_y;
 | 
			
		||||
} VP9_DENOISER;
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
 | 
			
		||||
                                    YV12_BUFFER_CONFIG src,
 | 
			
		||||
                                    FRAME_TYPE frame_type,
 | 
			
		||||
                                    int refresh_alt_ref_frame,
 | 
			
		||||
                                    int refresh_golden_frame,
 | 
			
		||||
                                    int refresh_last_frame);
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_denoise(VP9_DENOISER *denoiser,
 | 
			
		||||
                          MACROBLOCK *mb, MODE_INFO **grid,
 | 
			
		||||
void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
 | 
			
		||||
                          int mi_row, int mi_col, BLOCK_SIZE bs);
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_update_frame_stats();
 | 
			
		||||
 | 
			
		||||
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
 | 
			
		||||
                       int border);
 | 
			
		||||
                       int ssx, int ssy, int border);
 | 
			
		||||
 | 
			
		||||
void vp9_denoiser_free(VP9_DENOISER *denoiser);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -360,6 +360,9 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
 | 
			
		||||
  const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
 | 
			
		||||
  int i, j;
 | 
			
		||||
  const int16_t *src_diff;
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
#endif
 | 
			
		||||
  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
 | 
			
		||||
  src_diff = &p->src_diff[4 * (j * diff_stride + i)];
 | 
			
		||||
 | 
			
		||||
@@ -372,21 +375,45 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
 | 
			
		||||
                           scan_order->iscan);
 | 
			
		||||
      break;
 | 
			
		||||
    case TX_16X16:
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (plane != 0 || mbmi->ext_txfrm == NORM) {
 | 
			
		||||
#endif
 | 
			
		||||
      vp9_fdct16x16(src_diff, coeff, diff_stride);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_fht16x16(src_diff, coeff, diff_stride, ADST_ADST);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      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,
 | 
			
		||||
                     scan_order->scan, scan_order->iscan);
 | 
			
		||||
      break;
 | 
			
		||||
    case TX_8X8:
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (plane != 0 || mbmi->ext_txfrm == NORM) {
 | 
			
		||||
#endif
 | 
			
		||||
      vp9_fdct8x8(src_diff, coeff, diff_stride);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_fht8x8(src_diff, coeff, diff_stride, ADST_ADST);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      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,
 | 
			
		||||
                     scan_order->scan, scan_order->iscan);
 | 
			
		||||
      break;
 | 
			
		||||
    case TX_4X4:
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (plane != 0 || mbmi->ext_txfrm == NORM) {
 | 
			
		||||
#endif
 | 
			
		||||
      x->fwd_txm4x4(src_diff, coeff, diff_stride);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_fht4x4(src_diff, coeff, diff_stride, ADST_ADST);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      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,
 | 
			
		||||
@@ -409,6 +436,9 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
  int i, j;
 | 
			
		||||
  uint8_t *dst;
 | 
			
		||||
  ENTROPY_CONTEXT *a, *l;
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
#endif
 | 
			
		||||
  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
 | 
			
		||||
  dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
 | 
			
		||||
  a = &ctx->ta[plane][i];
 | 
			
		||||
@@ -454,16 +484,43 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
      vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
 | 
			
		||||
      break;
 | 
			
		||||
    case TX_16X16:
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (plane != 0 || mbmi->ext_txfrm == NORM) {
 | 
			
		||||
#endif
 | 
			
		||||
      vp9_idct16x16_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_iht16x16_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
 | 
			
		||||
                         p->eobs[block]);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    case TX_8X8:
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (plane != 0 || mbmi->ext_txfrm == NORM) {
 | 
			
		||||
#endif
 | 
			
		||||
      vp9_idct8x8_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_iht8x8_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
 | 
			
		||||
                       p->eobs[block]);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    case TX_4X4:
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      if (plane != 0 || mbmi->ext_txfrm == NORM) {
 | 
			
		||||
#endif
 | 
			
		||||
      // this is like vp9_short_idct4x4 but has a special case around eob<=1
 | 
			
		||||
      // which is significant (not just an optimization) for the lossless
 | 
			
		||||
      // case.
 | 
			
		||||
      x->itxm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
      } else {
 | 
			
		||||
        vp9_iht4x4_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
 | 
			
		||||
                       p->eobs[block]);
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0 && "Invalid transform size");
 | 
			
		||||
@@ -479,6 +536,10 @@ static void encode_block_pass1(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
  int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
 | 
			
		||||
  int i, j;
 | 
			
		||||
  uint8_t *dst;
 | 
			
		||||
#if CONFIG_EXT_TX
 | 
			
		||||
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
  mbmi->ext_txfrm = NORM;
 | 
			
		||||
#endif
 | 
			
		||||
  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
 | 
			
		||||
  dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
 | 
			
		||||
 | 
			
		||||
@@ -517,6 +578,26 @@ void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void vp9_encode_sb_supertx(MACROBLOCK *x, BLOCK_SIZE bsize) {
 | 
			
		||||
  MACROBLOCKD *const xd = &x->e_mbd;
 | 
			
		||||
  struct optimize_ctx ctx;
 | 
			
		||||
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
  struct encode_b_args arg = {x, &ctx, &mbmi->skip};
 | 
			
		||||
  int plane;
 | 
			
		||||
 | 
			
		||||
  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
 | 
			
		||||
    BLOCK_SIZE plane_size = bsize - 3 * (plane > 0);
 | 
			
		||||
    const struct macroblockd_plane* const pd = &xd->plane[plane];
 | 
			
		||||
    const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi) : mbmi->tx_size;
 | 
			
		||||
    vp9_subtract_plane(x, bsize, plane);
 | 
			
		||||
    vp9_get_entropy_contexts(bsize, tx_size, pd,
 | 
			
		||||
                             ctx.ta[plane], ctx.tl[plane]);
 | 
			
		||||
    encode_block(plane, 0, plane_size, bsize_to_tx_size(plane_size), &arg);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
                               TX_SIZE tx_size, void *arg) {
 | 
			
		||||
  struct encode_b_args* const args = arg;
 | 
			
		||||
@@ -531,6 +612,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
  const scan_order *scan_order;
 | 
			
		||||
  TX_TYPE tx_type;
 | 
			
		||||
  PREDICTION_MODE mode;
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
  int fbit = 0;
 | 
			
		||||
#endif
 | 
			
		||||
  const int bwl = b_width_log2(plane_bsize);
 | 
			
		||||
  const int diff_stride = 4 * (1 << bwl);
 | 
			
		||||
  uint8_t *src, *dst;
 | 
			
		||||
@@ -544,11 +628,20 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
  src = &p->src.buf[4 * (j * src_stride + i)];
 | 
			
		||||
  src_diff = &p->src_diff[4 * (j * diff_stride + i)];
 | 
			
		||||
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
      if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
 | 
			
		||||
        fbit = xd->mi[0]->b_filter_info[block];
 | 
			
		||||
      else
 | 
			
		||||
        fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
 | 
			
		||||
#endif
 | 
			
		||||
  switch (tx_size) {
 | 
			
		||||
    case TX_32X32:
 | 
			
		||||
      scan_order = &vp9_default_scan_orders[TX_32X32];
 | 
			
		||||
      mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
 | 
			
		||||
      vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                              fbit,
 | 
			
		||||
#endif
 | 
			
		||||
                              x->skip_encode ? src : dst,
 | 
			
		||||
                              x->skip_encode ? src_stride : dst_stride,
 | 
			
		||||
                              dst, dst_stride, i, j, plane);
 | 
			
		||||
@@ -569,6 +662,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
      scan_order = &vp9_scan_orders[TX_16X16][tx_type];
 | 
			
		||||
      mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
 | 
			
		||||
      vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                              fbit,
 | 
			
		||||
#endif
 | 
			
		||||
                              x->skip_encode ? src : dst,
 | 
			
		||||
                              x->skip_encode ? src_stride : dst_stride,
 | 
			
		||||
                              dst, dst_stride, i, j, plane);
 | 
			
		||||
@@ -589,6 +685,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
      scan_order = &vp9_scan_orders[TX_8X8][tx_type];
 | 
			
		||||
      mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
 | 
			
		||||
      vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                              fbit,
 | 
			
		||||
#endif
 | 
			
		||||
                              x->skip_encode ? src : dst,
 | 
			
		||||
                              x->skip_encode ? src_stride : dst_stride,
 | 
			
		||||
                              dst, dst_stride, i, j, plane);
 | 
			
		||||
@@ -609,6 +708,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
 | 
			
		||||
      scan_order = &vp9_scan_orders[TX_4X4][tx_type];
 | 
			
		||||
      mode = plane == 0 ? get_y_mode(xd->mi[0], block) : mbmi->uv_mode;
 | 
			
		||||
      vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                              fbit,
 | 
			
		||||
#endif
 | 
			
		||||
                              x->skip_encode ? src : dst,
 | 
			
		||||
                              x->skip_encode ? src_stride : dst_stride,
 | 
			
		||||
                              dst, dst_stride, i, j, plane);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,9 @@ extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void vp9_encode_sb_supertx(MACROBLOCK *x, BLOCK_SIZE bsize);
 | 
			
		||||
#endif
 | 
			
		||||
void vp9_encode_sby_pass1(MACROBLOCK *x, BLOCK_SIZE bsize);
 | 
			
		||||
void vp9_xform_quant_fp(MACROBLOCK *x, int plane, int block,
 | 
			
		||||
                        BLOCK_SIZE plane_bsize, TX_SIZE tx_size);
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,9 @@ void vp9_coef_tree_initialize();
 | 
			
		||||
 | 
			
		||||
// #define OUTPUT_YUV_REC
 | 
			
		||||
 | 
			
		||||
#ifdef OUTPUT_YUV_DENOISED
 | 
			
		||||
FILE *yuv_denoised_file;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef OUTPUT_YUV_SRC
 | 
			
		||||
FILE *yuv_file;
 | 
			
		||||
#endif
 | 
			
		||||
@@ -103,7 +106,7 @@ static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
 | 
			
		||||
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
 | 
			
		||||
  MACROBLOCK *const mb = &cpi->mb;
 | 
			
		||||
  cpi->common.allow_high_precision_mv = allow_high_precision_mv;
 | 
			
		||||
  if (cpi->common.allow_high_precision_mv) {
 | 
			
		||||
@@ -142,8 +145,6 @@ void vp9_initialize_enc() {
 | 
			
		||||
 | 
			
		||||
  if (!init_done) {
 | 
			
		||||
    vp9_init_neighbors();
 | 
			
		||||
    vp9_init_quant_tables();
 | 
			
		||||
 | 
			
		||||
    vp9_coef_tree_initialize();
 | 
			
		||||
    vp9_tokenize_initialize();
 | 
			
		||||
    vp9_init_me_luts();
 | 
			
		||||
@@ -173,10 +174,8 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
 | 
			
		||||
  vp9_cyclic_refresh_free(cpi->cyclic_refresh);
 | 
			
		||||
  cpi->cyclic_refresh = NULL;
 | 
			
		||||
 | 
			
		||||
  vpx_free(cpi->active_map);
 | 
			
		||||
  cpi->active_map = NULL;
 | 
			
		||||
 | 
			
		||||
  vp9_free_frame_buffers(cm);
 | 
			
		||||
  vp9_free_context_buffers(cm);
 | 
			
		||||
 | 
			
		||||
  vp9_free_frame_buffer(&cpi->last_frame_uf);
 | 
			
		||||
  vp9_free_frame_buffer(&cpi->scaled_source);
 | 
			
		||||
@@ -414,39 +413,46 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
 | 
			
		||||
                       "Failed to allocate altref buffer");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_alloc_compressor_data(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *cm = &cpi->common;
 | 
			
		||||
 | 
			
		||||
static void alloc_ref_frame_buffers(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  if (vp9_alloc_frame_buffers(cm, cm->width, cm->height))
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                       "Failed to allocate frame buffers");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  if (vp9_alloc_frame_buffer(&cpi->last_frame_uf,
 | 
			
		||||
                             cm->width, cm->height,
 | 
			
		||||
                             cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                             VP9_ENC_BORDER_IN_PIXELS))
 | 
			
		||||
static void alloc_util_frame_buffers(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
 | 
			
		||||
                               cm->width, cm->height,
 | 
			
		||||
                               cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                       "Failed to allocate last frame buffer");
 | 
			
		||||
 | 
			
		||||
  if (vp9_alloc_frame_buffer(&cpi->scaled_source,
 | 
			
		||||
                             cm->width, cm->height,
 | 
			
		||||
                             cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                             VP9_ENC_BORDER_IN_PIXELS))
 | 
			
		||||
  if (vp9_realloc_frame_buffer(&cpi->scaled_source,
 | 
			
		||||
                               cm->width, cm->height,
 | 
			
		||||
                               cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                       "Failed to allocate scaled source buffer");
 | 
			
		||||
 | 
			
		||||
  if (vp9_alloc_frame_buffer(&cpi->scaled_last_source,
 | 
			
		||||
                             cm->width, cm->height,
 | 
			
		||||
                             cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                             VP9_ENC_BORDER_IN_PIXELS))
 | 
			
		||||
  if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
 | 
			
		||||
                               cm->width, cm->height,
 | 
			
		||||
                               cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                       "Failed to allocate scaled last source buffer");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_alloc_compressor_data(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *cm = &cpi->common;
 | 
			
		||||
 | 
			
		||||
  vp9_alloc_context_buffers(cm, cm->width, cm->height);
 | 
			
		||||
 | 
			
		||||
  vpx_free(cpi->tok);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols);
 | 
			
		||||
 | 
			
		||||
    CHECK_MEM_ERROR(cm, cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -456,41 +462,7 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) {
 | 
			
		||||
static void update_frame_size(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 | 
			
		||||
 | 
			
		||||
  vp9_update_frame_size(cm);
 | 
			
		||||
 | 
			
		||||
  // Update size of buffers local to this frame
 | 
			
		||||
  if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
 | 
			
		||||
                               cm->width, cm->height,
 | 
			
		||||
                               cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
 | 
			
		||||
    vpx_internal_error(&cm->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,
 | 
			
		||||
                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                       "Failed to reallocate scaled source buffer");
 | 
			
		||||
 | 
			
		||||
  if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
 | 
			
		||||
                               cm->width, cm->height,
 | 
			
		||||
                               cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
 | 
			
		||||
    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                       "Failed to reallocate scaled last source buffer");
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    int y_stride = cpi->scaled_source.y_stride;
 | 
			
		||||
 | 
			
		||||
    if (cpi->sf.mv.search_method == NSTEP) {
 | 
			
		||||
      vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride);
 | 
			
		||||
    } else if (cpi->sf.mv.search_method == DIAMOND) {
 | 
			
		||||
      vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  init_macroblockd(cm, xd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -518,6 +490,12 @@ static void set_tile_limits(VP9_COMP *cpi) {
 | 
			
		||||
  cm->log2_tile_rows = cpi->oxcf.tile_rows;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_buffer_indices(VP9_COMP *cpi) {
 | 
			
		||||
  cpi->lst_fb_idx = 0;
 | 
			
		||||
  cpi->gld_fb_idx = 1;
 | 
			
		||||
  cpi->alt_fb_idx = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
 | 
			
		||||
@@ -528,8 +506,6 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
 | 
			
		||||
 | 
			
		||||
  cm->width = oxcf->width;
 | 
			
		||||
  cm->height = oxcf->height;
 | 
			
		||||
  cm->subsampling_x = 0;
 | 
			
		||||
  cm->subsampling_y = 0;
 | 
			
		||||
  vp9_alloc_compressor_data(cpi);
 | 
			
		||||
 | 
			
		||||
  // Spatial scalability.
 | 
			
		||||
@@ -548,10 +524,9 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
 | 
			
		||||
  vp9_change_config(cpi, oxcf);
 | 
			
		||||
 | 
			
		||||
  cpi->static_mb_pct = 0;
 | 
			
		||||
  cpi->ref_frame_flags = 0;
 | 
			
		||||
 | 
			
		||||
  cpi->lst_fb_idx = 0;
 | 
			
		||||
  cpi->gld_fb_idx = 1;
 | 
			
		||||
  cpi->alt_fb_idx = 2;
 | 
			
		||||
  init_buffer_indices(cpi);
 | 
			
		||||
 | 
			
		||||
  set_tile_limits(cpi);
 | 
			
		||||
}
 | 
			
		||||
@@ -590,7 +565,6 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
 | 
			
		||||
  cpi->pass = get_pass(cpi->oxcf.mode);
 | 
			
		||||
 | 
			
		||||
  rc->baseline_gf_interval = DEFAULT_GF_INTERVAL;
 | 
			
		||||
  cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
 | 
			
		||||
 | 
			
		||||
  cpi->refresh_golden_frame = 0;
 | 
			
		||||
  cpi->refresh_last_frame = 1;
 | 
			
		||||
@@ -598,7 +572,7 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
 | 
			
		||||
  cm->reset_frame_context = 0;
 | 
			
		||||
 | 
			
		||||
  vp9_reset_segment_features(&cm->seg);
 | 
			
		||||
  set_high_precision_mv(cpi, 0);
 | 
			
		||||
  vp9_set_high_precision_mv(cpi, 0);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    int i;
 | 
			
		||||
@@ -663,11 +637,7 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
 | 
			
		||||
                                           (int)cpi->oxcf.target_bandwidth);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  vp9_zero(cpi->alt_ref_source);
 | 
			
		||||
#else
 | 
			
		||||
  cpi->alt_ref_source = NULL;
 | 
			
		||||
#endif
 | 
			
		||||
  rc->is_src_frame_alt_ref = 0;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
@@ -683,6 +653,12 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
 | 
			
		||||
 | 
			
		||||
#if CONFIG_DENOISING
 | 
			
		||||
  vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
 | 
			
		||||
                     // TODO(tkopp) An unrelated bug causes
 | 
			
		||||
                     // cm->subsampling_{x,y} to be uninitialized at this point
 | 
			
		||||
                     // in execution. For now we assume YUV-420, which is x/y
 | 
			
		||||
                     // subsampling of 1.
 | 
			
		||||
                     1, 1,
 | 
			
		||||
                     // cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                     VP9_ENC_BORDER_IN_PIXELS);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@@ -781,10 +757,6 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
 | 
			
		||||
  CHECK_MEM_ERROR(cm, cpi->coding_context.last_frame_seg_map_copy,
 | 
			
		||||
                  vpx_calloc(cm->mi_rows * cm->mi_cols, 1));
 | 
			
		||||
 | 
			
		||||
  CHECK_MEM_ERROR(cm, cpi->active_map, vpx_calloc(cm->MBs, 1));
 | 
			
		||||
  vpx_memset(cpi->active_map, 1, cm->MBs);
 | 
			
		||||
  cpi->active_map_enabled = 0;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < (sizeof(cpi->mbgraph_stats) /
 | 
			
		||||
                   sizeof(cpi->mbgraph_stats[0])); i++) {
 | 
			
		||||
    CHECK_MEM_ERROR(cm, cpi->mbgraph_stats[i].mb_stats,
 | 
			
		||||
@@ -794,18 +766,23 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
 | 
			
		||||
 | 
			
		||||
  cpi->refresh_alt_ref_frame = 0;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  // Turn multiple ARF usage on/off. This is a quick hack for the initial test
 | 
			
		||||
  // version. It should eventually be set via the codec API.
 | 
			
		||||
  cpi->multi_arf_enabled = 1;
 | 
			
		||||
 | 
			
		||||
  if (cpi->multi_arf_enabled) {
 | 
			
		||||
    cpi->sequence_number = 0;
 | 
			
		||||
    cpi->frame_coding_order_period = 0;
 | 
			
		||||
    vp9_zero(cpi->frame_coding_order);
 | 
			
		||||
    vp9_zero(cpi->arf_buffer_idx);
 | 
			
		||||
  // Note that at the moment multi_arf will not work with svc.
 | 
			
		||||
  // For the current check in all the execution paths are defaulted to 0
 | 
			
		||||
  // pending further tuning and testing. The code is left in place here
 | 
			
		||||
  // as a place holder in regard to the required paths.
 | 
			
		||||
  if (cpi->pass == 2) {
 | 
			
		||||
    if (cpi->use_svc) {
 | 
			
		||||
      cpi->multi_arf_allowed = 0;
 | 
			
		||||
      cpi->multi_arf_enabled = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
      // Disable by default for now.
 | 
			
		||||
      cpi->multi_arf_allowed = 0;
 | 
			
		||||
      cpi->multi_arf_enabled = 0;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    cpi->multi_arf_allowed = 0;
 | 
			
		||||
    cpi->multi_arf_enabled = 0;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
 | 
			
		||||
#if CONFIG_INTERNAL_STATS
 | 
			
		||||
@@ -860,6 +837,9 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
 | 
			
		||||
  cpi->mb.nmvsadcost_hp[1] = &cpi->mb.nmvsadcosts_hp[1][MV_MAX];
 | 
			
		||||
  cal_nmvsadcosts_hp(cpi->mb.nmvsadcost_hp);
 | 
			
		||||
 | 
			
		||||
#ifdef OUTPUT_YUV_DENOISED
 | 
			
		||||
  yuv_denoised_file = fopen("denoised.yuv", "ab");
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef OUTPUT_YUV_SRC
 | 
			
		||||
  yuv_file = fopen("bd.yuv", "ab");
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1005,6 +985,41 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
 | 
			
		||||
      vp9_sub_pixel_avg_variance4x4,
 | 
			
		||||
      vp9_sad4x4x3, vp9_sad4x4x8, vp9_sad4x4x4d)
 | 
			
		||||
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
    CONFIG_MASKED_INTERINTER)
 | 
			
		||||
#define MBFP(BT, MSDF, MVF, MSVF) \
 | 
			
		||||
  cpi->fn_ptr[BT].msdf            = MSDF; \
 | 
			
		||||
  cpi->fn_ptr[BT].mvf             = MVF; \
 | 
			
		||||
  cpi->fn_ptr[BT].msvf            = MSVF;
 | 
			
		||||
 | 
			
		||||
  MBFP(BLOCK_64X64, vp9_masked_sad64x64, vp9_masked_variance64x64,
 | 
			
		||||
       vp9_masked_sub_pixel_variance64x64)
 | 
			
		||||
  MBFP(BLOCK_64X32, vp9_masked_sad64x32, vp9_masked_variance64x32,
 | 
			
		||||
         vp9_masked_sub_pixel_variance64x32)
 | 
			
		||||
  MBFP(BLOCK_32X64, vp9_masked_sad32x64, vp9_masked_variance32x64,
 | 
			
		||||
         vp9_masked_sub_pixel_variance32x64)
 | 
			
		||||
  MBFP(BLOCK_32X32, vp9_masked_sad32x32, vp9_masked_variance32x32,
 | 
			
		||||
       vp9_masked_sub_pixel_variance32x32)
 | 
			
		||||
  MBFP(BLOCK_32X16, vp9_masked_sad32x16, vp9_masked_variance32x16,
 | 
			
		||||
       vp9_masked_sub_pixel_variance32x16)
 | 
			
		||||
  MBFP(BLOCK_16X32, vp9_masked_sad16x32, vp9_masked_variance16x32,
 | 
			
		||||
       vp9_masked_sub_pixel_variance16x32)
 | 
			
		||||
  MBFP(BLOCK_16X16, vp9_masked_sad16x16, vp9_masked_variance16x16,
 | 
			
		||||
         vp9_masked_sub_pixel_variance16x16)
 | 
			
		||||
  MBFP(BLOCK_16X8, vp9_masked_sad16x8, vp9_masked_variance16x8,
 | 
			
		||||
         vp9_masked_sub_pixel_variance16x8)
 | 
			
		||||
  MBFP(BLOCK_8X16, vp9_masked_sad8x16, vp9_masked_variance8x16,
 | 
			
		||||
         vp9_masked_sub_pixel_variance8x16)
 | 
			
		||||
  MBFP(BLOCK_8X8, vp9_masked_sad8x8, vp9_masked_variance8x8,
 | 
			
		||||
       vp9_masked_sub_pixel_variance8x8)
 | 
			
		||||
  MBFP(BLOCK_4X8, vp9_masked_sad4x8, vp9_masked_variance4x8,
 | 
			
		||||
       vp9_masked_sub_pixel_variance4x8)
 | 
			
		||||
  MBFP(BLOCK_8X4, vp9_masked_sad8x4, vp9_masked_variance8x4,
 | 
			
		||||
       vp9_masked_sub_pixel_variance8x4)
 | 
			
		||||
  MBFP(BLOCK_4X4, vp9_masked_sad4x4, vp9_masked_variance4x4,
 | 
			
		||||
       vp9_masked_sub_pixel_variance4x4)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  cpi->full_search_sad = vp9_full_search_sad;
 | 
			
		||||
  cpi->diamond_search_sad = vp9_diamond_search_sad;
 | 
			
		||||
  cpi->refining_search_sad = vp9_refining_search_sad;
 | 
			
		||||
@@ -1105,6 +1120,9 @@ void vp9_remove_compressor(VP9_COMP *cpi) {
 | 
			
		||||
  vp9_remove_common(&cpi->common);
 | 
			
		||||
  vpx_free(cpi);
 | 
			
		||||
 | 
			
		||||
#ifdef OUTPUT_YUV_DENOISED
 | 
			
		||||
  fclose(yuv_denoised_file);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef OUTPUT_YUV_SRC
 | 
			
		||||
  fclose(yuv_file);
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1286,13 +1304,13 @@ int vp9_update_entropy(VP9_COMP * cpi, int update) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef OUTPUT_YUV_SRC
 | 
			
		||||
void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s) {
 | 
			
		||||
#if defined(OUTPUT_YUV_SRC) || defined(OUTPUT_YUV_DENOISED)
 | 
			
		||||
void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s, FILE *f) {
 | 
			
		||||
  uint8_t *src = s->y_buffer;
 | 
			
		||||
  int h = s->y_height;
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    fwrite(src, s->y_width, 1,  yuv_file);
 | 
			
		||||
    fwrite(src, s->y_width, 1, f);
 | 
			
		||||
    src += s->y_stride;
 | 
			
		||||
  } while (--h);
 | 
			
		||||
 | 
			
		||||
@@ -1300,7 +1318,7 @@ void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s) {
 | 
			
		||||
  h = s->uv_height;
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    fwrite(src, s->uv_width, 1,  yuv_file);
 | 
			
		||||
    fwrite(src, s->uv_width, 1, f);
 | 
			
		||||
    src += s->uv_stride;
 | 
			
		||||
  } while (--h);
 | 
			
		||||
 | 
			
		||||
@@ -1308,7 +1326,7 @@ void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s) {
 | 
			
		||||
  h = s->uv_height;
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    fwrite(src, s->uv_width, 1, yuv_file);
 | 
			
		||||
    fwrite(src, s->uv_width, 1, f);
 | 
			
		||||
    src += s->uv_stride;
 | 
			
		||||
  } while (--h);
 | 
			
		||||
}
 | 
			
		||||
@@ -1509,14 +1527,8 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
 | 
			
		||||
               &cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
 | 
			
		||||
    ref_cnt_fb(cm->frame_bufs,
 | 
			
		||||
               &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  else if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
 | 
			
		||||
      !cpi->refresh_alt_ref_frame) {
 | 
			
		||||
#else
 | 
			
		||||
  else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame &&
 | 
			
		||||
           !cpi->use_svc) {
 | 
			
		||||
#endif
 | 
			
		||||
  } else if (!cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
 | 
			
		||||
             cpi->rc.is_src_frame_alt_ref && !cpi->use_svc) {
 | 
			
		||||
    /* Preserve the previously existing golden frame and update the frame in
 | 
			
		||||
     * the alt ref slot instead. This is highly specific to the current use of
 | 
			
		||||
     * alt-ref as a forward reference, and this needs to be generalized as
 | 
			
		||||
@@ -1534,14 +1546,14 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
 | 
			
		||||
    tmp = cpi->alt_fb_idx;
 | 
			
		||||
    cpi->alt_fb_idx = cpi->gld_fb_idx;
 | 
			
		||||
    cpi->gld_fb_idx = tmp;
 | 
			
		||||
  }  else { /* For non key/golden frames */
 | 
			
		||||
  } else { /* For non key/golden frames */
 | 
			
		||||
    if (cpi->refresh_alt_ref_frame) {
 | 
			
		||||
      int arf_idx = cpi->alt_fb_idx;
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
      if (cpi->multi_arf_enabled) {
 | 
			
		||||
        arf_idx = cpi->arf_buffer_idx[cpi->sequence_number + 1];
 | 
			
		||||
      if ((cpi->pass == 2) && cpi->multi_arf_allowed) {
 | 
			
		||||
        const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
 | 
			
		||||
        arf_idx = gf_group->arf_update_idx[gf_group->index];
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      ref_cnt_fb(cm->frame_bufs,
 | 
			
		||||
                 &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1558,6 +1570,7 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_DENOISING
 | 
			
		||||
  vp9_denoiser_update_frame_info(&cpi->denoiser,
 | 
			
		||||
                                *cpi->Source,
 | 
			
		||||
                                cpi->common.frame_type,
 | 
			
		||||
                                cpi->refresh_alt_ref_frame,
 | 
			
		||||
                                cpi->refresh_golden_frame,
 | 
			
		||||
@@ -1593,13 +1606,15 @@ static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) {
 | 
			
		||||
void vp9_scale_references(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *cm = &cpi->common;
 | 
			
		||||
  MV_REFERENCE_FRAME ref_frame;
 | 
			
		||||
  const VP9_REFFRAME ref_mask[3] = {VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG};
 | 
			
		||||
 | 
			
		||||
  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
 | 
			
		||||
    const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
 | 
			
		||||
    const YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf;
 | 
			
		||||
 | 
			
		||||
    if (ref->y_crop_width != cm->width ||
 | 
			
		||||
        ref->y_crop_height != cm->height) {
 | 
			
		||||
    // Need to convert from VP9_REFFRAME to index into ref_mask (subtract 1).
 | 
			
		||||
    if ((cpi->ref_frame_flags & ref_mask[ref_frame - 1]) &&
 | 
			
		||||
        (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height)) {
 | 
			
		||||
      const int new_fb = get_free_fb(cm);
 | 
			
		||||
      vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
 | 
			
		||||
                               cm->width, cm->height,
 | 
			
		||||
@@ -1987,6 +2002,45 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
static void select_masked_interinter_mode(VP9_COMP *cpi) {
 | 
			
		||||
  static const double threshold = 1/128.0;
 | 
			
		||||
  VP9_COMMON *cm = &cpi->common;
 | 
			
		||||
  int sum = cpi->masked_interinter_select_counts[1] +
 | 
			
		||||
      cpi->masked_interinter_select_counts[0];
 | 
			
		||||
  if (sum) {
 | 
			
		||||
    double fraction = (double) cpi->masked_interinter_select_counts[1] / sum;
 | 
			
		||||
    cm->use_masked_interinter = (fraction > threshold);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
static void select_interintra_mode(VP9_COMP *cpi) {
 | 
			
		||||
  static const double threshold = 0.007;
 | 
			
		||||
  VP9_COMMON *cm = &cpi->common;
 | 
			
		||||
  int sum = cpi->interintra_select_count[1] + cpi->interintra_select_count[0];
 | 
			
		||||
  if (sum) {
 | 
			
		||||
    double fraction = (double)cpi->interintra_select_count[1] / (double)sum;
 | 
			
		||||
    cm->use_interintra = (fraction > threshold);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
static void select_masked_interintra_mode(VP9_COMP *cpi) {
 | 
			
		||||
  static const double threshold = 1/100.0;
 | 
			
		||||
  VP9_COMMON *cm = &cpi->common;
 | 
			
		||||
  int sum = cpi->masked_interintra_select_count[1] +
 | 
			
		||||
      cpi->masked_interintra_select_count[0];
 | 
			
		||||
  if (sum) {
 | 
			
		||||
    double fraction = (double)cpi->masked_interintra_select_count[1] /
 | 
			
		||||
                      (double)sum;
 | 
			
		||||
    cm->use_masked_interintra = (fraction > threshold);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void encode_frame_to_data_rate(VP9_COMP *cpi,
 | 
			
		||||
                                      size_t *size,
 | 
			
		||||
                                      uint8_t *dest,
 | 
			
		||||
@@ -2121,8 +2175,12 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef OUTPUT_YUV_DENOISED
 | 
			
		||||
  vp9_write_yuv_frame(&cpi->denoiser.running_avg_y[INTRA_FRAME],
 | 
			
		||||
                      yuv_denoised_file);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef OUTPUT_YUV_SRC
 | 
			
		||||
  vp9_write_yuv_frame(cpi->Source);
 | 
			
		||||
  vp9_write_yuv_frame(cpi->Source, yuv_file);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  set_speed_features(cpi);
 | 
			
		||||
@@ -2133,9 +2191,23 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 | 
			
		||||
  if (!frame_is_intra_only(cm)) {
 | 
			
		||||
    cm->interp_filter = DEFAULT_INTERP_FILTER;
 | 
			
		||||
    /* TODO: Decide this more intelligently */
 | 
			
		||||
    set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
 | 
			
		||||
    vp9_set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  if (cm->current_video_frame == 0)
 | 
			
		||||
    cm->use_masked_interinter = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  if (cm->current_video_frame == 0) {
 | 
			
		||||
    cm->use_interintra = 1;
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
    cm->use_masked_interintra = 1;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (cpi->sf.recode_loop == DISALLOW_RECODE) {
 | 
			
		||||
    encode_without_recode_loop(cpi, q);
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -2197,6 +2269,18 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 | 
			
		||||
      vp9_adapt_mode_probs(cm);
 | 
			
		||||
      vp9_adapt_mv_probs(cm, cm->allow_high_precision_mv);
 | 
			
		||||
    }
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
    select_masked_interinter_mode(cpi);
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
    select_interintra_mode(cpi);
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
    if (cpi->common.use_interintra)
 | 
			
		||||
      select_masked_interintra_mode(cpi);
 | 
			
		||||
    else
 | 
			
		||||
      cpi->common.use_masked_interintra = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (cpi->refresh_golden_frame == 1)
 | 
			
		||||
@@ -2221,31 +2305,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 | 
			
		||||
  if (cm->frame_type == KEY_FRAME) {
 | 
			
		||||
    // Tell the caller that the frame was coded as a key frame
 | 
			
		||||
    *frame_flags = cpi->frame_flags | FRAMEFLAGS_KEY;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    // Reset the sequence number.
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      cpi->sequence_number = 0;
 | 
			
		||||
      cpi->frame_coding_order_period = cpi->new_frame_coding_order_period;
 | 
			
		||||
      cpi->new_frame_coding_order_period = -1;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  } else {
 | 
			
		||||
    *frame_flags = cpi->frame_flags & ~FRAMEFLAGS_KEY;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    /* Increment position in the coded frame sequence. */
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      ++cpi->sequence_number;
 | 
			
		||||
      if (cpi->sequence_number >= cpi->frame_coding_order_period) {
 | 
			
		||||
        cpi->sequence_number = 0;
 | 
			
		||||
        cpi->frame_coding_order_period = cpi->new_frame_coding_order_period;
 | 
			
		||||
        cpi->new_frame_coding_order_period = -1;
 | 
			
		||||
      }
 | 
			
		||||
      cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number];
 | 
			
		||||
      assert(cpi->this_frame_weight >= 0);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Clear the one shot update flags for segmentation map and mode/ref loop
 | 
			
		||||
@@ -2299,6 +2360,16 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size,
 | 
			
		||||
  vp9_twopass_postencode_update(cpi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_motion_estimation(VP9_COMP *cpi) {
 | 
			
		||||
  int y_stride = cpi->scaled_source.y_stride;
 | 
			
		||||
 | 
			
		||||
  if (cpi->sf.mv.search_method == NSTEP) {
 | 
			
		||||
    vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride);
 | 
			
		||||
  } else if (cpi->sf.mv.search_method == DIAMOND) {
 | 
			
		||||
    vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_initial_width(VP9_COMP *cpi, int subsampling_x,
 | 
			
		||||
                                int subsampling_y) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
@@ -2306,7 +2377,13 @@ static void check_initial_width(VP9_COMP *cpi, int subsampling_x,
 | 
			
		||||
  if (!cpi->initial_width) {
 | 
			
		||||
    cm->subsampling_x = subsampling_x;
 | 
			
		||||
    cm->subsampling_y = subsampling_y;
 | 
			
		||||
 | 
			
		||||
    alloc_raw_frame_buffers(cpi);
 | 
			
		||||
    alloc_ref_frame_buffers(cpi);
 | 
			
		||||
    alloc_util_frame_buffers(cpi);
 | 
			
		||||
 | 
			
		||||
    init_motion_estimation(cpi);
 | 
			
		||||
 | 
			
		||||
    cpi->initial_width = cm->width;
 | 
			
		||||
    cpi->initial_height = cm->height;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2321,11 +2398,22 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, unsigned int frame_flags,
 | 
			
		||||
  int res = 0;
 | 
			
		||||
  const int subsampling_x = sd->uv_width  < sd->y_width;
 | 
			
		||||
  const int subsampling_y = sd->uv_height < sd->y_height;
 | 
			
		||||
  const int is_spatial_svc = cpi->use_svc &&
 | 
			
		||||
                             (cpi->svc.number_temporal_layers == 1);
 | 
			
		||||
 | 
			
		||||
  check_initial_width(cpi, subsampling_x, subsampling_y);
 | 
			
		||||
 | 
			
		||||
  vpx_usec_timer_start(&timer);
 | 
			
		||||
  if (vp9_lookahead_push(cpi->lookahead,
 | 
			
		||||
                         sd, time_stamp, end_time, frame_flags))
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
  if (is_spatial_svc)
 | 
			
		||||
    res = vp9_svc_lookahead_push(cpi, cpi->lookahead, sd, time_stamp, end_time,
 | 
			
		||||
                                 frame_flags);
 | 
			
		||||
  else
 | 
			
		||||
#endif
 | 
			
		||||
    res = vp9_lookahead_push(cpi->lookahead,
 | 
			
		||||
                             sd, time_stamp, end_time, frame_flags);
 | 
			
		||||
  if (res)
 | 
			
		||||
    res = -1;
 | 
			
		||||
  vpx_usec_timer_mark(&timer);
 | 
			
		||||
  cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
 | 
			
		||||
@@ -2353,13 +2441,6 @@ static int frame_is_reference(const VP9_COMP *cpi) {
 | 
			
		||||
         cm->seg.update_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
int is_next_frame_arf(VP9_COMP *cpi) {
 | 
			
		||||
  // Negative entry in frame_coding_order indicates an ARF at this position.
 | 
			
		||||
  return cpi->frame_coding_order[cpi->sequence_number + 1] < 0 ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void adjust_frame_rate(VP9_COMP *cpi) {
 | 
			
		||||
  int64_t this_duration;
 | 
			
		||||
  int step = 0;
 | 
			
		||||
@@ -2398,6 +2479,46 @@ void adjust_frame_rate(VP9_COMP *cpi) {
 | 
			
		||||
  cpi->last_end_time_stamp_seen = cpi->source->ts_end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns 0 if this is not an alt ref else the offset of the source frame
 | 
			
		||||
// used as the arf midpoint.
 | 
			
		||||
static int get_arf_src_index(VP9_COMP *cpi) {
 | 
			
		||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
  int arf_src_index = 0;
 | 
			
		||||
  if (is_altref_enabled(&cpi->oxcf)) {
 | 
			
		||||
    if (cpi->pass == 2) {
 | 
			
		||||
      const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
 | 
			
		||||
      if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
 | 
			
		||||
        arf_src_index = gf_group->arf_src_offset[gf_group->index];
 | 
			
		||||
      }
 | 
			
		||||
    } else if (rc->source_alt_ref_pending) {
 | 
			
		||||
      arf_src_index = rc->frames_till_gf_update_due;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return arf_src_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_src_altref(VP9_COMP *cpi) {
 | 
			
		||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
 | 
			
		||||
  if (cpi->pass == 2) {
 | 
			
		||||
    const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
 | 
			
		||||
    rc->is_src_frame_alt_ref =
 | 
			
		||||
      (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
 | 
			
		||||
  } else {
 | 
			
		||||
    rc->is_src_frame_alt_ref = cpi->alt_ref_source &&
 | 
			
		||||
                               (cpi->source == cpi->alt_ref_source);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (rc->is_src_frame_alt_ref) {
 | 
			
		||||
    // Current frame is an ARF overlay frame.
 | 
			
		||||
    cpi->alt_ref_source = NULL;
 | 
			
		||||
 | 
			
		||||
    // Don't refresh the last buffer for an ARF overlay frame. It will
 | 
			
		||||
    // become the GF so preserve last as an alternative prediction option.
 | 
			
		||||
    cpi->refresh_last_frame = 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
                            size_t *size, uint8_t *dest,
 | 
			
		||||
                            int64_t *time_stamp, int64_t *time_end, int flush) {
 | 
			
		||||
@@ -2407,11 +2528,15 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
  struct vpx_usec_timer  cmptimer;
 | 
			
		||||
  YV12_BUFFER_CONFIG *force_src_buffer = NULL;
 | 
			
		||||
  MV_REFERENCE_FRAME ref_frame;
 | 
			
		||||
  int arf_src_index;
 | 
			
		||||
  const int is_spatial_svc = cpi->use_svc &&
 | 
			
		||||
                             (cpi->svc.number_temporal_layers == 1);
 | 
			
		||||
 | 
			
		||||
  if (!cpi)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  if (cpi->svc.number_spatial_layers > 1 && cpi->pass == 2) {
 | 
			
		||||
  if (is_spatial_svc && cpi->pass == 2) {
 | 
			
		||||
    vp9_svc_lookahead_peek(cpi, cpi->lookahead, 0, 1);
 | 
			
		||||
    vp9_restore_layer_context(cpi);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -2420,7 +2545,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
  cpi->source = NULL;
 | 
			
		||||
  cpi->last_source = NULL;
 | 
			
		||||
 | 
			
		||||
  set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
 | 
			
		||||
  vp9_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
 | 
			
		||||
 | 
			
		||||
  // Normal defaults
 | 
			
		||||
  cm->reset_frame_context = 0;
 | 
			
		||||
@@ -2429,35 +2554,26 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
  cpi->refresh_golden_frame = 0;
 | 
			
		||||
  cpi->refresh_alt_ref_frame = 0;
 | 
			
		||||
 | 
			
		||||
  // Should we code an alternate reference frame.
 | 
			
		||||
  if (is_altref_enabled(&cpi->oxcf) && rc->source_alt_ref_pending) {
 | 
			
		||||
    int frames_to_arf;
 | 
			
		||||
  // Should we encode an arf frame.
 | 
			
		||||
  arf_src_index = get_arf_src_index(cpi);
 | 
			
		||||
  if (arf_src_index) {
 | 
			
		||||
    assert(arf_src_index <= rc->frames_to_key);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    assert(!cpi->multi_arf_enabled ||
 | 
			
		||||
           cpi->frame_coding_order[cpi->sequence_number] < 0);
 | 
			
		||||
 | 
			
		||||
    if (cpi->multi_arf_enabled && (cpi->pass == 2))
 | 
			
		||||
      frames_to_arf = (-cpi->frame_coding_order[cpi->sequence_number])
 | 
			
		||||
          - cpi->next_frame_in_order;
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
    if (is_spatial_svc)
 | 
			
		||||
      cpi->source = vp9_svc_lookahead_peek(cpi, cpi->lookahead,
 | 
			
		||||
                                           arf_src_index, 1);
 | 
			
		||||
    else
 | 
			
		||||
#endif
 | 
			
		||||
      frames_to_arf = rc->frames_till_gf_update_due;
 | 
			
		||||
 | 
			
		||||
    assert(frames_to_arf <= rc->frames_to_key);
 | 
			
		||||
 | 
			
		||||
    if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, frames_to_arf))) {
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
      cpi->alt_ref_source[cpi->arf_buffered] = cpi->source;
 | 
			
		||||
#else
 | 
			
		||||
      cpi->source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
 | 
			
		||||
    if (cpi->source != NULL) {
 | 
			
		||||
      cpi->alt_ref_source = cpi->source;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      if (cpi->oxcf.arnr_max_frames > 0) {
 | 
			
		||||
        // Produce the filtered ARF frame.
 | 
			
		||||
        // TODO(agrange) merge these two functions.
 | 
			
		||||
        vp9_configure_arnr_filter(cpi, frames_to_arf, rc->gfu_boost);
 | 
			
		||||
        vp9_temporal_filter_prepare(cpi, frames_to_arf);
 | 
			
		||||
        vp9_configure_arnr_filter(cpi, arf_src_index, rc->gfu_boost);
 | 
			
		||||
        vp9_temporal_filter_prepare(cpi, arf_src_index);
 | 
			
		||||
        vp9_extend_frame_borders(&cpi->alt_ref_buffer);
 | 
			
		||||
        force_src_buffer = &cpi->alt_ref_buffer;
 | 
			
		||||
      }
 | 
			
		||||
@@ -2467,59 +2583,38 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
      cpi->refresh_golden_frame = 0;
 | 
			
		||||
      cpi->refresh_last_frame = 0;
 | 
			
		||||
      rc->is_src_frame_alt_ref = 0;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
      if (!cpi->multi_arf_enabled)
 | 
			
		||||
#endif
 | 
			
		||||
        rc->source_alt_ref_pending = 0;
 | 
			
		||||
      rc->source_alt_ref_pending = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
      rc->source_alt_ref_pending = 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!cpi->source) {
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    int i;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // Get last frame source.
 | 
			
		||||
    if (cm->current_video_frame > 0) {
 | 
			
		||||
      if ((cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1)) == NULL)
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
      if (is_spatial_svc)
 | 
			
		||||
        cpi->last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
 | 
			
		||||
      else
 | 
			
		||||
#endif
 | 
			
		||||
        cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1);
 | 
			
		||||
      if (cpi->last_source == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) {
 | 
			
		||||
    // Read in the source frame.
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
    if (is_spatial_svc)
 | 
			
		||||
      cpi->source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
 | 
			
		||||
    else
 | 
			
		||||
#endif
 | 
			
		||||
      cpi->source = vp9_lookahead_pop(cpi->lookahead, flush);
 | 
			
		||||
    if (cpi->source != NULL) {
 | 
			
		||||
      cm->show_frame = 1;
 | 
			
		||||
      cm->intra_only = 0;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
      // Is this frame the ARF overlay.
 | 
			
		||||
      rc->is_src_frame_alt_ref = 0;
 | 
			
		||||
      for (i = 0; i < cpi->arf_buffered; ++i) {
 | 
			
		||||
        if (cpi->source == cpi->alt_ref_source[i]) {
 | 
			
		||||
          rc->is_src_frame_alt_ref = 1;
 | 
			
		||||
          cpi->refresh_golden_frame = 1;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
#else
 | 
			
		||||
      rc->is_src_frame_alt_ref = cpi->alt_ref_source &&
 | 
			
		||||
                                 (cpi->source == cpi->alt_ref_source);
 | 
			
		||||
#endif
 | 
			
		||||
      if (rc->is_src_frame_alt_ref) {
 | 
			
		||||
        // Current frame is an ARF overlay frame.
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
        cpi->alt_ref_source[i] = NULL;
 | 
			
		||||
#else
 | 
			
		||||
        cpi->alt_ref_source = NULL;
 | 
			
		||||
#endif
 | 
			
		||||
        // Don't refresh the last buffer for an ARF overlay frame. It will
 | 
			
		||||
        // become the GF so preserve last as an alternative prediction option.
 | 
			
		||||
        cpi->refresh_last_frame = 0;
 | 
			
		||||
      }
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
      ++cpi->next_frame_in_order;
 | 
			
		||||
#endif
 | 
			
		||||
      // Check to see if the frame should be encoded as an arf overlay.
 | 
			
		||||
      check_src_altref(cpi);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -2527,20 +2622,17 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
    cpi->un_scaled_source = cpi->Source = force_src_buffer ? force_src_buffer
 | 
			
		||||
                                                           : &cpi->source->img;
 | 
			
		||||
 | 
			
		||||
  if (cpi->last_source != NULL) {
 | 
			
		||||
    cpi->unscaled_last_source = &cpi->last_source->img;
 | 
			
		||||
  } else {
 | 
			
		||||
    cpi->unscaled_last_source = NULL;
 | 
			
		||||
  }
 | 
			
		||||
    if (cpi->last_source != NULL) {
 | 
			
		||||
      cpi->unscaled_last_source = &cpi->last_source->img;
 | 
			
		||||
    } else {
 | 
			
		||||
      cpi->unscaled_last_source = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *time_stamp = cpi->source->ts_start;
 | 
			
		||||
    *time_end = cpi->source->ts_end;
 | 
			
		||||
    *frame_flags = cpi->source->flags;
 | 
			
		||||
    *frame_flags =
 | 
			
		||||
        (cpi->source->flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    if (cm->frame_type != KEY_FRAME && cpi->pass == 2)
 | 
			
		||||
      rc->source_alt_ref_pending = is_next_frame_arf(cpi);
 | 
			
		||||
#endif
 | 
			
		||||
  } else {
 | 
			
		||||
    *size = 0;
 | 
			
		||||
    if (flush && cpi->pass == 1 && !cpi->twopass.first_pass_done) {
 | 
			
		||||
@@ -2578,16 +2670,14 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
  cm->frame_bufs[cm->new_fb_idx].ref_count--;
 | 
			
		||||
  cm->new_fb_idx = get_free_fb(cm);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  /* Set up the correct ARF frame. */
 | 
			
		||||
  if (cpi->refresh_alt_ref_frame) {
 | 
			
		||||
    ++cpi->arf_buffered;
 | 
			
		||||
  if (!cpi->use_svc && cpi->multi_arf_allowed) {
 | 
			
		||||
    if (cm->frame_type == KEY_FRAME) {
 | 
			
		||||
      init_buffer_indices(cpi);
 | 
			
		||||
    } else if (cpi->pass == 2) {
 | 
			
		||||
      const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
 | 
			
		||||
      cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
 | 
			
		||||
      (cpi->pass == 2)) {
 | 
			
		||||
    cpi->alt_fb_idx = cpi->arf_buffer_idx[cpi->sequence_number];
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  cpi->frame_flags = *frame_flags;
 | 
			
		||||
 | 
			
		||||
@@ -2606,6 +2696,9 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
			
		||||
                           cm->subsampling_x, cm->subsampling_y,
 | 
			
		||||
                           VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  alloc_util_frame_buffers(cpi);
 | 
			
		||||
  init_motion_estimation(cpi);
 | 
			
		||||
 | 
			
		||||
  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
 | 
			
		||||
    const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
 | 
			
		||||
    YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf;
 | 
			
		||||
@@ -2775,16 +2868,23 @@ int vp9_get_preview_raw_frame(VP9_COMP *cpi, YV12_BUFFER_CONFIG *dest,
 | 
			
		||||
 | 
			
		||||
int vp9_set_active_map(VP9_COMP *cpi, unsigned char *map, int rows, int cols) {
 | 
			
		||||
  if (rows == cpi->common.mb_rows && cols == cpi->common.mb_cols) {
 | 
			
		||||
    const int mi_rows = cpi->common.mi_rows;
 | 
			
		||||
    const int mi_cols = cpi->common.mi_cols;
 | 
			
		||||
    if (map) {
 | 
			
		||||
      vpx_memcpy(cpi->active_map, map, rows * cols);
 | 
			
		||||
      cpi->active_map_enabled = 1;
 | 
			
		||||
      int r, c;
 | 
			
		||||
      for (r = 0; r < mi_rows; r++) {
 | 
			
		||||
        for (c = 0; c < mi_cols; c++) {
 | 
			
		||||
          cpi->segmentation_map[r * mi_cols + c] =
 | 
			
		||||
              !map[(r >> 1) * cols + (c >> 1)];
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      vp9_enable_segfeature(&cpi->common.seg, 1, SEG_LVL_SKIP);
 | 
			
		||||
      vp9_enable_segmentation(&cpi->common.seg);
 | 
			
		||||
    } else {
 | 
			
		||||
      cpi->active_map_enabled = 0;
 | 
			
		||||
      vp9_disable_segmentation(&cpi->common.seg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
  } else {
 | 
			
		||||
    // cpi->active_map_enabled = 0;
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -2863,3 +2963,42 @@ int vp9_get_y_sse(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b) {
 | 
			
		||||
int vp9_get_quantizer(VP9_COMP *cpi) {
 | 
			
		||||
  return cpi->common.base_qindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags) {
 | 
			
		||||
  if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF |
 | 
			
		||||
               VP8_EFLAG_NO_REF_ARF)) {
 | 
			
		||||
    int ref = 7;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_REF_LAST)
 | 
			
		||||
      ref ^= VP9_LAST_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_REF_GF)
 | 
			
		||||
      ref ^= VP9_GOLD_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_REF_ARF)
 | 
			
		||||
      ref ^= VP9_ALT_FLAG;
 | 
			
		||||
 | 
			
		||||
    vp9_use_as_reference(cpi, ref);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
 | 
			
		||||
               VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF |
 | 
			
		||||
               VP8_EFLAG_FORCE_ARF)) {
 | 
			
		||||
    int upd = 7;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_UPD_LAST)
 | 
			
		||||
      upd ^= VP9_LAST_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_UPD_GF)
 | 
			
		||||
      upd ^= VP9_GOLD_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_UPD_ARF)
 | 
			
		||||
      upd ^= VP9_ALT_FLAG;
 | 
			
		||||
 | 
			
		||||
    vp9_update_reference(cpi, upd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
 | 
			
		||||
    vp9_update_entropy(cpi, 0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
#include "vp9/encoder/vp9_mcomp.h"
 | 
			
		||||
#include "vp9/encoder/vp9_quantize.h"
 | 
			
		||||
#include "vp9/encoder/vp9_ratectrl.h"
 | 
			
		||||
#include "vp9/encoder/vp9_rdopt.h"
 | 
			
		||||
#include "vp9/encoder/vp9_speed_features.h"
 | 
			
		||||
#include "vp9/encoder/vp9_svc_layercontext.h"
 | 
			
		||||
#include "vp9/encoder/vp9_tokenize.h"
 | 
			
		||||
@@ -46,9 +47,6 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_GF_INTERVAL         10
 | 
			
		||||
 | 
			
		||||
#define MAX_MODES 30
 | 
			
		||||
#define MAX_REFS  6
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  int nmvjointcost[MV_JOINTS];
 | 
			
		||||
  int nmvcosts[2][MV_VALS];
 | 
			
		||||
@@ -66,57 +64,6 @@ typedef struct {
 | 
			
		||||
  FRAME_CONTEXT fc;
 | 
			
		||||
} CODING_CONTEXT;
 | 
			
		||||
 | 
			
		||||
// This enumerator type needs to be kept aligned with the mode order in
 | 
			
		||||
// const MODE_DEFINITION vp9_mode_order[MAX_MODES] used in the rd code.
 | 
			
		||||
typedef enum {
 | 
			
		||||
  THR_NEARESTMV,
 | 
			
		||||
  THR_NEARESTA,
 | 
			
		||||
  THR_NEARESTG,
 | 
			
		||||
 | 
			
		||||
  THR_DC,
 | 
			
		||||
 | 
			
		||||
  THR_NEWMV,
 | 
			
		||||
  THR_NEWA,
 | 
			
		||||
  THR_NEWG,
 | 
			
		||||
 | 
			
		||||
  THR_NEARMV,
 | 
			
		||||
  THR_NEARA,
 | 
			
		||||
  THR_COMP_NEARESTLA,
 | 
			
		||||
  THR_COMP_NEARESTGA,
 | 
			
		||||
 | 
			
		||||
  THR_TM,
 | 
			
		||||
 | 
			
		||||
  THR_COMP_NEARLA,
 | 
			
		||||
  THR_COMP_NEWLA,
 | 
			
		||||
  THR_NEARG,
 | 
			
		||||
  THR_COMP_NEARGA,
 | 
			
		||||
  THR_COMP_NEWGA,
 | 
			
		||||
 | 
			
		||||
  THR_ZEROMV,
 | 
			
		||||
  THR_ZEROG,
 | 
			
		||||
  THR_ZEROA,
 | 
			
		||||
  THR_COMP_ZEROLA,
 | 
			
		||||
  THR_COMP_ZEROGA,
 | 
			
		||||
 | 
			
		||||
  THR_H_PRED,
 | 
			
		||||
  THR_V_PRED,
 | 
			
		||||
  THR_D135_PRED,
 | 
			
		||||
  THR_D207_PRED,
 | 
			
		||||
  THR_D153_PRED,
 | 
			
		||||
  THR_D63_PRED,
 | 
			
		||||
  THR_D117_PRED,
 | 
			
		||||
  THR_D45_PRED,
 | 
			
		||||
} THR_MODES;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  THR_LAST,
 | 
			
		||||
  THR_GOLD,
 | 
			
		||||
  THR_ALTR,
 | 
			
		||||
  THR_COMP_LA,
 | 
			
		||||
  THR_COMP_GA,
 | 
			
		||||
  THR_INTRA,
 | 
			
		||||
} THR_MODES_SUB8X8;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  // encode_breakout is disabled.
 | 
			
		||||
  ENCODE_BREAKOUT_DISABLED = 0,
 | 
			
		||||
@@ -293,32 +240,6 @@ static INLINE int is_best_mode(MODE mode) {
 | 
			
		||||
  return mode == ONE_PASS_BEST || mode == TWO_PASS_SECOND_BEST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct RD_OPT {
 | 
			
		||||
  // Thresh_mult is used to set a threshold for the rd score. A higher value
 | 
			
		||||
  // means that we will accept the best mode so far more often. This number
 | 
			
		||||
  // is used in combination with the current block size, and thresh_freq_fact
 | 
			
		||||
  // to pick a threshold.
 | 
			
		||||
  int thresh_mult[MAX_MODES];
 | 
			
		||||
  int thresh_mult_sub8x8[MAX_REFS];
 | 
			
		||||
 | 
			
		||||
  int threshes[MAX_SEGMENTS][BLOCK_SIZES][MAX_MODES];
 | 
			
		||||
  int thresh_freq_fact[BLOCK_SIZES][MAX_MODES];
 | 
			
		||||
 | 
			
		||||
  int64_t comp_pred_diff[REFERENCE_MODES];
 | 
			
		||||
  int64_t prediction_type_threshes[MAX_REF_FRAMES][REFERENCE_MODES];
 | 
			
		||||
  int64_t tx_select_diff[TX_MODES];
 | 
			
		||||
  // FIXME(rbultje) can this overflow?
 | 
			
		||||
  int tx_select_threshes[MAX_REF_FRAMES][TX_MODES];
 | 
			
		||||
 | 
			
		||||
  int64_t filter_diff[SWITCHABLE_FILTER_CONTEXTS];
 | 
			
		||||
  int64_t filter_threshes[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
 | 
			
		||||
  int64_t filter_cache[SWITCHABLE_FILTER_CONTEXTS];
 | 
			
		||||
  int64_t mask_filter;
 | 
			
		||||
 | 
			
		||||
  int RDMULT;
 | 
			
		||||
  int RDDIV;
 | 
			
		||||
} RD_OPT;
 | 
			
		||||
 | 
			
		||||
typedef struct VP9_COMP {
 | 
			
		||||
  QUANTS quants;
 | 
			
		||||
  MACROBLOCK mb;
 | 
			
		||||
@@ -326,11 +247,7 @@ typedef struct VP9_COMP {
 | 
			
		||||
  VP9EncoderConfig oxcf;
 | 
			
		||||
  struct lookahead_ctx    *lookahead;
 | 
			
		||||
  struct lookahead_entry  *source;
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  struct lookahead_entry  *alt_ref_source[REF_FRAMES];
 | 
			
		||||
#else
 | 
			
		||||
  struct lookahead_entry  *alt_ref_source;
 | 
			
		||||
#endif
 | 
			
		||||
  struct lookahead_entry  *last_source;
 | 
			
		||||
 | 
			
		||||
  YV12_BUFFER_CONFIG *Source;
 | 
			
		||||
@@ -349,9 +266,6 @@ typedef struct VP9_COMP {
 | 
			
		||||
  int gld_fb_idx;
 | 
			
		||||
  int alt_fb_idx;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  int alt_ref_fb_idx[REF_FRAMES - 3];
 | 
			
		||||
#endif
 | 
			
		||||
  int refresh_last_frame;
 | 
			
		||||
  int refresh_golden_frame;
 | 
			
		||||
  int refresh_alt_ref_frame;
 | 
			
		||||
@@ -369,13 +283,6 @@ typedef struct VP9_COMP {
 | 
			
		||||
  TOKENEXTRA *tok;
 | 
			
		||||
  unsigned int tok_count[4][1 << 6];
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  // Position within a frame coding order (including any additional ARF frames).
 | 
			
		||||
  unsigned int sequence_number;
 | 
			
		||||
  // Next frame in naturally occurring order that has not yet been coded.
 | 
			
		||||
  int next_frame_in_order;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // Ambient reconstruction err target for force key frames
 | 
			
		||||
  int ambient_err;
 | 
			
		||||
 | 
			
		||||
@@ -425,9 +332,6 @@ typedef struct VP9_COMP {
 | 
			
		||||
 | 
			
		||||
  unsigned char *complexity_map;
 | 
			
		||||
 | 
			
		||||
  unsigned char *active_map;
 | 
			
		||||
  unsigned int active_map_enabled;
 | 
			
		||||
 | 
			
		||||
  CYCLIC_REFRESH *cyclic_refresh;
 | 
			
		||||
 | 
			
		||||
  fractional_mv_step_fp *find_fractional_mv_step;
 | 
			
		||||
@@ -505,28 +409,32 @@ typedef struct VP9_COMP {
 | 
			
		||||
  int intra_uv_mode_cost[FRAME_TYPES][INTRA_MODES];
 | 
			
		||||
  int y_mode_costs[INTRA_MODES][INTRA_MODES][INTRA_MODES];
 | 
			
		||||
  int switchable_interp_costs[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
 | 
			
		||||
#if CONFIG_COPY_CODING
 | 
			
		||||
  int copy_mode_cost_l2[COPY_MODE_CONTEXTS][2];
 | 
			
		||||
  int copy_mode_cost[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 1];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  PICK_MODE_CONTEXT *leaf_tree;
 | 
			
		||||
  PC_TREE *pc_tree;
 | 
			
		||||
  PC_TREE *pc_root;
 | 
			
		||||
  int partition_cost[PARTITION_CONTEXTS][PARTITION_TYPES];
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  // ARF tracking variables.
 | 
			
		||||
  int multi_arf_allowed;
 | 
			
		||||
  int multi_arf_enabled;
 | 
			
		||||
  unsigned int frame_coding_order_period;
 | 
			
		||||
  unsigned int new_frame_coding_order_period;
 | 
			
		||||
  int frame_coding_order[MAX_LAG_BUFFERS * 2];
 | 
			
		||||
  int arf_buffer_idx[MAX_LAG_BUFFERS * 3 / 2];
 | 
			
		||||
  int arf_weight[MAX_LAG_BUFFERS];
 | 
			
		||||
  int arf_buffered;
 | 
			
		||||
  int this_frame_weight;
 | 
			
		||||
  int max_arf_level;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_DENOISING
 | 
			
		||||
  VP9_DENOISER denoiser;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MASKED_INTERINTER
 | 
			
		||||
  unsigned int masked_interinter_select_counts[2];
 | 
			
		||||
#endif
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  unsigned int interintra_select_count[2];
 | 
			
		||||
#if CONFIG_MASKED_INTERINTRA
 | 
			
		||||
  unsigned int masked_interintra_select_count[2];
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
} VP9_COMP;
 | 
			
		||||
 | 
			
		||||
void vp9_initialize_enc();
 | 
			
		||||
@@ -622,10 +530,14 @@ void vp9_update_reference_frames(VP9_COMP *cpi);
 | 
			
		||||
 | 
			
		||||
int64_t vp9_rescale(int64_t val, int64_t num, int denom);
 | 
			
		||||
 | 
			
		||||
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv);
 | 
			
		||||
 | 
			
		||||
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
 | 
			
		||||
                                          YV12_BUFFER_CONFIG *unscaled,
 | 
			
		||||
                                          YV12_BUFFER_CONFIG *scaled);
 | 
			
		||||
 | 
			
		||||
void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags);
 | 
			
		||||
 | 
			
		||||
static INLINE void set_ref_ptrs(VP9_COMMON *cm, MACROBLOCKD *xd,
 | 
			
		||||
                                MV_REFERENCE_FRAME ref0,
 | 
			
		||||
                                MV_REFERENCE_FRAME ref1) {
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,6 @@
 | 
			
		||||
#include "vp9/encoder/vp9_firstpass.h"
 | 
			
		||||
#include "vp9/encoder/vp9_mcomp.h"
 | 
			
		||||
#include "vp9/encoder/vp9_quantize.h"
 | 
			
		||||
#include "vp9/encoder/vp9_ratectrl.h"
 | 
			
		||||
#include "vp9/encoder/vp9_rdopt.h"
 | 
			
		||||
#include "vp9/encoder/vp9_variance.h"
 | 
			
		||||
 | 
			
		||||
@@ -56,14 +55,7 @@
 | 
			
		||||
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
 | 
			
		||||
 | 
			
		||||
#define MIN_KF_BOOST        300
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
// Set MIN_GF_INTERVAL to 1 for the full decomposition.
 | 
			
		||||
#define MIN_GF_INTERVAL             2
 | 
			
		||||
#else
 | 
			
		||||
#define MIN_GF_INTERVAL             4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MIN_GF_INTERVAL     4
 | 
			
		||||
#define LONG_TERM_VBR_CORRECTION
 | 
			
		||||
 | 
			
		||||
static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
 | 
			
		||||
@@ -497,6 +489,8 @@ void vp9_first_pass(VP9_COMP *cpi) {
 | 
			
		||||
                                        &cpi->scaled_source);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
 | 
			
		||||
 | 
			
		||||
  vp9_setup_src_planes(x, cpi->Source, 0, 0);
 | 
			
		||||
  vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
 | 
			
		||||
  vp9_setup_dst_planes(xd->plane, new_yv12, 0, 0);
 | 
			
		||||
@@ -504,8 +498,6 @@ void vp9_first_pass(VP9_COMP *cpi) {
 | 
			
		||||
  xd->mi = cm->mi_grid_visible;
 | 
			
		||||
  xd->mi[0] = cm->mi;
 | 
			
		||||
 | 
			
		||||
  vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
 | 
			
		||||
 | 
			
		||||
  vp9_frame_init_quantizer(cpi);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < MAX_MB_PLANE; ++i) {
 | 
			
		||||
@@ -615,7 +607,8 @@ void vp9_first_pass(VP9_COMP *cpi) {
 | 
			
		||||
                                                &unscaled_last_source_buf_2d);
 | 
			
		||||
 | 
			
		||||
        // TODO(pengchong): Replace the hard-coded threshold
 | 
			
		||||
        if (raw_motion_error > 25) {
 | 
			
		||||
        if (raw_motion_error > 25 ||
 | 
			
		||||
            (cpi->use_svc && cpi->svc.number_temporal_layers == 1)) {
 | 
			
		||||
          // Test last reference frame using the previous best mv as the
 | 
			
		||||
          // starting point (best reference) for the search.
 | 
			
		||||
          first_pass_motion_search(cpi, x, &best_ref_mv.as_mv, &mv.as_mv,
 | 
			
		||||
@@ -1221,144 +1214,6 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset,
 | 
			
		||||
  return arf_boost;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
// Work out the frame coding order for a GF or an ARF group.
 | 
			
		||||
// The current implementation codes frames in their natural order for a
 | 
			
		||||
// GF group, and inserts additional ARFs into an ARF group using a
 | 
			
		||||
// binary split approach.
 | 
			
		||||
// NOTE: this function is currently implemented recursively.
 | 
			
		||||
static void schedule_frames(VP9_COMP *cpi, const int start, const int end,
 | 
			
		||||
                            const int arf_idx, const int gf_or_arf_group,
 | 
			
		||||
                            const int level) {
 | 
			
		||||
  int i, abs_end, half_range;
 | 
			
		||||
  int *cfo = cpi->frame_coding_order;
 | 
			
		||||
  int idx = cpi->new_frame_coding_order_period;
 | 
			
		||||
 | 
			
		||||
  // If (end < 0) an ARF should be coded at position (-end).
 | 
			
		||||
  assert(start >= 0);
 | 
			
		||||
 | 
			
		||||
  // printf("start:%d end:%d\n", start, end);
 | 
			
		||||
 | 
			
		||||
  // GF Group: code frames in logical order.
 | 
			
		||||
  if (gf_or_arf_group == 0) {
 | 
			
		||||
    assert(end >= start);
 | 
			
		||||
    for (i = start; i <= end; ++i) {
 | 
			
		||||
      cfo[idx] = i;
 | 
			
		||||
      cpi->arf_buffer_idx[idx] = arf_idx;
 | 
			
		||||
      cpi->arf_weight[idx] = -1;
 | 
			
		||||
      ++idx;
 | 
			
		||||
    }
 | 
			
		||||
    cpi->new_frame_coding_order_period = idx;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // ARF Group: Work out the ARF schedule and mark ARF frames as negative.
 | 
			
		||||
  if (end < 0) {
 | 
			
		||||
    // printf("start:%d end:%d\n", -end, -end);
 | 
			
		||||
    // ARF frame is at the end of the range.
 | 
			
		||||
    cfo[idx] = end;
 | 
			
		||||
    // What ARF buffer does this ARF use as predictor.
 | 
			
		||||
    cpi->arf_buffer_idx[idx] = (arf_idx > 2) ? (arf_idx - 1) : 2;
 | 
			
		||||
    cpi->arf_weight[idx] = level;
 | 
			
		||||
    ++idx;
 | 
			
		||||
    abs_end = -end;
 | 
			
		||||
  } else {
 | 
			
		||||
    abs_end = end;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  half_range = (abs_end - start) >> 1;
 | 
			
		||||
 | 
			
		||||
  // ARFs may not be adjacent, they must be separated by at least
 | 
			
		||||
  // MIN_GF_INTERVAL non-ARF frames.
 | 
			
		||||
  if ((start + MIN_GF_INTERVAL) >= (abs_end - MIN_GF_INTERVAL)) {
 | 
			
		||||
    // printf("start:%d end:%d\n", start, abs_end);
 | 
			
		||||
    // Update the coding order and active ARF.
 | 
			
		||||
    for (i = start; i <= abs_end; ++i) {
 | 
			
		||||
      cfo[idx] = i;
 | 
			
		||||
      cpi->arf_buffer_idx[idx] = arf_idx;
 | 
			
		||||
      cpi->arf_weight[idx] = -1;
 | 
			
		||||
      ++idx;
 | 
			
		||||
    }
 | 
			
		||||
    cpi->new_frame_coding_order_period = idx;
 | 
			
		||||
  } else {
 | 
			
		||||
    // Place a new ARF at the mid-point of the range.
 | 
			
		||||
    cpi->new_frame_coding_order_period = idx;
 | 
			
		||||
    schedule_frames(cpi, start, -(start + half_range), arf_idx + 1,
 | 
			
		||||
                    gf_or_arf_group, level + 1);
 | 
			
		||||
    schedule_frames(cpi, start + half_range + 1, abs_end, arf_idx,
 | 
			
		||||
                    gf_or_arf_group, level + 1);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define FIXED_ARF_GROUP_SIZE 16
 | 
			
		||||
 | 
			
		||||
void define_fixed_arf_period(VP9_COMP *cpi) {
 | 
			
		||||
  int i;
 | 
			
		||||
  int max_level = INT_MIN;
 | 
			
		||||
 | 
			
		||||
  assert(cpi->multi_arf_enabled);
 | 
			
		||||
  assert(cpi->oxcf.lag_in_frames >= FIXED_ARF_GROUP_SIZE);
 | 
			
		||||
 | 
			
		||||
  // Save the weight of the last frame in the sequence before next
 | 
			
		||||
  // sequence pattern overwrites it.
 | 
			
		||||
  cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number];
 | 
			
		||||
  assert(cpi->this_frame_weight >= 0);
 | 
			
		||||
 | 
			
		||||
  cpi->twopass.gf_zeromotion_pct = 0;
 | 
			
		||||
 | 
			
		||||
  // Initialize frame coding order variables.
 | 
			
		||||
  cpi->new_frame_coding_order_period = 0;
 | 
			
		||||
  cpi->next_frame_in_order = 0;
 | 
			
		||||
  cpi->arf_buffered = 0;
 | 
			
		||||
  vp9_zero(cpi->frame_coding_order);
 | 
			
		||||
  vp9_zero(cpi->arf_buffer_idx);
 | 
			
		||||
  vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight));
 | 
			
		||||
 | 
			
		||||
  if (cpi->rc.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) {
 | 
			
		||||
    // Setup a GF group close to the keyframe.
 | 
			
		||||
    cpi->rc.source_alt_ref_pending = 0;
 | 
			
		||||
    cpi->rc.baseline_gf_interval = cpi->rc.frames_to_key;
 | 
			
		||||
    schedule_frames(cpi, 0, (cpi->rc.baseline_gf_interval - 1), 2, 0, 0);
 | 
			
		||||
  } else {
 | 
			
		||||
    // Setup a fixed period ARF group.
 | 
			
		||||
    cpi->rc.source_alt_ref_pending = 1;
 | 
			
		||||
    cpi->rc.baseline_gf_interval = FIXED_ARF_GROUP_SIZE;
 | 
			
		||||
    schedule_frames(cpi, 0, -(cpi->rc.baseline_gf_interval - 1), 2, 1, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Replace level indicator of -1 with correct level.
 | 
			
		||||
  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
    if (cpi->arf_weight[i] > max_level) {
 | 
			
		||||
      max_level = cpi->arf_weight[i];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  ++max_level;
 | 
			
		||||
  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
    if (cpi->arf_weight[i] == -1) {
 | 
			
		||||
      cpi->arf_weight[i] = max_level;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  cpi->max_arf_level = max_level;
 | 
			
		||||
#if 0
 | 
			
		||||
  printf("\nSchedule: ");
 | 
			
		||||
  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
    printf("%4d ", cpi->frame_coding_order[i]);
 | 
			
		||||
  }
 | 
			
		||||
  printf("\n");
 | 
			
		||||
  printf("ARFref:   ");
 | 
			
		||||
  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
    printf("%4d ", cpi->arf_buffer_idx[i]);
 | 
			
		||||
  }
 | 
			
		||||
  printf("\n");
 | 
			
		||||
  printf("Weight:   ");
 | 
			
		||||
  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
    printf("%4d ", cpi->arf_weight[i]);
 | 
			
		||||
  }
 | 
			
		||||
  printf("\n");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Calculate a section intra ratio used in setting max loop filter.
 | 
			
		||||
static int calculate_section_intra_ratio(const FIRSTPASS_STATS *begin,
 | 
			
		||||
                                         const FIRSTPASS_STATS *end,
 | 
			
		||||
@@ -1428,6 +1283,18 @@ static int calculate_boost_bits(int frame_count,
 | 
			
		||||
  return MAX((int)(((int64_t)boost * total_group_bits) / allocation_chunks), 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Current limit on maximum number of active arfs in a GF/ARF group.
 | 
			
		||||
#define MAX_ACTIVE_ARFS 2
 | 
			
		||||
#define ARF_SLOT1 2
 | 
			
		||||
#define ARF_SLOT2 3
 | 
			
		||||
// This function indirects the choice of buffers for arfs.
 | 
			
		||||
// At the moment the values are fixed but this may change as part of
 | 
			
		||||
// the integration process with other codec features that swap buffers around.
 | 
			
		||||
static void get_arf_buffer_indices(unsigned char *arf_buffer_indices) {
 | 
			
		||||
  arf_buffer_indices[0] = ARF_SLOT1;
 | 
			
		||||
  arf_buffer_indices[1] = ARF_SLOT2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
 | 
			
		||||
                                   double group_error, int gf_arf_bits) {
 | 
			
		||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
@@ -1435,42 +1302,85 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
 | 
			
		||||
  TWO_PASS *twopass = &cpi->twopass;
 | 
			
		||||
  FIRSTPASS_STATS frame_stats;
 | 
			
		||||
  int i;
 | 
			
		||||
  int group_frame_index = 1;
 | 
			
		||||
  int frame_index = 1;
 | 
			
		||||
  int target_frame_size;
 | 
			
		||||
  int key_frame;
 | 
			
		||||
  const int max_bits = frame_max_bits(&cpi->rc, &cpi->oxcf);
 | 
			
		||||
  int64_t total_group_bits = gf_group_bits;
 | 
			
		||||
  double modified_err = 0.0;
 | 
			
		||||
  double err_fraction;
 | 
			
		||||
  int mid_boost_bits = 0;
 | 
			
		||||
  int mid_frame_idx;
 | 
			
		||||
  unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
 | 
			
		||||
 | 
			
		||||
  key_frame = cpi->common.frame_type == KEY_FRAME ||
 | 
			
		||||
              vp9_is_upper_layer_key_frame(cpi);
 | 
			
		||||
 | 
			
		||||
  get_arf_buffer_indices(arf_buffer_indices);
 | 
			
		||||
 | 
			
		||||
  // For key frames the frame target rate is already set and it
 | 
			
		||||
  // is also the golden frame.
 | 
			
		||||
  // NOTE: We dont bother to check for the special case of ARF overlay
 | 
			
		||||
  // frames here, as there is clamping code for this in the function
 | 
			
		||||
  // vp9_rc_clamp_pframe_target_size(), which applies to one and two pass
 | 
			
		||||
  // encodes.
 | 
			
		||||
  if (!key_frame) {
 | 
			
		||||
    twopass->gf_group_bit_allocation[0] = gf_arf_bits;
 | 
			
		||||
    if (rc->source_alt_ref_active) {
 | 
			
		||||
      twopass->gf_group.update_type[0] = OVERLAY_UPDATE;
 | 
			
		||||
      twopass->gf_group.rf_level[0] = INTER_NORMAL;
 | 
			
		||||
      twopass->gf_group.bit_allocation[0] = 0;
 | 
			
		||||
      twopass->gf_group.arf_update_idx[0] = arf_buffer_indices[0];
 | 
			
		||||
      twopass->gf_group.arf_ref_idx[0] = arf_buffer_indices[0];
 | 
			
		||||
    } else {
 | 
			
		||||
      twopass->gf_group.update_type[0] = GF_UPDATE;
 | 
			
		||||
      twopass->gf_group.rf_level[0] = GF_ARF_STD;
 | 
			
		||||
      twopass->gf_group.bit_allocation[0] = gf_arf_bits;
 | 
			
		||||
      twopass->gf_group.arf_update_idx[0] = arf_buffer_indices[0];
 | 
			
		||||
      twopass->gf_group.arf_ref_idx[0] = arf_buffer_indices[0];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Step over the golden frame / overlay frame
 | 
			
		||||
    if (EOF == input_stats(twopass, &frame_stats))
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Store the bits to spend on the ARF if there is one.
 | 
			
		||||
  if (rc->source_alt_ref_pending) {
 | 
			
		||||
    twopass->gf_group_bit_allocation[group_frame_index++] = gf_arf_bits;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Deduct the boost bits for arf or gf if it is not a key frame.
 | 
			
		||||
  // Deduct the boost bits for arf (or gf if it is not a key frame)
 | 
			
		||||
  // from the group total.
 | 
			
		||||
  if (rc->source_alt_ref_pending || !key_frame)
 | 
			
		||||
    total_group_bits -= gf_arf_bits;
 | 
			
		||||
 | 
			
		||||
  // Store the bits to spend on the ARF if there is one.
 | 
			
		||||
  if (rc->source_alt_ref_pending) {
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      // A portion of the gf / arf extra bits are set asside for lower level
 | 
			
		||||
      // boosted frames in the middle of the group.
 | 
			
		||||
      mid_boost_bits += gf_arf_bits >> 5;
 | 
			
		||||
      gf_arf_bits -= (gf_arf_bits >> 5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    twopass->gf_group.update_type[frame_index] = ARF_UPDATE;
 | 
			
		||||
    twopass->gf_group.rf_level[frame_index] = GF_ARF_STD;
 | 
			
		||||
    twopass->gf_group.bit_allocation[frame_index] = gf_arf_bits;
 | 
			
		||||
    twopass->gf_group.arf_src_offset[frame_index] =
 | 
			
		||||
      (unsigned char)(rc->baseline_gf_interval - 1);
 | 
			
		||||
    twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0];
 | 
			
		||||
    twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
 | 
			
		||||
    ++frame_index;
 | 
			
		||||
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      // Set aside a slot for a level 1 arf.
 | 
			
		||||
      twopass->gf_group.update_type[frame_index] = ARF_UPDATE;
 | 
			
		||||
      twopass->gf_group.rf_level[frame_index] = GF_ARF_LOW;
 | 
			
		||||
      twopass->gf_group.arf_src_offset[frame_index] =
 | 
			
		||||
        (unsigned char)((rc->baseline_gf_interval >> 1) - 1);
 | 
			
		||||
      twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[1];
 | 
			
		||||
      twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
 | 
			
		||||
      ++frame_index;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Define middle frame
 | 
			
		||||
  mid_frame_idx = frame_index + (rc->baseline_gf_interval >> 1) - 1;
 | 
			
		||||
 | 
			
		||||
  // Allocate bits to the other frames in the group.
 | 
			
		||||
  for (i = 0; i < rc->baseline_gf_interval - 1; ++i) {
 | 
			
		||||
    int arf_idx = 0;
 | 
			
		||||
    if (EOF == input_stats(twopass, &frame_stats))
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
@@ -1482,10 +1392,48 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
 | 
			
		||||
      err_fraction = 0.0;
 | 
			
		||||
 | 
			
		||||
    target_frame_size = (int)((double)total_group_bits * err_fraction);
 | 
			
		||||
 | 
			
		||||
    if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) {
 | 
			
		||||
      mid_boost_bits += (target_frame_size >> 4);
 | 
			
		||||
      target_frame_size -= (target_frame_size >> 4);
 | 
			
		||||
 | 
			
		||||
      if (frame_index <= mid_frame_idx)
 | 
			
		||||
        arf_idx = 1;
 | 
			
		||||
    }
 | 
			
		||||
    twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[arf_idx];
 | 
			
		||||
    twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[arf_idx];
 | 
			
		||||
 | 
			
		||||
    target_frame_size = clamp(target_frame_size, 0,
 | 
			
		||||
                              MIN(max_bits, (int)total_group_bits));
 | 
			
		||||
 | 
			
		||||
    twopass->gf_group_bit_allocation[group_frame_index++] = target_frame_size;
 | 
			
		||||
    twopass->gf_group.update_type[frame_index] = LF_UPDATE;
 | 
			
		||||
    twopass->gf_group.rf_level[frame_index] = INTER_NORMAL;
 | 
			
		||||
 | 
			
		||||
    twopass->gf_group.bit_allocation[frame_index] = target_frame_size;
 | 
			
		||||
    ++frame_index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Note:
 | 
			
		||||
  // We need to configure the frame at the end of the sequence + 1 that will be
 | 
			
		||||
  // the start frame for the next group. Otherwise prior to the call to
 | 
			
		||||
  // vp9_rc_get_second_pass_params() the data will be undefined.
 | 
			
		||||
  twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0];
 | 
			
		||||
  twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
 | 
			
		||||
 | 
			
		||||
  if (rc->source_alt_ref_pending) {
 | 
			
		||||
    twopass->gf_group.update_type[frame_index] = OVERLAY_UPDATE;
 | 
			
		||||
    twopass->gf_group.rf_level[frame_index] = INTER_NORMAL;
 | 
			
		||||
 | 
			
		||||
    // Final setup for second arf and its overlay.
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      twopass->gf_group.bit_allocation[2] =
 | 
			
		||||
        twopass->gf_group.bit_allocation[mid_frame_idx] + mid_boost_bits;
 | 
			
		||||
      twopass->gf_group.update_type[mid_frame_idx] = OVERLAY_UPDATE;
 | 
			
		||||
      twopass->gf_group.bit_allocation[mid_frame_idx] = 0;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    twopass->gf_group.update_type[frame_index] = GF_UPDATE;
 | 
			
		||||
    twopass->gf_group.rf_level[frame_index] = GF_ARF_STD;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1528,8 +1476,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
 | 
			
		||||
  // Reset the GF group data structures unless this is a key
 | 
			
		||||
  // frame in which case it will already have been done.
 | 
			
		||||
  if (cpi->common.frame_type != KEY_FRAME) {
 | 
			
		||||
    twopass->gf_group_index = 0;
 | 
			
		||||
    vp9_zero(twopass->gf_group_bit_allocation);
 | 
			
		||||
    vp9_zero(twopass->gf_group);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vp9_clear_system_state();
 | 
			
		||||
@@ -1651,24 +1598,14 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  if (cpi->multi_arf_enabled) {
 | 
			
		||||
    // Initialize frame coding order variables.
 | 
			
		||||
    cpi->new_frame_coding_order_period = 0;
 | 
			
		||||
    cpi->next_frame_in_order = 0;
 | 
			
		||||
    cpi->arf_buffered = 0;
 | 
			
		||||
    vp9_zero(cpi->frame_coding_order);
 | 
			
		||||
    vp9_zero(cpi->arf_buffer_idx);
 | 
			
		||||
    vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight));
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // Set the interval until the next gf.
 | 
			
		||||
  if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active)
 | 
			
		||||
    rc->baseline_gf_interval = i - 1;
 | 
			
		||||
  else
 | 
			
		||||
    rc->baseline_gf_interval = i;
 | 
			
		||||
 | 
			
		||||
  rc->frames_till_gf_update_due = rc->baseline_gf_interval;
 | 
			
		||||
 | 
			
		||||
  // Should we use the alternate reference frame.
 | 
			
		||||
  if (allow_alt_ref &&
 | 
			
		||||
      (i < cpi->oxcf.lag_in_frames) &&
 | 
			
		||||
@@ -1681,62 +1618,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
 | 
			
		||||
                                   &b_boost);
 | 
			
		||||
    rc->source_alt_ref_pending = 1;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    // Set the ARF schedule.
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      schedule_frames(cpi, 0, -(rc->baseline_gf_interval - 1), 2, 1, 0);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  } else {
 | 
			
		||||
    rc->gfu_boost = (int)boost_score;
 | 
			
		||||
    rc->source_alt_ref_pending = 0;
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    // Set the GF schedule.
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      schedule_frames(cpi, 0, rc->baseline_gf_interval - 1, 2, 0, 0);
 | 
			
		||||
      assert(cpi->new_frame_coding_order_period ==
 | 
			
		||||
             rc->baseline_gf_interval);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  if (cpi->multi_arf_enabled && (cpi->common.frame_type != KEY_FRAME)) {
 | 
			
		||||
    int max_level = INT_MIN;
 | 
			
		||||
    // Replace level indicator of -1 with correct level.
 | 
			
		||||
    for (i = 0; i < cpi->frame_coding_order_period; ++i) {
 | 
			
		||||
      if (cpi->arf_weight[i] > max_level) {
 | 
			
		||||
        max_level = cpi->arf_weight[i];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    ++max_level;
 | 
			
		||||
    for (i = 0; i < cpi->frame_coding_order_period; ++i) {
 | 
			
		||||
      if (cpi->arf_weight[i] == -1) {
 | 
			
		||||
        cpi->arf_weight[i] = max_level;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    cpi->max_arf_level = max_level;
 | 
			
		||||
  }
 | 
			
		||||
#if 0
 | 
			
		||||
  if (cpi->multi_arf_enabled) {
 | 
			
		||||
    printf("\nSchedule: ");
 | 
			
		||||
    for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
      printf("%4d ", cpi->frame_coding_order[i]);
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n");
 | 
			
		||||
    printf("ARFref:   ");
 | 
			
		||||
    for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
      printf("%4d ", cpi->arf_buffer_idx[i]);
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n");
 | 
			
		||||
    printf("Weight:   ");
 | 
			
		||||
    for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
 | 
			
		||||
      printf("%4d ", cpi->arf_weight[i]);
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n");
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
  // Reset the file position.
 | 
			
		||||
  reset_fpf_position(twopass, start_pos);
 | 
			
		||||
 | 
			
		||||
@@ -1886,8 +1772,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
 | 
			
		||||
  cpi->common.frame_type = KEY_FRAME;
 | 
			
		||||
 | 
			
		||||
  // Reset the GF group data structures.
 | 
			
		||||
  twopass->gf_group_index = 0;
 | 
			
		||||
  vp9_zero(twopass->gf_group_bit_allocation);
 | 
			
		||||
  vp9_zero(twopass->gf_group);
 | 
			
		||||
 | 
			
		||||
  // Is this a forced key frame by interval.
 | 
			
		||||
  rc->this_key_frame_forced = rc->next_key_frame_forced;
 | 
			
		||||
@@ -2078,7 +1963,9 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
 | 
			
		||||
  twopass->kf_group_bits -= kf_bits;
 | 
			
		||||
 | 
			
		||||
  // Save the bits to spend on the key frame.
 | 
			
		||||
  twopass->gf_group_bit_allocation[0] = kf_bits;
 | 
			
		||||
  twopass->gf_group.bit_allocation[0] = kf_bits;
 | 
			
		||||
  twopass->gf_group.update_type[0] = KF_UPDATE;
 | 
			
		||||
  twopass->gf_group.rf_level[0] = KF_STD;
 | 
			
		||||
 | 
			
		||||
  // Note the total error score of the kf group minus the key frame itself.
 | 
			
		||||
  twopass->kf_group_error_left = (int)(kf_group_err - kf_mod_err);
 | 
			
		||||
@@ -2106,6 +1993,44 @@ void vbr_rate_correction(int * this_frame_target,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Define the reference buffers that will be updated post encode.
 | 
			
		||||
void configure_buffer_updates(VP9_COMP *cpi) {
 | 
			
		||||
  TWO_PASS *const twopass = &cpi->twopass;
 | 
			
		||||
 | 
			
		||||
  cpi->rc.is_src_frame_alt_ref = 0;
 | 
			
		||||
  switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
 | 
			
		||||
    case KF_UPDATE:
 | 
			
		||||
      cpi->refresh_last_frame = 1;
 | 
			
		||||
      cpi->refresh_golden_frame = 1;
 | 
			
		||||
      cpi->refresh_alt_ref_frame = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    case LF_UPDATE:
 | 
			
		||||
      cpi->refresh_last_frame = 1;
 | 
			
		||||
      cpi->refresh_golden_frame = 0;
 | 
			
		||||
      cpi->refresh_alt_ref_frame = 0;
 | 
			
		||||
      break;
 | 
			
		||||
    case GF_UPDATE:
 | 
			
		||||
      cpi->refresh_last_frame = 1;
 | 
			
		||||
      cpi->refresh_golden_frame = 1;
 | 
			
		||||
      cpi->refresh_alt_ref_frame = 0;
 | 
			
		||||
      break;
 | 
			
		||||
    case OVERLAY_UPDATE:
 | 
			
		||||
      cpi->refresh_last_frame = 0;
 | 
			
		||||
      cpi->refresh_golden_frame = 1;
 | 
			
		||||
      cpi->refresh_alt_ref_frame = 0;
 | 
			
		||||
      cpi->rc.is_src_frame_alt_ref = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    case ARF_UPDATE:
 | 
			
		||||
      cpi->refresh_last_frame = 0;
 | 
			
		||||
      cpi->refresh_golden_frame = 0;
 | 
			
		||||
      cpi->refresh_alt_ref_frame = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
@@ -2130,14 +2055,12 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
 | 
			
		||||
  if (!twopass->stats_in)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  // Increment the gf group index.
 | 
			
		||||
  ++twopass->gf_group_index;
 | 
			
		||||
 | 
			
		||||
  // If this is an arf frame then we dont want to read the stats file or
 | 
			
		||||
  // advance the input pointer as we already have what we need.
 | 
			
		||||
  if (cpi->refresh_alt_ref_frame) {
 | 
			
		||||
  if (twopass->gf_group.update_type[twopass->gf_group.index] == ARF_UPDATE) {
 | 
			
		||||
    int target_rate;
 | 
			
		||||
    target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index];
 | 
			
		||||
    configure_buffer_updates(cpi);
 | 
			
		||||
    target_rate = twopass->gf_group.bit_allocation[twopass->gf_group.index];
 | 
			
		||||
    target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate);
 | 
			
		||||
    rc->base_frame_target = target_rate;
 | 
			
		||||
#ifdef LONG_TERM_VBR_CORRECTION
 | 
			
		||||
@@ -2201,15 +2124,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
 | 
			
		||||
 | 
			
		||||
  // Define a new GF/ARF group. (Should always enter here for key frames).
 | 
			
		||||
  if (rc->frames_till_gf_update_due == 0) {
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    if (cpi->multi_arf_enabled) {
 | 
			
		||||
      define_fixed_arf_period(cpi);
 | 
			
		||||
    } else {
 | 
			
		||||
#endif
 | 
			
		||||
      define_gf_group(cpi, &this_frame_copy);
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    define_gf_group(cpi, &this_frame_copy);
 | 
			
		||||
 | 
			
		||||
    if (twopass->gf_zeromotion_pct > 995) {
 | 
			
		||||
      // As long as max_thresh for encode breakout is small enough, it is ok
 | 
			
		||||
@@ -2233,7 +2148,9 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index];
 | 
			
		||||
  configure_buffer_updates(cpi);
 | 
			
		||||
 | 
			
		||||
  target_rate = twopass->gf_group.bit_allocation[twopass->gf_group.index];
 | 
			
		||||
  if (cpi->common.frame_type == KEY_FRAME)
 | 
			
		||||
    target_rate = vp9_rc_clamp_iframe_target_size(cpi, target_rate);
 | 
			
		||||
  else
 | 
			
		||||
@@ -2296,4 +2213,7 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) {
 | 
			
		||||
    twopass->kf_group_bits -= bits_used;
 | 
			
		||||
  }
 | 
			
		||||
  twopass->kf_group_bits = MAX(twopass->kf_group_bits, 0);
 | 
			
		||||
 | 
			
		||||
  // Increment the gf group index ready for the next frame.
 | 
			
		||||
  ++twopass->gf_group.index;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
#define VP9_ENCODER_VP9_FIRSTPASS_H_
 | 
			
		||||
 | 
			
		||||
#include "vp9/encoder/vp9_lookahead.h"
 | 
			
		||||
#include "vp9/encoder/vp9_ratectrl.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
@@ -39,6 +40,25 @@ typedef struct {
 | 
			
		||||
  int64_t spatial_layer_id;
 | 
			
		||||
} FIRSTPASS_STATS;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  KF_UPDATE = 0,
 | 
			
		||||
  LF_UPDATE = 1,
 | 
			
		||||
  GF_UPDATE = 2,
 | 
			
		||||
  ARF_UPDATE = 3,
 | 
			
		||||
  OVERLAY_UPDATE = 4,
 | 
			
		||||
  FRAME_UPDATE_TYPES = 5
 | 
			
		||||
} FRAME_UPDATE_TYPE;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  unsigned char index;
 | 
			
		||||
  RATE_FACTOR_LEVEL rf_level[(MAX_LAG_BUFFERS * 2) + 1];
 | 
			
		||||
  FRAME_UPDATE_TYPE update_type[(MAX_LAG_BUFFERS * 2) + 1];
 | 
			
		||||
  unsigned char arf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
 | 
			
		||||
  unsigned char arf_update_idx[(MAX_LAG_BUFFERS * 2) + 1];
 | 
			
		||||
  unsigned char arf_ref_idx[(MAX_LAG_BUFFERS * 2) + 1];
 | 
			
		||||
  int bit_allocation[(MAX_LAG_BUFFERS * 2) + 1];
 | 
			
		||||
} GF_GROUP;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  unsigned int section_intra_rating;
 | 
			
		||||
  unsigned int next_iiratio;
 | 
			
		||||
@@ -68,8 +88,7 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
  int active_worst_quality;
 | 
			
		||||
 | 
			
		||||
  int gf_group_index;
 | 
			
		||||
  int gf_group_bit_allocation[MAX_LAG_BUFFERS * 2];
 | 
			
		||||
  GF_GROUP gf_group;
 | 
			
		||||
} TWO_PASS;
 | 
			
		||||
 | 
			
		||||
struct VP9_COMP;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,18 +18,6 @@
 | 
			
		||||
#include "vp9/encoder/vp9_extend.h"
 | 
			
		||||
#include "vp9/encoder/vp9_lookahead.h"
 | 
			
		||||
 | 
			
		||||
// The max of past frames we want to keep in the queue.
 | 
			
		||||
#define MAX_PRE_FRAMES 1
 | 
			
		||||
 | 
			
		||||
struct lookahead_ctx {
 | 
			
		||||
  unsigned int max_sz;         /* Absolute size of the queue */
 | 
			
		||||
  unsigned int sz;             /* Number of buffers currently in the queue */
 | 
			
		||||
  unsigned int read_idx;       /* Read index */
 | 
			
		||||
  unsigned int write_idx;      /* Write index */
 | 
			
		||||
  struct lookahead_entry *buf; /* Buffer list */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Return the buffer at the given absolute index and increment the index */
 | 
			
		||||
static struct lookahead_entry *pop(struct lookahead_ctx *ctx,
 | 
			
		||||
                                   unsigned int *idx) {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,11 @@
 | 
			
		||||
#include "vpx_scale/yv12config.h"
 | 
			
		||||
#include "vpx/vpx_integer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
#include "vpx/vp8cx.h"
 | 
			
		||||
#include "vpx/vpx_encoder.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
@@ -25,10 +30,22 @@ struct lookahead_entry {
 | 
			
		||||
  int64_t             ts_start;
 | 
			
		||||
  int64_t             ts_end;
 | 
			
		||||
  unsigned int        flags;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
  vpx_svc_parameters_t svc_params[VPX_SS_MAX_LAYERS];
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// The max of past frames we want to keep in the queue.
 | 
			
		||||
#define MAX_PRE_FRAMES 1
 | 
			
		||||
 | 
			
		||||
struct lookahead_ctx;
 | 
			
		||||
struct lookahead_ctx {
 | 
			
		||||
  unsigned int max_sz;         /* Absolute size of the queue */
 | 
			
		||||
  unsigned int sz;             /* Number of buffers currently in the queue */
 | 
			
		||||
  unsigned int read_idx;       /* Read index */
 | 
			
		||||
  unsigned int write_idx;      /* Write index */
 | 
			
		||||
  struct lookahead_entry *buf; /* Buffer list */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**\brief Initializes the lookahead stage
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,9 @@ static unsigned int do_16x16_motion_iteration(VP9_COMP *cpi,
 | 
			
		||||
  xd->mi[0]->mbmi.mode = NEWMV;
 | 
			
		||||
  xd->mi[0]->mbmi.mv[0].as_mv = *dst_mv;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  xd->mi[0]->mbmi.ref_frame[1] = NONE;
 | 
			
		||||
#endif
 | 
			
		||||
  vp9_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_16X16);
 | 
			
		||||
 | 
			
		||||
  /* restore UMV window */
 | 
			
		||||
@@ -141,6 +144,9 @@ static int find_best_16x16_intra(VP9_COMP *cpi, PREDICTION_MODE *pbest_mode) {
 | 
			
		||||
 | 
			
		||||
    xd->mi[0]->mbmi.mode = mode;
 | 
			
		||||
    vp9_predict_intra_block(xd, 0, 2, TX_16X16, mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                            0,
 | 
			
		||||
#endif
 | 
			
		||||
                            x->plane[0].src.buf, x->plane[0].src.stride,
 | 
			
		||||
                            xd->plane[0].dst.buf, xd->plane[0].dst.stride,
 | 
			
		||||
                            0, 0, 0);
 | 
			
		||||
 
 | 
			
		||||
@@ -1640,3 +1640,354 @@ int vp9_full_pixel_search(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
 | 
			
		||||
  return var;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
    CONFIG_MASKED_INTERINTER)
 | 
			
		||||
/* returns subpixel variance error function */
 | 
			
		||||
#define DIST(r, c) \
 | 
			
		||||
    vfp->msvf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
 | 
			
		||||
              src_stride, mask, mask_stride, &sse)
 | 
			
		||||
 | 
			
		||||
/* checks if (r, c) has better score than previous best */
 | 
			
		||||
 | 
			
		||||
#define MVC(r, c)                                       \
 | 
			
		||||
    (mvcost ?                                           \
 | 
			
		||||
     ((mvjcost[((r) != rr) * 2 + ((c) != rc)] +         \
 | 
			
		||||
       mvcost[0][((r) - rr)] + mvcost[1][((c) - rc)]) * \
 | 
			
		||||
      error_per_bit + 4096) >> 13 : 0)
 | 
			
		||||
 | 
			
		||||
#define CHECK_BETTER(v, r, c) \
 | 
			
		||||
  if (c >= minc && c <= maxc && r >= minr && r <= maxr) {              \
 | 
			
		||||
    thismse = (DIST(r, c));                                            \
 | 
			
		||||
    if ((v = MVC(r, c) + thismse) < besterr) {                         \
 | 
			
		||||
      besterr = v;                                                     \
 | 
			
		||||
      br = r;                                                          \
 | 
			
		||||
      bc = c;                                                          \
 | 
			
		||||
      *distortion = thismse;                                           \
 | 
			
		||||
      *sse1 = sse;                                                     \
 | 
			
		||||
    }                                                                  \
 | 
			
		||||
  } else {                                                             \
 | 
			
		||||
    v = INT_MAX;                                                       \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
 | 
			
		||||
                                        uint8_t *mask, int mask_stride,
 | 
			
		||||
                                        MV *bestmv, const MV *ref_mv,
 | 
			
		||||
                                        int allow_hp,
 | 
			
		||||
                                        int error_per_bit,
 | 
			
		||||
                                        const vp9_variance_fn_ptr_t *vfp,
 | 
			
		||||
                                        int forced_stop,
 | 
			
		||||
                                        int iters_per_step,
 | 
			
		||||
                                        int *mvjcost, int *mvcost[2],
 | 
			
		||||
                                        int *distortion,
 | 
			
		||||
                                        unsigned int *sse1, int is_second) {
 | 
			
		||||
  const uint8_t *const z = x->plane[0].src.buf;
 | 
			
		||||
  const int src_stride = x->plane[0].src.stride;
 | 
			
		||||
  const MACROBLOCKD *xd = &x->e_mbd;
 | 
			
		||||
  unsigned int besterr = INT_MAX;
 | 
			
		||||
  unsigned int sse;
 | 
			
		||||
  unsigned int whichdir;
 | 
			
		||||
  int thismse;
 | 
			
		||||
  unsigned int halfiters = iters_per_step;
 | 
			
		||||
  unsigned int quarteriters = iters_per_step;
 | 
			
		||||
  unsigned int eighthiters = iters_per_step;
 | 
			
		||||
 | 
			
		||||
  const int y_stride = xd->plane[0].pre[is_second].stride;
 | 
			
		||||
  const int offset = bestmv->row * y_stride + bestmv->col;
 | 
			
		||||
  const uint8_t *const y = xd->plane[0].pre[is_second].buf;
 | 
			
		||||
 | 
			
		||||
  int rr = ref_mv->row;
 | 
			
		||||
  int rc = ref_mv->col;
 | 
			
		||||
  int br = bestmv->row * 8;
 | 
			
		||||
  int bc = bestmv->col * 8;
 | 
			
		||||
  int hstep = 4;
 | 
			
		||||
  const int minc = MAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
 | 
			
		||||
  const int maxc = MIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
 | 
			
		||||
  const int minr = MAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
 | 
			
		||||
  const int maxr = MIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
 | 
			
		||||
 | 
			
		||||
  int tr = br;
 | 
			
		||||
  int tc = bc;
 | 
			
		||||
 | 
			
		||||
  // central mv
 | 
			
		||||
  bestmv->row *= 8;
 | 
			
		||||
  bestmv->col *= 8;
 | 
			
		||||
 | 
			
		||||
  // calculate central point error
 | 
			
		||||
  besterr = vfp->mvf(y + offset, y_stride, z, src_stride, mask, mask_stride,
 | 
			
		||||
                     sse1);
 | 
			
		||||
  *distortion = besterr;
 | 
			
		||||
  besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
 | 
			
		||||
 | 
			
		||||
  // 1/2 pel
 | 
			
		||||
  FIRST_LEVEL_CHECKS;
 | 
			
		||||
  if (halfiters > 1) {
 | 
			
		||||
    SECOND_LEVEL_CHECKS;
 | 
			
		||||
  }
 | 
			
		||||
  tr = br;
 | 
			
		||||
  tc = bc;
 | 
			
		||||
 | 
			
		||||
  // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
 | 
			
		||||
  if (forced_stop != 2) {
 | 
			
		||||
    hstep >>= 1;
 | 
			
		||||
    FIRST_LEVEL_CHECKS;
 | 
			
		||||
    if (quarteriters > 1) {
 | 
			
		||||
      SECOND_LEVEL_CHECKS;
 | 
			
		||||
    }
 | 
			
		||||
    tr = br;
 | 
			
		||||
    tc = bc;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (allow_hp && vp9_use_mv_hp(ref_mv) && forced_stop == 0) {
 | 
			
		||||
    hstep >>= 1;
 | 
			
		||||
    FIRST_LEVEL_CHECKS;
 | 
			
		||||
    if (eighthiters > 1) {
 | 
			
		||||
      SECOND_LEVEL_CHECKS;
 | 
			
		||||
    }
 | 
			
		||||
    tr = br;
 | 
			
		||||
    tc = bc;
 | 
			
		||||
  }
 | 
			
		||||
  // These lines insure static analysis doesn't warn that
 | 
			
		||||
  // tr and tc aren't used after the above point.
 | 
			
		||||
  (void) tr;
 | 
			
		||||
  (void) tc;
 | 
			
		||||
 | 
			
		||||
  bestmv->row = br;
 | 
			
		||||
  bestmv->col = bc;
 | 
			
		||||
 | 
			
		||||
  if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
 | 
			
		||||
      (abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
 | 
			
		||||
    return INT_MAX;
 | 
			
		||||
 | 
			
		||||
  return besterr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef DIST
 | 
			
		||||
#undef MVC
 | 
			
		||||
#undef CHECK_BETTER
 | 
			
		||||
 | 
			
		||||
int vp9_get_masked_mvpred_var(const MACROBLOCK *x,
 | 
			
		||||
                              uint8_t *mask, int mask_stride,
 | 
			
		||||
                              const MV *best_mv, const MV *center_mv,
 | 
			
		||||
                              const vp9_variance_fn_ptr_t *vfp,
 | 
			
		||||
                              int use_mvcost, int is_second) {
 | 
			
		||||
  const MACROBLOCKD *const xd = &x->e_mbd;
 | 
			
		||||
  const struct buf_2d *const what = &x->plane[0].src;
 | 
			
		||||
  const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
 | 
			
		||||
  const MV mv = {best_mv->row * 8, best_mv->col * 8};
 | 
			
		||||
  unsigned int unused;
 | 
			
		||||
 | 
			
		||||
  return vfp->mvf(what->buf, what->stride,
 | 
			
		||||
                  get_buf_from_mv(in_what, best_mv), in_what->stride,
 | 
			
		||||
                  mask, mask_stride, &unused) +
 | 
			
		||||
      (use_mvcost ?  mv_err_cost(&mv, center_mv, x->nmvjointcost,
 | 
			
		||||
                                 x->mvcost, x->errorperbit) : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_masked_refining_search_sad_c(const MACROBLOCK *x,
 | 
			
		||||
                                     uint8_t *mask, int mask_stride,
 | 
			
		||||
                                     MV *ref_mv, int error_per_bit,
 | 
			
		||||
                                     int search_range,
 | 
			
		||||
                                     const vp9_variance_fn_ptr_t *fn_ptr,
 | 
			
		||||
                                     const MV *center_mv, int is_second) {
 | 
			
		||||
  const MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
 | 
			
		||||
  const MACROBLOCKD *const xd = &x->e_mbd;
 | 
			
		||||
  const struct buf_2d *const what = &x->plane[0].src;
 | 
			
		||||
  const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
 | 
			
		||||
  const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
 | 
			
		||||
  unsigned int best_sad = fn_ptr->msdf(what->buf, what->stride,
 | 
			
		||||
                                       get_buf_from_mv(in_what, ref_mv),
 | 
			
		||||
                                       in_what->stride, mask, mask_stride) +
 | 
			
		||||
      mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
 | 
			
		||||
  int i, j;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < search_range; i++) {
 | 
			
		||||
    int best_site = -1;
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < 4; j++) {
 | 
			
		||||
      const MV mv = {ref_mv->row + neighbors[j].row,
 | 
			
		||||
                     ref_mv->col + neighbors[j].col};
 | 
			
		||||
      if (is_mv_in(x, &mv)) {
 | 
			
		||||
        unsigned int sad = fn_ptr->msdf(what->buf, what->stride,
 | 
			
		||||
            get_buf_from_mv(in_what, &mv), in_what->stride, mask, mask_stride);
 | 
			
		||||
        if (sad < best_sad) {
 | 
			
		||||
          sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
 | 
			
		||||
          if (sad < best_sad) {
 | 
			
		||||
            best_sad = sad;
 | 
			
		||||
            best_site = j;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (best_site == -1) {
 | 
			
		||||
      break;
 | 
			
		||||
    } else {
 | 
			
		||||
      ref_mv->row += neighbors[best_site].row;
 | 
			
		||||
      ref_mv->col += neighbors[best_site].col;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return best_sad;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_masked_diamond_search_sad_c(const MACROBLOCK *x,
 | 
			
		||||
                             const search_site_config *cfg,
 | 
			
		||||
                             uint8_t *mask, int mask_stride,
 | 
			
		||||
                             MV *ref_mv, MV *best_mv,
 | 
			
		||||
                             int search_param, int sad_per_bit, int *num00,
 | 
			
		||||
                             const vp9_variance_fn_ptr_t *fn_ptr,
 | 
			
		||||
                             const MV *center_mv, int is_second) {
 | 
			
		||||
  const MACROBLOCKD *const xd = &x->e_mbd;
 | 
			
		||||
  const struct buf_2d *const what = &x->plane[0].src;
 | 
			
		||||
  const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
 | 
			
		||||
  // search_param determines the length of the initial step and hence the number
 | 
			
		||||
  // of iterations
 | 
			
		||||
  // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 =
 | 
			
		||||
  // (MAX_FIRST_STEP/4) pel... etc.
 | 
			
		||||
  const search_site *const ss = &cfg->ss[search_param * cfg->searches_per_step];
 | 
			
		||||
  const int tot_steps = (cfg->ss_count / cfg->searches_per_step) - search_param;
 | 
			
		||||
  const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
 | 
			
		||||
  const uint8_t *best_address, *in_what_ref;
 | 
			
		||||
  int best_sad = INT_MAX;
 | 
			
		||||
  int best_site = 0;
 | 
			
		||||
  int last_site = 0;
 | 
			
		||||
  int i, j, step;
 | 
			
		||||
 | 
			
		||||
  clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
 | 
			
		||||
  in_what_ref = get_buf_from_mv(in_what, ref_mv);
 | 
			
		||||
  best_address = in_what_ref;
 | 
			
		||||
  *num00 = 0;
 | 
			
		||||
  *best_mv = *ref_mv;
 | 
			
		||||
 | 
			
		||||
  // Check the starting position
 | 
			
		||||
  best_sad = fn_ptr->msdf(what->buf, what->stride,
 | 
			
		||||
                         best_address, in_what->stride,
 | 
			
		||||
                         mask, mask_stride) +
 | 
			
		||||
      mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit);
 | 
			
		||||
 | 
			
		||||
  i = 1;
 | 
			
		||||
 | 
			
		||||
  for (step = 0; step < tot_steps; step++) {
 | 
			
		||||
    for (j = 0; j < cfg->searches_per_step; j++) {
 | 
			
		||||
      const MV mv = {best_mv->row + ss[i].mv.row,
 | 
			
		||||
                     best_mv->col + ss[i].mv.col};
 | 
			
		||||
      if (is_mv_in(x, &mv)) {
 | 
			
		||||
       int sad = fn_ptr->msdf(what->buf, what->stride,
 | 
			
		||||
                              best_address + ss[i].offset, in_what->stride,
 | 
			
		||||
                              mask, mask_stride);
 | 
			
		||||
        if (sad < best_sad) {
 | 
			
		||||
          sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit);
 | 
			
		||||
          if (sad < best_sad) {
 | 
			
		||||
            best_sad = sad;
 | 
			
		||||
            best_site = i;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      i++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (best_site != last_site) {
 | 
			
		||||
      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) {
 | 
			
		||||
        const MV this_mv = {best_mv->row + ss[best_site].mv.row,
 | 
			
		||||
                            best_mv->col + ss[best_site].mv.col};
 | 
			
		||||
        if (is_mv_in(x, &this_mv)) {
 | 
			
		||||
          int sad = fn_ptr->msdf(what->buf, what->stride,
 | 
			
		||||
                                 best_address + ss[best_site].offset,
 | 
			
		||||
                                 in_what->stride, mask, mask_stride);
 | 
			
		||||
          if (sad < best_sad) {
 | 
			
		||||
            sad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
 | 
			
		||||
            if (sad < best_sad) {
 | 
			
		||||
              best_sad = sad;
 | 
			
		||||
              best_mv->row += ss[best_site].mv.row;
 | 
			
		||||
              best_mv->col += ss[best_site].mv.col;
 | 
			
		||||
              best_address += ss[best_site].offset;
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
    } else if (best_address == in_what_ref) {
 | 
			
		||||
      (*num00)++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return best_sad;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_masked_full_pixel_diamond(const VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                                  uint8_t *mask, int mask_stride,
 | 
			
		||||
                                  MV *mvp_full, int step_param,
 | 
			
		||||
                                  int sadpb, int further_steps, int do_refine,
 | 
			
		||||
                                  const vp9_variance_fn_ptr_t *fn_ptr,
 | 
			
		||||
                                  const MV *ref_mv, MV *dst_mv,
 | 
			
		||||
                                  int is_second) {
 | 
			
		||||
  MV temp_mv;
 | 
			
		||||
  int thissme, n, num00 = 0;
 | 
			
		||||
  int bestsme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
 | 
			
		||||
                                                mask, mask_stride,
 | 
			
		||||
                                                mvp_full, &temp_mv,
 | 
			
		||||
                                                step_param, sadpb, &n,
 | 
			
		||||
                                                fn_ptr, ref_mv, is_second);
 | 
			
		||||
  if (bestsme < INT_MAX)
 | 
			
		||||
    bestsme = vp9_get_masked_mvpred_var(x, mask, mask_stride, &temp_mv, ref_mv,
 | 
			
		||||
                                        fn_ptr, 1, is_second);
 | 
			
		||||
  *dst_mv = temp_mv;
 | 
			
		||||
 | 
			
		||||
  // If there won't be more n-step search, check to see if refining search is
 | 
			
		||||
  // needed.
 | 
			
		||||
  if (n > further_steps)
 | 
			
		||||
    do_refine = 0;
 | 
			
		||||
 | 
			
		||||
  while (n < further_steps) {
 | 
			
		||||
    ++n;
 | 
			
		||||
 | 
			
		||||
    if (num00) {
 | 
			
		||||
      num00--;
 | 
			
		||||
    } else {
 | 
			
		||||
      thissme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
 | 
			
		||||
                                                mask, mask_stride,
 | 
			
		||||
                                                mvp_full, &temp_mv,
 | 
			
		||||
                                                step_param + n, sadpb, &num00,
 | 
			
		||||
                                                fn_ptr, ref_mv, is_second);
 | 
			
		||||
      if (thissme < INT_MAX)
 | 
			
		||||
        thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
 | 
			
		||||
                                            &temp_mv, ref_mv, fn_ptr, 1,
 | 
			
		||||
                                            is_second);
 | 
			
		||||
 | 
			
		||||
      // check to see if refining search is needed.
 | 
			
		||||
      if (num00 > further_steps - n)
 | 
			
		||||
        do_refine = 0;
 | 
			
		||||
 | 
			
		||||
      if (thissme < bestsme) {
 | 
			
		||||
        bestsme = thissme;
 | 
			
		||||
        *dst_mv = temp_mv;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // final 1-away diamond refining search
 | 
			
		||||
  if (do_refine) {
 | 
			
		||||
    const int search_range = 8;
 | 
			
		||||
    MV best_mv = *dst_mv;
 | 
			
		||||
    thissme = vp9_masked_refining_search_sad_c(x, mask, mask_stride,
 | 
			
		||||
                                               &best_mv, sadpb, search_range,
 | 
			
		||||
                                               fn_ptr, ref_mv, is_second);
 | 
			
		||||
    if (thissme < INT_MAX)
 | 
			
		||||
      thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
 | 
			
		||||
                                          &best_mv, ref_mv, fn_ptr, 1,
 | 
			
		||||
                                          is_second);
 | 
			
		||||
    if (thissme < bestsme) {
 | 
			
		||||
      bestsme = thissme;
 | 
			
		||||
      *dst_mv = best_mv;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return bestsme;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -153,6 +153,29 @@ int vp9_full_pixel_search(struct VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                          int step_param, int error_per_bit,
 | 
			
		||||
                          const MV *ref_mv, MV *tmp_mv,
 | 
			
		||||
                          int var_max, int rd);
 | 
			
		||||
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
    CONFIG_MASKED_INTERINTER)
 | 
			
		||||
int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
 | 
			
		||||
                                        uint8_t *mask, int mask_stride,
 | 
			
		||||
                                        MV *bestmv, const MV *ref_mv,
 | 
			
		||||
                                        int allow_hp,
 | 
			
		||||
                                        int error_per_bit,
 | 
			
		||||
                                        const vp9_variance_fn_ptr_t *vfp,
 | 
			
		||||
                                        int forced_stop,
 | 
			
		||||
                                        int iters_per_step,
 | 
			
		||||
                                        int *mvjcost, int *mvcost[2],
 | 
			
		||||
                                        int *distortion,
 | 
			
		||||
                                        unsigned int *sse1, int is_second);
 | 
			
		||||
int vp9_masked_full_pixel_diamond(const struct VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                                  uint8_t *mask, int mask_stride,
 | 
			
		||||
                                  MV *mvp_full, int step_param,
 | 
			
		||||
                                  int sadpb, int further_steps, int do_refine,
 | 
			
		||||
                                  const vp9_variance_fn_ptr_t *fn_ptr,
 | 
			
		||||
                                  const MV *ref_mv, MV *dst_mv,
 | 
			
		||||
                                  int is_second);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,89 @@
 | 
			
		||||
#include "vp9/common/vp9_reconintra.h"
 | 
			
		||||
 | 
			
		||||
#include "vp9/encoder/vp9_encoder.h"
 | 
			
		||||
#include "vp9/encoder/vp9_pickmode.h"
 | 
			
		||||
#include "vp9/encoder/vp9_ratectrl.h"
 | 
			
		||||
#include "vp9/encoder/vp9_rdopt.h"
 | 
			
		||||
 | 
			
		||||
static int mv_refs_rt(const VP9_COMMON *cm, const MACROBLOCKD *xd,
 | 
			
		||||
                       const TileInfo *const tile,
 | 
			
		||||
                       MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
 | 
			
		||||
                       int_mv *mv_ref_list,
 | 
			
		||||
                       int mi_row, int mi_col) {
 | 
			
		||||
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
 | 
			
		||||
  int i, refmv_count = 0;
 | 
			
		||||
 | 
			
		||||
  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
 | 
			
		||||
 | 
			
		||||
  int different_ref_found = 0;
 | 
			
		||||
  int context_counter = 0;
 | 
			
		||||
  int const_motion = 0;
 | 
			
		||||
 | 
			
		||||
  // Blank the reference vector list
 | 
			
		||||
  vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
 | 
			
		||||
 | 
			
		||||
  // The nearest 2 blocks are treated differently
 | 
			
		||||
  // if the size < 8x8 we get the mv from the bmi substructure,
 | 
			
		||||
  // and we also need to keep a mode count.
 | 
			
		||||
  for (i = 0; i < 2; ++i) {
 | 
			
		||||
    const POSITION *const mv_ref = &mv_ref_search[i];
 | 
			
		||||
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
 | 
			
		||||
      const MODE_INFO *const candidate_mi = xd->mi[mv_ref->col + mv_ref->row *
 | 
			
		||||
                                                   xd->mi_stride];
 | 
			
		||||
      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
 | 
			
		||||
      // Keep counts for entropy encoding.
 | 
			
		||||
      context_counter += mode_2_counter[candidate->mode];
 | 
			
		||||
      different_ref_found = 1;
 | 
			
		||||
 | 
			
		||||
      if (candidate->ref_frame[0] == ref_frame)
 | 
			
		||||
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, -1));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const_motion = 1;
 | 
			
		||||
 | 
			
		||||
  // Check the rest of the neighbors in much the same way
 | 
			
		||||
  // as before except we don't need to keep track of sub blocks or
 | 
			
		||||
  // mode counts.
 | 
			
		||||
  for (; i < MVREF_NEIGHBOURS && !refmv_count; ++i) {
 | 
			
		||||
    const POSITION *const mv_ref = &mv_ref_search[i];
 | 
			
		||||
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
 | 
			
		||||
      const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row *
 | 
			
		||||
                                                    xd->mi_stride]->mbmi;
 | 
			
		||||
      different_ref_found = 1;
 | 
			
		||||
 | 
			
		||||
      if (candidate->ref_frame[0] == ref_frame)
 | 
			
		||||
        ADD_MV_REF_LIST(candidate->mv[0]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Since we couldn't find 2 mvs from the same reference frame
 | 
			
		||||
  // go back through the neighbors and find motion vectors from
 | 
			
		||||
  // different reference frames.
 | 
			
		||||
  if (different_ref_found && !refmv_count) {
 | 
			
		||||
    for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
 | 
			
		||||
      const POSITION *mv_ref = &mv_ref_search[i];
 | 
			
		||||
      if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
 | 
			
		||||
        const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row
 | 
			
		||||
                                              * xd->mi_stride]->mbmi;
 | 
			
		||||
 | 
			
		||||
        // If the candidate is INTRA we don't want to consider its mv.
 | 
			
		||||
        IF_DIFF_REF_FRAME_ADD_MV(candidate);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 Done:
 | 
			
		||||
 | 
			
		||||
  mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
 | 
			
		||||
 | 
			
		||||
  // Clamp vectors
 | 
			
		||||
  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
 | 
			
		||||
    clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
 | 
			
		||||
 | 
			
		||||
  return const_motion;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void full_pixel_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                                    BLOCK_SIZE bsize, int mi_row, int mi_col,
 | 
			
		||||
                                    int_mv *tmp_mv, int *rate_mv) {
 | 
			
		||||
@@ -172,15 +252,31 @@ static void model_rd_for_sb_y(VP9_COMP *cpi, BLOCK_SIZE bsize,
 | 
			
		||||
  else
 | 
			
		||||
    x->skip_txfm = 0;
 | 
			
		||||
 | 
			
		||||
  // TODO(jingning) This is a temporary solution to account for frames with
 | 
			
		||||
  // light changes. Need to customize the rate-distortion modeling for non-RD
 | 
			
		||||
  // mode decision.
 | 
			
		||||
  if ((sse >> 3) > var)
 | 
			
		||||
    sse = var;
 | 
			
		||||
  vp9_model_rd_from_var_lapndz(var + sse, 1 << num_pels_log2_lookup[bsize],
 | 
			
		||||
                               ac_quant >> 3, &rate, &dist);
 | 
			
		||||
  *out_rate_sum = rate;
 | 
			
		||||
  vp9_model_rd_from_var_lapndz(sse - var, 1 << num_pels_log2_lookup[bsize],
 | 
			
		||||
                               dc_quant >> 3, &rate, &dist);
 | 
			
		||||
  *out_rate_sum = rate >> 1;
 | 
			
		||||
  *out_dist_sum = dist << 3;
 | 
			
		||||
 | 
			
		||||
  vp9_model_rd_from_var_lapndz(var, 1 << num_pels_log2_lookup[bsize],
 | 
			
		||||
                               ac_quant >> 3, &rate, &dist);
 | 
			
		||||
  *out_rate_sum += rate;
 | 
			
		||||
  *out_dist_sum += dist << 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_pred_buffer(PRED_BUFFER *p, int len) {
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < len; i++) {
 | 
			
		||||
    if (!p[i].in_use) {
 | 
			
		||||
      p[i].in_use = 1;
 | 
			
		||||
      return i;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_pred_buffer(PRED_BUFFER *p) {
 | 
			
		||||
  p->in_use = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO(jingning) placeholder for inter-frame non-RD mode decision.
 | 
			
		||||
@@ -228,6 +324,32 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
  int bsl = mi_width_log2_lookup[bsize];
 | 
			
		||||
  const int pred_filter_search = (((mi_row + mi_col) >> bsl) +
 | 
			
		||||
                                      get_chessboard_index(cm)) % 2;
 | 
			
		||||
  int const_motion[MAX_REF_FRAMES] = { 0 };
 | 
			
		||||
 | 
			
		||||
  // For speed 6, the result of interp filter is reused later in actual encoding
 | 
			
		||||
  // process.
 | 
			
		||||
  int bh = num_4x4_blocks_high_lookup[bsize] << 2;
 | 
			
		||||
  int bw = num_4x4_blocks_wide_lookup[bsize] << 2;
 | 
			
		||||
  int pixels_in_block = bh * bw;
 | 
			
		||||
  // tmp[3] points to dst buffer, and the other 3 point to allocated buffers.
 | 
			
		||||
  PRED_BUFFER tmp[4];
 | 
			
		||||
  DECLARE_ALIGNED_ARRAY(16, uint8_t, pred_buf, 3 * 64 * 64);
 | 
			
		||||
  struct buf_2d orig_dst = pd->dst;
 | 
			
		||||
  PRED_BUFFER *best_pred = NULL;
 | 
			
		||||
  PRED_BUFFER *this_mode_pred = NULL;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (cpi->sf.reuse_inter_pred_sby) {
 | 
			
		||||
    for (i = 0; i < 3; i++) {
 | 
			
		||||
      tmp[i].data = &pred_buf[pixels_in_block * i];
 | 
			
		||||
      tmp[i].stride = bw;
 | 
			
		||||
      tmp[i].in_use = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tmp[3].data = pd->dst.buf;
 | 
			
		||||
    tmp[3].stride = pd->dst.stride;
 | 
			
		||||
    tmp[3].in_use = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
 | 
			
		||||
 | 
			
		||||
@@ -241,18 +363,36 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
  mbmi->ref_frame[0] = NONE;
 | 
			
		||||
  mbmi->ref_frame[1] = NONE;
 | 
			
		||||
  mbmi->tx_size = MIN(max_txsize_lookup[bsize],
 | 
			
		||||
                      tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
 | 
			
		||||
  mbmi->interp_filter = cpi->common.interp_filter == SWITCHABLE ?
 | 
			
		||||
                        EIGHTTAP : cpi->common.interp_filter;
 | 
			
		||||
                      tx_mode_to_biggest_tx_size[cm->tx_mode]);
 | 
			
		||||
  mbmi->interp_filter = cm->interp_filter == SWITCHABLE ?
 | 
			
		||||
                        EIGHTTAP : cm->interp_filter;
 | 
			
		||||
  mbmi->skip = 0;
 | 
			
		||||
  mbmi->segment_id = segment_id;
 | 
			
		||||
 | 
			
		||||
  for (ref_frame = LAST_FRAME; ref_frame <= LAST_FRAME ; ++ref_frame) {
 | 
			
		||||
    x->pred_mv_sad[ref_frame] = INT_MAX;
 | 
			
		||||
    if (cpi->ref_frame_flags & flag_list[ref_frame]) {
 | 
			
		||||
      vp9_setup_buffer_inter(cpi, x, tile,
 | 
			
		||||
                             ref_frame, bsize, mi_row, mi_col,
 | 
			
		||||
                             frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
 | 
			
		||||
      const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
 | 
			
		||||
      int_mv *const candidates = mbmi->ref_mvs[ref_frame];
 | 
			
		||||
      const struct scale_factors *const sf = &cm->frame_refs[ref_frame - 1].sf;
 | 
			
		||||
      vp9_setup_pred_block(xd, yv12_mb[ref_frame], yv12, mi_row, mi_col,
 | 
			
		||||
                           sf, sf);
 | 
			
		||||
 | 
			
		||||
      if (cm->coding_use_prev_mi)
 | 
			
		||||
        vp9_find_mv_refs(cm, xd, tile, xd->mi[0], ref_frame,
 | 
			
		||||
                         candidates, mi_row, mi_col);
 | 
			
		||||
      else
 | 
			
		||||
        const_motion[ref_frame] = mv_refs_rt(cm, xd, tile, xd->mi[0],
 | 
			
		||||
                                             ref_frame, candidates,
 | 
			
		||||
                                             mi_row, mi_col);
 | 
			
		||||
 | 
			
		||||
      vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv, candidates,
 | 
			
		||||
                            &frame_mv[NEARESTMV][ref_frame],
 | 
			
		||||
                            &frame_mv[NEARMV][ref_frame]);
 | 
			
		||||
 | 
			
		||||
      if (!vp9_is_scaled(sf) && bsize >= BLOCK_8X8)
 | 
			
		||||
        vp9_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12->y_stride,
 | 
			
		||||
                    ref_frame, bsize);
 | 
			
		||||
    }
 | 
			
		||||
    frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
 | 
			
		||||
    frame_mv[ZEROMV][ref_frame].as_int = 0;
 | 
			
		||||
@@ -286,6 +426,10 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
    for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
 | 
			
		||||
      int rate_mv = 0;
 | 
			
		||||
 | 
			
		||||
      if (const_motion[ref_frame] &&
 | 
			
		||||
          (this_mode == NEARMV || this_mode == ZEROMV))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!(cpi->sf.inter_mode_mask[bsize] & (1 << this_mode)))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
@@ -324,6 +468,16 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
      // Search for the best prediction filter type, when the resulting
 | 
			
		||||
      // motion vector is at sub-pixel accuracy level for luma component, i.e.,
 | 
			
		||||
      // the last three bits are all zeros.
 | 
			
		||||
      if (cpi->sf.reuse_inter_pred_sby) {
 | 
			
		||||
        if (this_mode == NEARESTMV) {
 | 
			
		||||
          this_mode_pred = &tmp[3];
 | 
			
		||||
        } else {
 | 
			
		||||
          this_mode_pred = &tmp[get_pred_buffer(tmp, 3)];
 | 
			
		||||
          pd->dst.buf = this_mode_pred->data;
 | 
			
		||||
          pd->dst.stride = bw;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if ((this_mode == NEWMV || filter_ref == SWITCHABLE) &&
 | 
			
		||||
          pred_filter_search &&
 | 
			
		||||
          ((mbmi->mv[0].as_mv.row & 0x07) != 0 ||
 | 
			
		||||
@@ -334,6 +488,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
        unsigned int pf_sse[3];
 | 
			
		||||
        int64_t best_cost = INT64_MAX;
 | 
			
		||||
        INTERP_FILTER best_filter = SWITCHABLE, filter;
 | 
			
		||||
        PRED_BUFFER *current_pred = this_mode_pred;
 | 
			
		||||
 | 
			
		||||
        for (filter = EIGHTTAP; filter <= EIGHTTAP_SHARP; ++filter) {
 | 
			
		||||
          int64_t cost;
 | 
			
		||||
@@ -345,12 +500,28 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                        vp9_get_switchable_rate(cpi) + pf_rate[filter],
 | 
			
		||||
                        pf_dist[filter]);
 | 
			
		||||
          if (cost < best_cost) {
 | 
			
		||||
              best_filter = filter;
 | 
			
		||||
              best_cost = cost;
 | 
			
		||||
              skip_txfm = x->skip_txfm;
 | 
			
		||||
            best_filter = filter;
 | 
			
		||||
            best_cost = cost;
 | 
			
		||||
            skip_txfm = x->skip_txfm;
 | 
			
		||||
 | 
			
		||||
            if (cpi->sf.reuse_inter_pred_sby) {
 | 
			
		||||
              if (this_mode_pred != current_pred) {
 | 
			
		||||
                free_pred_buffer(this_mode_pred);
 | 
			
		||||
                this_mode_pred = current_pred;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              if (filter < EIGHTTAP_SHARP) {
 | 
			
		||||
                current_pred = &tmp[get_pred_buffer(tmp, 3)];
 | 
			
		||||
                pd->dst.buf = current_pred->data;
 | 
			
		||||
                pd->dst.stride = bw;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cpi->sf.reuse_inter_pred_sby && this_mode_pred != current_pred)
 | 
			
		||||
          free_pred_buffer(current_pred);
 | 
			
		||||
 | 
			
		||||
        mbmi->interp_filter = best_filter;
 | 
			
		||||
        rate = pf_rate[mbmi->interp_filter];
 | 
			
		||||
        dist = pf_dist[mbmi->interp_filter];
 | 
			
		||||
@@ -370,31 +541,35 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
 | 
			
		||||
      // Skipping checking: test to see if this block can be reconstructed by
 | 
			
		||||
      // prediction only.
 | 
			
		||||
      if (!x->in_active_map) {
 | 
			
		||||
        x->skip = 1;
 | 
			
		||||
      } else if (cpi->allow_encode_breakout && x->encode_breakout) {
 | 
			
		||||
      if (cpi->allow_encode_breakout) {
 | 
			
		||||
        const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
 | 
			
		||||
        unsigned int var = var_y, sse = sse_y;
 | 
			
		||||
        // Skipping threshold for ac.
 | 
			
		||||
        unsigned int thresh_ac;
 | 
			
		||||
        // Skipping threshold for dc.
 | 
			
		||||
        unsigned int thresh_dc;
 | 
			
		||||
        // Set a maximum for threshold to avoid big PSNR loss in low bit rate
 | 
			
		||||
        // case. Use extreme low threshold for static frames to limit skipping.
 | 
			
		||||
        const unsigned int max_thresh = 36000;
 | 
			
		||||
        // The encode_breakout input
 | 
			
		||||
        const unsigned int min_thresh =
 | 
			
		||||
            MIN(((unsigned int)x->encode_breakout << 4), max_thresh);
 | 
			
		||||
        if (x->encode_breakout > 0) {
 | 
			
		||||
          // Set a maximum for threshold to avoid big PSNR loss in low bit rate
 | 
			
		||||
          // case. Use extreme low threshold for static frames to limit
 | 
			
		||||
          // skipping.
 | 
			
		||||
          const unsigned int max_thresh = 36000;
 | 
			
		||||
          // The encode_breakout input
 | 
			
		||||
          const unsigned int min_thresh =
 | 
			
		||||
              MIN(((unsigned int)x->encode_breakout << 4), max_thresh);
 | 
			
		||||
 | 
			
		||||
        // Calculate threshold according to dequant value.
 | 
			
		||||
        thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
 | 
			
		||||
        thresh_ac = clamp(thresh_ac, min_thresh, max_thresh);
 | 
			
		||||
          // Calculate threshold according to dequant value.
 | 
			
		||||
          thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
 | 
			
		||||
          thresh_ac = clamp(thresh_ac, min_thresh, max_thresh);
 | 
			
		||||
 | 
			
		||||
        // Adjust ac threshold according to partition size.
 | 
			
		||||
        thresh_ac >>= 8 - (b_width_log2_lookup[bsize] +
 | 
			
		||||
            b_height_log2_lookup[bsize]);
 | 
			
		||||
          // Adjust ac threshold according to partition size.
 | 
			
		||||
          thresh_ac >>=
 | 
			
		||||
              8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
 | 
			
		||||
 | 
			
		||||
        thresh_dc = (xd->plane[0].dequant[0] * xd->plane[0].dequant[0] >> 6);
 | 
			
		||||
          thresh_dc = (xd->plane[0].dequant[0] * xd->plane[0].dequant[0] >> 6);
 | 
			
		||||
        } else {
 | 
			
		||||
          thresh_ac = 0;
 | 
			
		||||
          thresh_dc = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Y skipping condition checking for ac and dc.
 | 
			
		||||
        if (var <= thresh_ac && (sse - var) <= thresh_dc) {
 | 
			
		||||
@@ -451,6 +626,16 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
        best_pred_filter = mbmi->interp_filter;
 | 
			
		||||
        best_ref_frame = ref_frame;
 | 
			
		||||
        skip_txfm = x->skip_txfm;
 | 
			
		||||
 | 
			
		||||
        if (cpi->sf.reuse_inter_pred_sby) {
 | 
			
		||||
          if (best_pred != NULL)
 | 
			
		||||
            free_pred_buffer(best_pred);
 | 
			
		||||
 | 
			
		||||
          best_pred = this_mode_pred;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        if (cpi->sf.reuse_inter_pred_sby)
 | 
			
		||||
          free_pred_buffer(this_mode_pred);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (x->skip)
 | 
			
		||||
@@ -458,6 +643,19 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If best prediction is not in dst buf, then copy the prediction block from
 | 
			
		||||
  // temp buf to dst buf.
 | 
			
		||||
  if (cpi->sf.reuse_inter_pred_sby && best_pred->data != orig_dst.buf) {
 | 
			
		||||
    uint8_t *copy_from, *copy_to;
 | 
			
		||||
 | 
			
		||||
    pd->dst = orig_dst;
 | 
			
		||||
    copy_to = pd->dst.buf;
 | 
			
		||||
 | 
			
		||||
    copy_from = best_pred->data;
 | 
			
		||||
 | 
			
		||||
    vp9_convolve_copy(copy_from, bw, copy_to, pd->dst.stride, NULL, 0, NULL, 0,
 | 
			
		||||
                      bw, bh);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mbmi->mode = best_mode;
 | 
			
		||||
  mbmi->interp_filter = best_pred_filter;
 | 
			
		||||
@@ -469,18 +667,51 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
  // Perform intra prediction search, if the best SAD is above a certain
 | 
			
		||||
  // threshold.
 | 
			
		||||
  if (!x->skip && best_rd > inter_mode_thresh &&
 | 
			
		||||
      bsize < cpi->sf.max_intra_bsize) {
 | 
			
		||||
    for (this_mode = DC_PRED; this_mode <= DC_PRED; ++this_mode) {
 | 
			
		||||
      vp9_predict_intra_block(xd, 0, b_width_log2(bsize),
 | 
			
		||||
                              mbmi->tx_size, this_mode,
 | 
			
		||||
                              &p->src.buf[0], p->src.stride,
 | 
			
		||||
                              &pd->dst.buf[0], pd->dst.stride, 0, 0, 0);
 | 
			
		||||
      bsize <= cpi->sf.max_intra_bsize) {
 | 
			
		||||
    int i, j;
 | 
			
		||||
    const int step   = 1 << mbmi->tx_size;
 | 
			
		||||
    const int width  = num_4x4_blocks_wide_lookup[bsize];
 | 
			
		||||
    const int height = num_4x4_blocks_high_lookup[bsize];
 | 
			
		||||
 | 
			
		||||
    int rate2 = 0;
 | 
			
		||||
    int64_t dist2 = 0;
 | 
			
		||||
    const int dst_stride = pd->dst.stride;
 | 
			
		||||
    const int src_stride = p->src.stride;
 | 
			
		||||
    int block_idx = 0;
 | 
			
		||||
 | 
			
		||||
    for (this_mode = DC_PRED; this_mode <= DC_PRED; ++this_mode) {
 | 
			
		||||
      if (cpi->sf.reuse_inter_pred_sby) {
 | 
			
		||||
        pd->dst.buf = tmp[0].data;
 | 
			
		||||
        pd->dst.stride = bw;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < height; j += step) {
 | 
			
		||||
        for (i = 0; i < width; i += step) {
 | 
			
		||||
          vp9_predict_intra_block(xd, block_idx, b_width_log2(bsize),
 | 
			
		||||
                                  mbmi->tx_size, this_mode,
 | 
			
		||||
#if CONFIG_FILTERINTRA
 | 
			
		||||
                                  0,
 | 
			
		||||
#endif
 | 
			
		||||
                                  &p->src.buf[4 * (j * dst_stride + i)],
 | 
			
		||||
                                  src_stride,
 | 
			
		||||
                                  &pd->dst.buf[4 * (j * dst_stride + i)],
 | 
			
		||||
                                  dst_stride, i, j, 0);
 | 
			
		||||
          model_rd_for_sb_y(cpi, bsize, x, xd, &rate, &dist, &var_y, &sse_y);
 | 
			
		||||
          rate2 += rate;
 | 
			
		||||
          dist2 += dist;
 | 
			
		||||
          ++block_idx;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      rate = rate2;
 | 
			
		||||
      dist = dist2;
 | 
			
		||||
 | 
			
		||||
      model_rd_for_sb_y(cpi, bsize, x, xd, &rate, &dist, &var_y, &sse_y);
 | 
			
		||||
      rate += cpi->mbmode_cost[this_mode];
 | 
			
		||||
      rate += intra_cost_penalty;
 | 
			
		||||
      this_rd = RDCOST(x->rdmult, x->rddiv, rate, dist);
 | 
			
		||||
 | 
			
		||||
      if (cpi->sf.reuse_inter_pred_sby)
 | 
			
		||||
        pd->dst = orig_dst;
 | 
			
		||||
 | 
			
		||||
      if (this_rd + intra_mode_cost < best_rd) {
 | 
			
		||||
        best_rd = this_rd;
 | 
			
		||||
        *returnrate = rate;
 | 
			
		||||
@@ -494,9 +725,9 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if CONFIG_DENOISING
 | 
			
		||||
  vp9_denoiser_denoise(&cpi->denoiser, x, cpi->common.mi_grid_visible, mi_row,
 | 
			
		||||
                       mi_col, bsize);
 | 
			
		||||
  vp9_denoiser_denoise(&cpi->denoiser, x, mi_row, mi_col, bsize);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  return INT64_MAX;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,12 @@
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint8_t *data;
 | 
			
		||||
  int stride;
 | 
			
		||||
  int in_use;
 | 
			
		||||
} PRED_BUFFER;
 | 
			
		||||
 | 
			
		||||
int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                            const struct TileInfo *const tile,
 | 
			
		||||
                            int mi_row, int mi_col,
 | 
			
		||||
 
 | 
			
		||||
@@ -186,6 +186,8 @@ static void update_buffer_level(VP9_COMP *cpi, int encoded_frame_size) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (pass == 0 && oxcf->rc_mode == VPX_CBR) {
 | 
			
		||||
    rc->avg_frame_qindex[KEY_FRAME] = oxcf->worst_allowed_q;
 | 
			
		||||
    rc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q;
 | 
			
		||||
@@ -227,9 +229,9 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
 | 
			
		||||
  rc->tot_q = 0.0;
 | 
			
		||||
  rc->avg_q = vp9_convert_qindex_to_q(oxcf->worst_allowed_q);
 | 
			
		||||
 | 
			
		||||
  rc->rate_correction_factor = 1.0;
 | 
			
		||||
  rc->key_frame_rate_correction_factor = 1.0;
 | 
			
		||||
  rc->gf_rate_correction_factor = 1.0;
 | 
			
		||||
  for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
 | 
			
		||||
    rc->rate_correction_factors[i] = 1.0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_rc_drop_frame(VP9_COMP *cpi) {
 | 
			
		||||
@@ -271,28 +273,40 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double get_rate_correction_factor(const VP9_COMP *cpi) {
 | 
			
		||||
  const RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
 | 
			
		||||
  if (cpi->common.frame_type == KEY_FRAME) {
 | 
			
		||||
    return cpi->rc.key_frame_rate_correction_factor;
 | 
			
		||||
    return rc->rate_correction_factors[KF_STD];
 | 
			
		||||
  } else if (cpi->pass == 2) {
 | 
			
		||||
    RATE_FACTOR_LEVEL rf_lvl =
 | 
			
		||||
      cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index];
 | 
			
		||||
    return rc->rate_correction_factors[rf_lvl];
 | 
			
		||||
  } else {
 | 
			
		||||
    if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
 | 
			
		||||
        !cpi->rc.is_src_frame_alt_ref &&
 | 
			
		||||
        !rc->is_src_frame_alt_ref &&
 | 
			
		||||
        !(cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR))
 | 
			
		||||
      return cpi->rc.gf_rate_correction_factor;
 | 
			
		||||
      return rc->rate_correction_factors[GF_ARF_STD];
 | 
			
		||||
    else
 | 
			
		||||
      return cpi->rc.rate_correction_factor;
 | 
			
		||||
      return rc->rate_correction_factors[INTER_NORMAL];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_rate_correction_factor(VP9_COMP *cpi, double factor) {
 | 
			
		||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
 | 
			
		||||
  if (cpi->common.frame_type == KEY_FRAME) {
 | 
			
		||||
    cpi->rc.key_frame_rate_correction_factor = factor;
 | 
			
		||||
    rc->rate_correction_factors[KF_STD] = factor;
 | 
			
		||||
  } else if (cpi->pass == 2) {
 | 
			
		||||
    RATE_FACTOR_LEVEL rf_lvl =
 | 
			
		||||
      cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index];
 | 
			
		||||
    rc->rate_correction_factors[rf_lvl] = factor;
 | 
			
		||||
  } else {
 | 
			
		||||
    if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
 | 
			
		||||
        !cpi->rc.is_src_frame_alt_ref &&
 | 
			
		||||
        !rc->is_src_frame_alt_ref &&
 | 
			
		||||
        !(cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR))
 | 
			
		||||
      cpi->rc.gf_rate_correction_factor = factor;
 | 
			
		||||
      rc->rate_correction_factors[GF_ARF_STD] = factor;
 | 
			
		||||
    else
 | 
			
		||||
      cpi->rc.rate_correction_factor = factor;
 | 
			
		||||
      rc->rate_correction_factors[INTER_NORMAL] = factor;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -628,8 +642,8 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
 | 
			
		||||
 | 
			
		||||
  if (frame_is_intra_only(cm)) {
 | 
			
		||||
    active_best_quality = rc->best_quality;
 | 
			
		||||
#if !CONFIG_MULTIPLE_ARF
 | 
			
		||||
    // Handle the special case for key frames forced when we have75 reached
 | 
			
		||||
 | 
			
		||||
    // Handle the special case for key frames forced when we have reached
 | 
			
		||||
    // the maximum key frame interval. Here force the Q to a range
 | 
			
		||||
    // based on the ambient Q to reduce the risk of popping.
 | 
			
		||||
    if (rc->this_key_frame_forced) {
 | 
			
		||||
@@ -660,13 +674,6 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
 | 
			
		||||
      active_best_quality += vp9_compute_qdelta(rc, q_val,
 | 
			
		||||
                                                q_val * q_adj_factor);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    double current_q;
 | 
			
		||||
    // Force the KF quantizer to be 30% of the active_worst_quality.
 | 
			
		||||
    current_q = vp9_convert_qindex_to_q(active_worst_quality);
 | 
			
		||||
    active_best_quality = active_worst_quality
 | 
			
		||||
        + vp9_compute_qdelta(rc, current_q, current_q * 0.3);
 | 
			
		||||
#endif
 | 
			
		||||
  } else if (!rc->is_src_frame_alt_ref &&
 | 
			
		||||
             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
 | 
			
		||||
    // Use the lower of active_worst_quality and recent
 | 
			
		||||
@@ -768,23 +775,7 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
 | 
			
		||||
        q = *top_index;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  // Force the quantizer determined by the coding order pattern.
 | 
			
		||||
  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
 | 
			
		||||
      cpi->oxcf.rc_mode != VPX_Q) {
 | 
			
		||||
    double new_q;
 | 
			
		||||
    double current_q = vp9_convert_qindex_to_q(active_worst_quality);
 | 
			
		||||
    int level = cpi->this_frame_weight;
 | 
			
		||||
    assert(level >= 0);
 | 
			
		||||
    new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
 | 
			
		||||
    q = active_worst_quality +
 | 
			
		||||
        vp9_compute_qdelta(rc, current_q, new_q);
 | 
			
		||||
 | 
			
		||||
    *bottom_index = q;
 | 
			
		||||
    *top_index    = q;
 | 
			
		||||
    printf("frame:%d q:%d\n", cm->current_video_frame, q);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  assert(*top_index <= rc->worst_quality &&
 | 
			
		||||
         *top_index >= rc->best_quality);
 | 
			
		||||
  assert(*bottom_index <= rc->worst_quality &&
 | 
			
		||||
@@ -805,7 +796,6 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
 | 
			
		||||
  int q;
 | 
			
		||||
 | 
			
		||||
  if (frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi)) {
 | 
			
		||||
#if !CONFIG_MULTIPLE_ARF
 | 
			
		||||
    // Handle the special case for key frames forced when we have75 reached
 | 
			
		||||
    // the maximum key frame interval. Here force the Q to a range
 | 
			
		||||
    // based on the ambient Q to reduce the risk of popping.
 | 
			
		||||
@@ -840,13 +830,6 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
 | 
			
		||||
      active_best_quality += vp9_compute_qdelta(rc, q_val,
 | 
			
		||||
                                                q_val * q_adj_factor);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    double current_q;
 | 
			
		||||
    // Force the KF quantizer to be 30% of the active_worst_quality.
 | 
			
		||||
    current_q = vp9_convert_qindex_to_q(active_worst_quality);
 | 
			
		||||
    active_best_quality = active_worst_quality
 | 
			
		||||
        + vp9_compute_qdelta(rc, current_q, current_q * 0.3);
 | 
			
		||||
#endif
 | 
			
		||||
  } else if (!rc->is_src_frame_alt_ref &&
 | 
			
		||||
             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
 | 
			
		||||
    // Use the lower of active_worst_quality and recent
 | 
			
		||||
@@ -909,21 +892,20 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
 | 
			
		||||
  *bottom_index = active_best_quality;
 | 
			
		||||
 | 
			
		||||
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
 | 
			
		||||
  vp9_clear_system_state();
 | 
			
		||||
  {
 | 
			
		||||
    int qdelta = 0;
 | 
			
		||||
    vp9_clear_system_state();
 | 
			
		||||
 | 
			
		||||
    // Limit Q range for the adaptive loop.
 | 
			
		||||
    if ((cm->frame_type == KEY_FRAME || vp9_is_upper_layer_key_frame(cpi)) &&
 | 
			
		||||
        !rc->this_key_frame_forced) {
 | 
			
		||||
      qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
 | 
			
		||||
                                          active_worst_quality, 2.0);
 | 
			
		||||
    } else if (!rc->is_src_frame_alt_ref &&
 | 
			
		||||
               (oxcf->rc_mode != VPX_CBR) &&
 | 
			
		||||
               (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
 | 
			
		||||
      qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
 | 
			
		||||
                                          active_worst_quality, 1.75);
 | 
			
		||||
    }
 | 
			
		||||
    const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
 | 
			
		||||
    const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
 | 
			
		||||
      1.00,  // INTER_NORMAL
 | 
			
		||||
      1.00,  // INTER_HIGH
 | 
			
		||||
      1.50,  // GF_ARF_LOW
 | 
			
		||||
      1.75,  // GF_ARF_STD
 | 
			
		||||
      2.00,  // KF_STD
 | 
			
		||||
    };
 | 
			
		||||
    const double rate_factor =
 | 
			
		||||
      rate_factor_deltas[gf_group->rf_level[gf_group->index]];
 | 
			
		||||
    int qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
 | 
			
		||||
                                            active_worst_quality, rate_factor);
 | 
			
		||||
    *top_index = active_worst_quality + qdelta;
 | 
			
		||||
    *top_index = (*top_index > *bottom_index) ? *top_index : *bottom_index;
 | 
			
		||||
  }
 | 
			
		||||
@@ -945,23 +927,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
 | 
			
		||||
        q = *top_index;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  // Force the quantizer determined by the coding order pattern.
 | 
			
		||||
  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
 | 
			
		||||
      cpi->oxcf.rc_mode != VPX_Q) {
 | 
			
		||||
    double new_q;
 | 
			
		||||
    double current_q = vp9_convert_qindex_to_q(active_worst_quality);
 | 
			
		||||
    int level = cpi->this_frame_weight;
 | 
			
		||||
    assert(level >= 0);
 | 
			
		||||
    new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
 | 
			
		||||
    q = active_worst_quality +
 | 
			
		||||
        vp9_compute_qdelta(rc, current_q, new_q);
 | 
			
		||||
 | 
			
		||||
    *bottom_index = q;
 | 
			
		||||
    *top_index    = q;
 | 
			
		||||
    printf("frame:%d q:%d\n", cm->current_video_frame, q);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  assert(*top_index <= rc->worst_quality &&
 | 
			
		||||
         *top_index >= rc->best_quality);
 | 
			
		||||
  assert(*bottom_index <= rc->worst_quality &&
 | 
			
		||||
@@ -1026,11 +992,8 @@ static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
 | 
			
		||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
			
		||||
  rc->frames_since_golden = 0;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MULTIPLE_ARF
 | 
			
		||||
  if (!cpi->multi_arf_enabled)
 | 
			
		||||
#endif
 | 
			
		||||
    // Clear the alternate reference update pending flag.
 | 
			
		||||
    rc->source_alt_ref_pending = 0;
 | 
			
		||||
  // Mark the alt ref as done (setting to 0 means no further alt refs pending).
 | 
			
		||||
  rc->source_alt_ref_pending = 0;
 | 
			
		||||
 | 
			
		||||
  // Set the alternate reference frame active flag
 | 
			
		||||
  rc->source_alt_ref_active = 1;
 | 
			
		||||
@@ -1044,8 +1007,13 @@ static void update_golden_frame_stats(VP9_COMP *cpi) {
 | 
			
		||||
    // this frame refreshes means next frames don't unless specified by user
 | 
			
		||||
    rc->frames_since_golden = 0;
 | 
			
		||||
 | 
			
		||||
    if (!rc->source_alt_ref_pending)
 | 
			
		||||
    if (cpi->pass == 2) {
 | 
			
		||||
      if (!rc->source_alt_ref_pending &&
 | 
			
		||||
          cpi->twopass.gf_group.rf_level[0] == GF_ARF_STD)
 | 
			
		||||
      rc->source_alt_ref_active = 0;
 | 
			
		||||
    } else if (!rc->source_alt_ref_pending) {
 | 
			
		||||
      rc->source_alt_ref_active = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Decrement count down till next gf
 | 
			
		||||
    if (rc->frames_till_gf_update_due > 0)
 | 
			
		||||
@@ -1388,6 +1356,8 @@ void vp9_rc_set_gf_max_interval(const VP9EncoderConfig *const oxcf,
 | 
			
		||||
 | 
			
		||||
  // Extended interval for genuinely static scenes
 | 
			
		||||
  rc->static_scene_max_gf_interval = oxcf->key_freq >> 1;
 | 
			
		||||
  if (rc->static_scene_max_gf_interval > (MAX_LAG_BUFFERS * 2))
 | 
			
		||||
    rc->static_scene_max_gf_interval = MAX_LAG_BUFFERS * 2;
 | 
			
		||||
 | 
			
		||||
  if (is_altref_enabled(oxcf)) {
 | 
			
		||||
    if (rc->static_scene_max_gf_interval > oxcf->lag_in_frames - 1)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,15 @@ extern "C" {
 | 
			
		||||
// Bits Per MB at different Q (Multiplied by 512)
 | 
			
		||||
#define BPER_MB_NORMBITS    9
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  INTER_NORMAL = 0,
 | 
			
		||||
  INTER_HIGH = 1,
 | 
			
		||||
  GF_ARF_LOW = 2,
 | 
			
		||||
  GF_ARF_STD = 3,
 | 
			
		||||
  KF_STD = 4,
 | 
			
		||||
  RATE_FACTOR_LEVELS = 5
 | 
			
		||||
} RATE_FACTOR_LEVEL;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  // Rate targetting variables
 | 
			
		||||
  int base_frame_target;           // A baseline frame target before adjustment
 | 
			
		||||
@@ -37,9 +46,7 @@ typedef struct {
 | 
			
		||||
  int last_boost;
 | 
			
		||||
  int kf_boost;
 | 
			
		||||
 | 
			
		||||
  double rate_correction_factor;
 | 
			
		||||
  double key_frame_rate_correction_factor;
 | 
			
		||||
  double gf_rate_correction_factor;
 | 
			
		||||
  double rate_correction_factors[RATE_FACTOR_LEVELS];
 | 
			
		||||
 | 
			
		||||
  int frames_since_golden;
 | 
			
		||||
  int frames_till_gf_update_due;
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -13,7 +13,10 @@
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
#include "vp9/encoder/vp9_encoder.h"
 | 
			
		||||
#include "vp9/common/vp9_blockd.h"
 | 
			
		||||
 | 
			
		||||
#include "vp9/encoder/vp9_block.h"
 | 
			
		||||
#include "vp9/encoder/vp9_context_tree.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
@@ -30,21 +33,125 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
#define INVALID_MV 0x80008000
 | 
			
		||||
 | 
			
		||||
#if !CONFIG_INTERINTRA
 | 
			
		||||
#define MAX_MODES 30
 | 
			
		||||
#else
 | 
			
		||||
#define MAX_MODES 42
 | 
			
		||||
#endif
 | 
			
		||||
#define MAX_REFS  6
 | 
			
		||||
 | 
			
		||||
// This enumerator type needs to be kept aligned with the mode order in
 | 
			
		||||
// const MODE_DEFINITION vp9_mode_order[MAX_MODES] used in the rd code.
 | 
			
		||||
typedef enum {
 | 
			
		||||
  THR_NEARESTMV,
 | 
			
		||||
  THR_NEARESTA,
 | 
			
		||||
  THR_NEARESTG,
 | 
			
		||||
 | 
			
		||||
  THR_DC,
 | 
			
		||||
 | 
			
		||||
  THR_NEWMV,
 | 
			
		||||
  THR_NEWA,
 | 
			
		||||
  THR_NEWG,
 | 
			
		||||
 | 
			
		||||
  THR_NEARMV,
 | 
			
		||||
  THR_NEARA,
 | 
			
		||||
  THR_COMP_NEARESTLA,
 | 
			
		||||
  THR_COMP_NEARESTGA,
 | 
			
		||||
 | 
			
		||||
  THR_TM,
 | 
			
		||||
 | 
			
		||||
  THR_COMP_NEARLA,
 | 
			
		||||
  THR_COMP_NEWLA,
 | 
			
		||||
  THR_NEARG,
 | 
			
		||||
  THR_COMP_NEARGA,
 | 
			
		||||
  THR_COMP_NEWGA,
 | 
			
		||||
 | 
			
		||||
  THR_ZEROMV,
 | 
			
		||||
  THR_ZEROG,
 | 
			
		||||
  THR_ZEROA,
 | 
			
		||||
  THR_COMP_ZEROLA,
 | 
			
		||||
  THR_COMP_ZEROGA,
 | 
			
		||||
 | 
			
		||||
  THR_H_PRED,
 | 
			
		||||
  THR_V_PRED,
 | 
			
		||||
  THR_D135_PRED,
 | 
			
		||||
  THR_D207_PRED,
 | 
			
		||||
  THR_D153_PRED,
 | 
			
		||||
  THR_D63_PRED,
 | 
			
		||||
  THR_D117_PRED,
 | 
			
		||||
  THR_D45_PRED,
 | 
			
		||||
 | 
			
		||||
#if CONFIG_INTERINTRA
 | 
			
		||||
  THR_COMP_INTERINTRA_ZEROL,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEARESTL,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEARL,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEWL,
 | 
			
		||||
 | 
			
		||||
  THR_COMP_INTERINTRA_ZEROG,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEARESTG,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEARG,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEWG,
 | 
			
		||||
 | 
			
		||||
  THR_COMP_INTERINTRA_ZEROA,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEARESTA,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEARA,
 | 
			
		||||
  THR_COMP_INTERINTRA_NEWA,
 | 
			
		||||
#endif
 | 
			
		||||
} THR_MODES;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  THR_LAST,
 | 
			
		||||
  THR_GOLD,
 | 
			
		||||
  THR_ALTR,
 | 
			
		||||
  THR_COMP_LA,
 | 
			
		||||
  THR_COMP_GA,
 | 
			
		||||
  THR_INTRA,
 | 
			
		||||
} THR_MODES_SUB8X8;
 | 
			
		||||
 | 
			
		||||
typedef struct RD_OPT {
 | 
			
		||||
  // Thresh_mult is used to set a threshold for the rd score. A higher value
 | 
			
		||||
  // means that we will accept the best mode so far more often. This number
 | 
			
		||||
  // is used in combination with the current block size, and thresh_freq_fact
 | 
			
		||||
  // to pick a threshold.
 | 
			
		||||
  int thresh_mult[MAX_MODES];
 | 
			
		||||
  int thresh_mult_sub8x8[MAX_REFS];
 | 
			
		||||
 | 
			
		||||
  int threshes[MAX_SEGMENTS][BLOCK_SIZES][MAX_MODES];
 | 
			
		||||
  int thresh_freq_fact[BLOCK_SIZES][MAX_MODES];
 | 
			
		||||
 | 
			
		||||
  int64_t comp_pred_diff[REFERENCE_MODES];
 | 
			
		||||
  int64_t prediction_type_threshes[MAX_REF_FRAMES][REFERENCE_MODES];
 | 
			
		||||
  int64_t tx_select_diff[TX_MODES];
 | 
			
		||||
  // FIXME(rbultje) can this overflow?
 | 
			
		||||
  int tx_select_threshes[MAX_REF_FRAMES][TX_MODES];
 | 
			
		||||
 | 
			
		||||
  int64_t filter_diff[SWITCHABLE_FILTER_CONTEXTS];
 | 
			
		||||
  int64_t filter_threshes[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
 | 
			
		||||
  int64_t filter_cache[SWITCHABLE_FILTER_CONTEXTS];
 | 
			
		||||
  int64_t mask_filter;
 | 
			
		||||
 | 
			
		||||
  int RDMULT;
 | 
			
		||||
  int RDDIV;
 | 
			
		||||
} RD_OPT;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct TileInfo;
 | 
			
		||||
struct VP9_COMP;
 | 
			
		||||
struct macroblock;
 | 
			
		||||
 | 
			
		||||
int vp9_compute_rd_mult(const VP9_COMP *cpi, int qindex);
 | 
			
		||||
int vp9_compute_rd_mult(const struct VP9_COMP *cpi, int qindex);
 | 
			
		||||
 | 
			
		||||
void vp9_initialize_rd_consts(VP9_COMP *cpi);
 | 
			
		||||
void vp9_initialize_rd_consts(struct VP9_COMP *cpi);
 | 
			
		||||
 | 
			
		||||
void vp9_initialize_me_consts(VP9_COMP *cpi, int qindex);
 | 
			
		||||
void vp9_initialize_me_consts(struct VP9_COMP *cpi, int qindex);
 | 
			
		||||
 | 
			
		||||
void vp9_model_rd_from_var_lapndz(unsigned int var, unsigned int n,
 | 
			
		||||
                                  unsigned int qstep, int *rate,
 | 
			
		||||
                                  int64_t *dist);
 | 
			
		||||
 | 
			
		||||
int vp9_get_switchable_rate(const VP9_COMP *cpi);
 | 
			
		||||
int vp9_get_switchable_rate(const struct VP9_COMP *cpi);
 | 
			
		||||
 | 
			
		||||
void vp9_setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
void vp9_setup_buffer_inter(struct VP9_COMP *cpi, struct macroblock *x,
 | 
			
		||||
                            const TileInfo *const tile,
 | 
			
		||||
                            MV_REFERENCE_FRAME ref_frame,
 | 
			
		||||
                            BLOCK_SIZE block_size,
 | 
			
		||||
@@ -53,26 +160,43 @@ void vp9_setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                            int_mv frame_near_mv[MAX_REF_FRAMES],
 | 
			
		||||
                            struct buf_2d yv12_mb[4][MAX_MB_PLANE]);
 | 
			
		||||
 | 
			
		||||
const YV12_BUFFER_CONFIG *vp9_get_scaled_ref_frame(const VP9_COMP *cpi,
 | 
			
		||||
const YV12_BUFFER_CONFIG *vp9_get_scaled_ref_frame(const struct VP9_COMP *cpi,
 | 
			
		||||
                                                   int ref_frame);
 | 
			
		||||
 | 
			
		||||
void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
void vp9_rd_pick_intra_mode_sb(struct VP9_COMP *cpi, struct macroblock *x,
 | 
			
		||||
                               int *r, int64_t *d, BLOCK_SIZE bsize,
 | 
			
		||||
                               PICK_MODE_CONTEXT *ctx, int64_t best_rd);
 | 
			
		||||
 | 
			
		||||
int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
int64_t vp9_rd_pick_inter_mode_sb(struct VP9_COMP *cpi, struct macroblock *x,
 | 
			
		||||
                                  const struct TileInfo *const tile,
 | 
			
		||||
                                  int mi_row, int mi_col,
 | 
			
		||||
                                  int *returnrate,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                                  int *returnrate_nocoef,
 | 
			
		||||
#endif
 | 
			
		||||
                                  int64_t *returndistortion,
 | 
			
		||||
                                  BLOCK_SIZE bsize,
 | 
			
		||||
                                  PICK_MODE_CONTEXT *ctx,
 | 
			
		||||
                                  int64_t best_rd_so_far);
 | 
			
		||||
 | 
			
		||||
int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
int64_t vp9_rd_pick_inter_mode_sb_seg_skip(struct VP9_COMP *cpi,
 | 
			
		||||
                                           struct macroblock *x,
 | 
			
		||||
                                           const TileInfo *const tile,
 | 
			
		||||
                                           int mi_row, int mi_col,
 | 
			
		||||
                                           int *returnrate,
 | 
			
		||||
                                           int64_t *returndistortion,
 | 
			
		||||
                                           BLOCK_SIZE bsize,
 | 
			
		||||
                                           PICK_MODE_CONTEXT *ctx,
 | 
			
		||||
                                           int64_t best_rd_so_far);
 | 
			
		||||
 | 
			
		||||
int64_t vp9_rd_pick_inter_mode_sub8x8(struct VP9_COMP *cpi,
 | 
			
		||||
                                      struct macroblock *x,
 | 
			
		||||
                                      const struct TileInfo *const tile,
 | 
			
		||||
                                      int mi_row, int mi_col,
 | 
			
		||||
                                      int *returnrate,
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
                                      int *returnrate_nocoef,
 | 
			
		||||
#endif
 | 
			
		||||
                                      int64_t *returndistortion,
 | 
			
		||||
                                      BLOCK_SIZE bsize,
 | 
			
		||||
                                      PICK_MODE_CONTEXT *ctx,
 | 
			
		||||
@@ -85,15 +209,40 @@ void vp9_get_entropy_contexts(BLOCK_SIZE bsize, TX_SIZE tx_size,
 | 
			
		||||
                              ENTROPY_CONTEXT t_above[16],
 | 
			
		||||
                              ENTROPY_CONTEXT t_left[16]);
 | 
			
		||||
 | 
			
		||||
void vp9_set_rd_speed_thresholds(VP9_COMP *cpi);
 | 
			
		||||
void vp9_set_rd_speed_thresholds(struct VP9_COMP *cpi);
 | 
			
		||||
 | 
			
		||||
void vp9_set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi);
 | 
			
		||||
void vp9_set_rd_speed_thresholds_sub8x8(struct VP9_COMP *cpi);
 | 
			
		||||
 | 
			
		||||
static INLINE int rd_less_than_thresh(int64_t best_rd, int thresh,
 | 
			
		||||
                                      int thresh_fact) {
 | 
			
		||||
    return best_rd < ((int64_t)thresh * thresh_fact >> 5) || thresh == INT_MAX;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vp9_mv_pred(struct VP9_COMP *cpi, MACROBLOCK *x,
 | 
			
		||||
                 uint8_t *ref_y_buffer, int ref_y_stride,
 | 
			
		||||
                 int ref_frame, BLOCK_SIZE block_size);
 | 
			
		||||
 | 
			
		||||
void vp9_setup_pred_block(const MACROBLOCKD *xd,
 | 
			
		||||
                          struct buf_2d dst[MAX_MB_PLANE],
 | 
			
		||||
                          const YV12_BUFFER_CONFIG *src,
 | 
			
		||||
                          int mi_row, int mi_col,
 | 
			
		||||
                          const struct scale_factors *scale,
 | 
			
		||||
                          const struct scale_factors *scale_uv);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void txfm_rd_in_plane_supertx(MACROBLOCK *x,
 | 
			
		||||
                              int *rate, int64_t *distortion,
 | 
			
		||||
                              int *skippable, int64_t *sse,
 | 
			
		||||
                              int64_t ref_best_rd, int plane,
 | 
			
		||||
                              BLOCK_SIZE bsize, TX_SIZE tx_size,
 | 
			
		||||
                              int use_fast_coef_casting);
 | 
			
		||||
void txfm_rd_in_plane(MACROBLOCK *x,
 | 
			
		||||
                      int *rate, int64_t *distortion,
 | 
			
		||||
                      int *skippable, int64_t *sse,
 | 
			
		||||
                      int64_t ref_best_rd, int plane,
 | 
			
		||||
                      BLOCK_SIZE bsize, TX_SIZE tx_size,
 | 
			
		||||
                      int use_fast_coef_casting);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -131,3 +131,47 @@ sadMxN(4, 4)
 | 
			
		||||
sadMxNxK(4, 4, 3)
 | 
			
		||||
sadMxNxK(4, 4, 8)
 | 
			
		||||
sadMxNx4D(4, 4)
 | 
			
		||||
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
     CONFIG_MASKED_INTERINTER)
 | 
			
		||||
static INLINE unsigned int masked_sad(const uint8_t *a, int a_stride,
 | 
			
		||||
                                      const uint8_t *b, int b_stride,
 | 
			
		||||
                                      const uint8_t *m, int m_stride,
 | 
			
		||||
                                      int width, int height) {
 | 
			
		||||
  int y, x;
 | 
			
		||||
  unsigned int sad = 0;
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < height; y++) {
 | 
			
		||||
    for (x = 0; x < width; x++)
 | 
			
		||||
      sad += m[x] * abs(a[x] - b[x]);
 | 
			
		||||
 | 
			
		||||
    a += a_stride;
 | 
			
		||||
    b += b_stride;
 | 
			
		||||
    m += m_stride;
 | 
			
		||||
  }
 | 
			
		||||
  sad = (sad + 31) >> 6;
 | 
			
		||||
 | 
			
		||||
  return sad;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MASKSADMxN(m, n) \
 | 
			
		||||
unsigned int vp9_masked_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
 | 
			
		||||
                                         const uint8_t *ref, int ref_stride, \
 | 
			
		||||
                                         const uint8_t *msk, int msk_stride) { \
 | 
			
		||||
  return masked_sad(src, src_stride, ref, ref_stride, msk, msk_stride, m, n); \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MASKSADMxN(64, 64)
 | 
			
		||||
MASKSADMxN(64, 32)
 | 
			
		||||
MASKSADMxN(32, 64)
 | 
			
		||||
MASKSADMxN(32, 32)
 | 
			
		||||
MASKSADMxN(32, 16)
 | 
			
		||||
MASKSADMxN(16, 32)
 | 
			
		||||
MASKSADMxN(16, 16)
 | 
			
		||||
MASKSADMxN(16, 8)
 | 
			
		||||
MASKSADMxN(8, 16)
 | 
			
		||||
MASKSADMxN(8, 8)
 | 
			
		||||
MASKSADMxN(8, 4)
 | 
			
		||||
MASKSADMxN(4, 8)
 | 
			
		||||
MASKSADMxN(4, 4)
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -84,16 +84,17 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
 | 
			
		||||
 | 
			
		||||
  if (speed >= 2) {
 | 
			
		||||
    if (MIN(cm->width, cm->height) >= 720) {
 | 
			
		||||
      sf->lf_motion_threshold = LOW_MOITION_THRESHOLD;
 | 
			
		||||
      sf->lf_motion_threshold = LOW_MOTION_THRESHOLD;
 | 
			
		||||
      sf->last_partitioning_redo_frequency = 3;
 | 
			
		||||
      sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
 | 
			
		||||
                                              : DISABLE_ALL_INTER_SPLIT;
 | 
			
		||||
    } else {
 | 
			
		||||
      sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
 | 
			
		||||
      sf->last_partitioning_redo_frequency = 2;
 | 
			
		||||
      sf->lf_motion_threshold = NO_MOITION_THRESHOLD;
 | 
			
		||||
      sf->lf_motion_threshold = NO_MOTION_THRESHOLD;
 | 
			
		||||
    }
 | 
			
		||||
    sf->adaptive_pred_interp_filter = 2;
 | 
			
		||||
 | 
			
		||||
    sf->adaptive_pred_interp_filter = 0;
 | 
			
		||||
    sf->reference_masking = 1;
 | 
			
		||||
    sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
 | 
			
		||||
                                 FLAG_SKIP_INTRA_BESTINTER |
 | 
			
		||||
@@ -114,7 +115,7 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
 | 
			
		||||
    else
 | 
			
		||||
      sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT;
 | 
			
		||||
 | 
			
		||||
    sf->lf_motion_threshold = LOW_MOITION_THRESHOLD;
 | 
			
		||||
    sf->lf_motion_threshold = LOW_MOTION_THRESHOLD;
 | 
			
		||||
    sf->last_partitioning_redo_frequency = 3;
 | 
			
		||||
    sf->recode_loop = ALLOW_RECODE_KFMAXBW;
 | 
			
		||||
    sf->adaptive_rd_thresh = 3;
 | 
			
		||||
@@ -198,7 +199,7 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
 | 
			
		||||
    sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
 | 
			
		||||
    sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
 | 
			
		||||
    sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION;
 | 
			
		||||
    sf->lf_motion_threshold = LOW_MOITION_THRESHOLD;
 | 
			
		||||
    sf->lf_motion_threshold = LOW_MOTION_THRESHOLD;
 | 
			
		||||
    sf->adjust_partitioning_from_last_frame = 1;
 | 
			
		||||
    sf->last_partitioning_redo_frequency = 3;
 | 
			
		||||
    sf->use_lp32x32fdct = 1;
 | 
			
		||||
@@ -249,6 +250,8 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (speed >= 5) {
 | 
			
		||||
    sf->auto_min_max_partition_size = (cm->frame_type == KEY_FRAME) ?
 | 
			
		||||
        RELAXED_NEIGHBORING_MIN_MAX : STRICT_NEIGHBORING_MIN_MAX;
 | 
			
		||||
    sf->max_partition_size = BLOCK_32X32;
 | 
			
		||||
    sf->min_partition_size = BLOCK_8X8;
 | 
			
		||||
    sf->partition_check =
 | 
			
		||||
@@ -270,6 +273,10 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
 | 
			
		||||
    sf->source_var_thresh = 360;
 | 
			
		||||
 | 
			
		||||
    sf->tx_size_search_method = USE_TX_8X8;
 | 
			
		||||
    sf->max_intra_bsize = BLOCK_8X8;
 | 
			
		||||
 | 
			
		||||
    // This feature is only enabled when partition search is disabled.
 | 
			
		||||
    sf->reuse_inter_pred_sby = 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (speed >= 7) {
 | 
			
		||||
@@ -335,6 +342,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
 | 
			
		||||
  for (i = 0; i < BLOCK_SIZES; ++i)
 | 
			
		||||
    sf->inter_mode_mask[i] = INTER_ALL;
 | 
			
		||||
  sf->max_intra_bsize = BLOCK_64X64;
 | 
			
		||||
  sf->reuse_inter_pred_sby = 0;
 | 
			
		||||
  // This setting only takes effect when partition_search_type is set
 | 
			
		||||
  // to FIXED_PARTITION.
 | 
			
		||||
  sf->always_this_block_size = BLOCK_16X16;
 | 
			
		||||
 
 | 
			
		||||
@@ -44,8 +44,8 @@ typedef enum {
 | 
			
		||||
} SUBPEL_SEARCH_METHODS;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NO_MOITION_THRESHOLD = 0,
 | 
			
		||||
  LOW_MOITION_THRESHOLD = 7
 | 
			
		||||
  NO_MOTION_THRESHOLD = 0,
 | 
			
		||||
  LOW_MOTION_THRESHOLD = 7
 | 
			
		||||
} MOTION_THRESHOLD;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
@@ -353,6 +353,11 @@ typedef struct SPEED_FEATURES {
 | 
			
		||||
 | 
			
		||||
  // The threshold used in SOURCE_VAR_BASED_PARTITION search type.
 | 
			
		||||
  unsigned int source_var_thresh;
 | 
			
		||||
 | 
			
		||||
  // When partition is pre-set, the inter prediction result from pick_inter_mode
 | 
			
		||||
  // can be reused in final block encoding process. It is enabled only for real-
 | 
			
		||||
  // time mode speed 6.
 | 
			
		||||
  int reuse_inter_pred_sby;
 | 
			
		||||
} SPEED_FEATURES;
 | 
			
		||||
 | 
			
		||||
struct VP9_COMP;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 | 
			
		||||
#include "vp9/encoder/vp9_encoder.h"
 | 
			
		||||
#include "vp9/encoder/vp9_svc_layercontext.h"
 | 
			
		||||
#include "vp9/encoder/vp9_extend.h"
 | 
			
		||||
 | 
			
		||||
void vp9_init_layer_context(VP9_COMP *const cpi) {
 | 
			
		||||
  SVC *const svc = &cpi->svc;
 | 
			
		||||
@@ -31,6 +32,7 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
 | 
			
		||||
  for (layer = 0; layer < layer_end; ++layer) {
 | 
			
		||||
    LAYER_CONTEXT *const lc = &svc->layer_context[layer];
 | 
			
		||||
    RATE_CONTROL *const lrc = &lc->rc;
 | 
			
		||||
    int i;
 | 
			
		||||
    lc->current_video_frame_in_layer = 0;
 | 
			
		||||
    lrc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q;
 | 
			
		||||
    lrc->ni_av_qi = oxcf->worst_allowed_q;
 | 
			
		||||
@@ -42,8 +44,10 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
 | 
			
		||||
    lrc->ni_frames = 0;
 | 
			
		||||
    lrc->decimation_count = 0;
 | 
			
		||||
    lrc->decimation_factor = 0;
 | 
			
		||||
    lrc->rate_correction_factor = 1.0;
 | 
			
		||||
    lrc->key_frame_rate_correction_factor = 1.0;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
 | 
			
		||||
      lrc->rate_correction_factors[i] = 1.0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (svc->number_temporal_layers > 1) {
 | 
			
		||||
      lc->target_bandwidth = oxcf->ts_target_bitrate[layer];
 | 
			
		||||
@@ -206,3 +210,101 @@ int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) {
 | 
			
		||||
         cpi->svc.spatial_layer_id > 0 &&
 | 
			
		||||
         cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vp9_svc_lookahead_push(const VP9_COMP *const cpi, struct lookahead_ctx *ctx,
 | 
			
		||||
                           YV12_BUFFER_CONFIG *src, int64_t ts_start,
 | 
			
		||||
                           int64_t ts_end, unsigned int flags) {
 | 
			
		||||
  struct lookahead_entry *buf;
 | 
			
		||||
  int i, index;
 | 
			
		||||
 | 
			
		||||
  if (vp9_lookahead_push(ctx, src, ts_start, ts_end, flags))
 | 
			
		||||
    return 1;
 | 
			
		||||
 | 
			
		||||
  index = ctx->write_idx - 1;
 | 
			
		||||
  if (index < 0)
 | 
			
		||||
    index += ctx->max_sz;
 | 
			
		||||
 | 
			
		||||
  buf = ctx->buf + index;
 | 
			
		||||
 | 
			
		||||
  if (buf == NULL)
 | 
			
		||||
    return 1;
 | 
			
		||||
 | 
			
		||||
  // Store svc parameters for each layer
 | 
			
		||||
  for (i = 0; i < cpi->svc.number_spatial_layers; ++i)
 | 
			
		||||
    buf->svc_params[i] = cpi->svc.layer_context[i].svc_params_received;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int copy_svc_params(VP9_COMP *const cpi, struct lookahead_entry *buf) {
 | 
			
		||||
  int layer_id;
 | 
			
		||||
  vpx_svc_parameters_t *layer_param;
 | 
			
		||||
  vpx_enc_frame_flags_t flags;
 | 
			
		||||
 | 
			
		||||
  // Find the next layer to be encoded
 | 
			
		||||
  for (layer_id = 0; layer_id < cpi->svc.number_spatial_layers; ++layer_id) {
 | 
			
		||||
    if (buf->svc_params[layer_id].spatial_layer >=0)
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (layer_id == cpi->svc.number_spatial_layers)
 | 
			
		||||
    return 1;
 | 
			
		||||
 | 
			
		||||
  layer_param = &buf->svc_params[layer_id];
 | 
			
		||||
  buf->flags = flags = layer_param->flags;
 | 
			
		||||
  cpi->svc.spatial_layer_id = layer_param->spatial_layer;
 | 
			
		||||
  cpi->svc.temporal_layer_id = layer_param->temporal_layer;
 | 
			
		||||
  cpi->lst_fb_idx = layer_param->lst_fb_idx;
 | 
			
		||||
  cpi->gld_fb_idx = layer_param->gld_fb_idx;
 | 
			
		||||
  cpi->alt_fb_idx = layer_param->alt_fb_idx;
 | 
			
		||||
 | 
			
		||||
  if (vp9_set_size_literal(cpi, layer_param->width, layer_param->height) != 0)
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
 | 
			
		||||
  cpi->oxcf.worst_allowed_q =
 | 
			
		||||
      vp9_quantizer_to_qindex(layer_param->max_quantizer);
 | 
			
		||||
  cpi->oxcf.best_allowed_q =
 | 
			
		||||
      vp9_quantizer_to_qindex(layer_param->min_quantizer);
 | 
			
		||||
 | 
			
		||||
  vp9_change_config(cpi, &cpi->oxcf);
 | 
			
		||||
 | 
			
		||||
  vp9_set_high_precision_mv(cpi, 1);
 | 
			
		||||
 | 
			
		||||
  // Retrieve the encoding flags for each layer and apply it to encoder.
 | 
			
		||||
  // It includes reference frame flags and update frame flags.
 | 
			
		||||
  vp9_apply_encoding_flags(cpi, flags);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lookahead_entry *vp9_svc_lookahead_peek(VP9_COMP *const cpi,
 | 
			
		||||
                                               struct lookahead_ctx *ctx,
 | 
			
		||||
                                               int index, int copy_params) {
 | 
			
		||||
  struct lookahead_entry *buf = vp9_lookahead_peek(ctx, index);
 | 
			
		||||
 | 
			
		||||
  if (buf != NULL && copy_params != 0) {
 | 
			
		||||
    if (copy_svc_params(cpi, buf) != 0)
 | 
			
		||||
      return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
 | 
			
		||||
                                              struct lookahead_ctx *ctx,
 | 
			
		||||
                                              int drain) {
 | 
			
		||||
  struct lookahead_entry *buf = NULL;
 | 
			
		||||
 | 
			
		||||
  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
 | 
			
		||||
    buf = vp9_svc_lookahead_peek(cpi, ctx, 0, 1);
 | 
			
		||||
    if (buf != NULL) {
 | 
			
		||||
      // Only remove the buffer when pop the highest layer. Simply set the
 | 
			
		||||
      // spatial_layer to -1 for lower layers.
 | 
			
		||||
      buf->svc_params[cpi->svc.spatial_layer_id].spatial_layer = -1;
 | 
			
		||||
      if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
 | 
			
		||||
        vp9_lookahead_pop(ctx, drain);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return buf;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@ typedef struct {
 | 
			
		||||
  struct vpx_fixed_buf rc_twopass_stats_in;
 | 
			
		||||
  unsigned int current_video_frame_in_layer;
 | 
			
		||||
  int is_key_frame;
 | 
			
		||||
  vpx_svc_parameters_t svc_params_received;
 | 
			
		||||
} LAYER_CONTEXT;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
@@ -74,6 +75,23 @@ void vp9_inc_frame_in_layer(SVC *svc);
 | 
			
		||||
// Check if current layer is key frame in spatial upper layer
 | 
			
		||||
int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi);
 | 
			
		||||
 | 
			
		||||
// Copy the source image, flags and svc parameters into a new framebuffer
 | 
			
		||||
// with the expected stride/border
 | 
			
		||||
int vp9_svc_lookahead_push(const struct VP9_COMP *const cpi,
 | 
			
		||||
                           struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
 | 
			
		||||
                           int64_t ts_start, int64_t ts_end,
 | 
			
		||||
                           unsigned int flags);
 | 
			
		||||
 | 
			
		||||
// Get the next source buffer to encode
 | 
			
		||||
struct lookahead_entry *vp9_svc_lookahead_pop(struct VP9_COMP *const cpi,
 | 
			
		||||
                                              struct lookahead_ctx *ctx,
 | 
			
		||||
                                              int drain);
 | 
			
		||||
 | 
			
		||||
// Get a future source buffer to encode
 | 
			
		||||
struct lookahead_entry *vp9_svc_lookahead_peek(struct VP9_COMP *const cpi,
 | 
			
		||||
                                               struct lookahead_ctx *ctx,
 | 
			
		||||
                                               int index, int copy_params);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -334,3 +334,41 @@ void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
 | 
			
		||||
    *t = t_backup;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void vp9_tokenize_sb_supertx(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
 | 
			
		||||
                             BLOCK_SIZE bsize) {
 | 
			
		||||
  VP9_COMMON *const cm = &cpi->common;
 | 
			
		||||
  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 | 
			
		||||
  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
 | 
			
		||||
  TOKENEXTRA *t_backup = *t;
 | 
			
		||||
  const int ctx = vp9_get_skip_context(xd);
 | 
			
		||||
  const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
 | 
			
		||||
                                              SEG_LVL_SKIP);
 | 
			
		||||
  struct tokenize_b_args arg = {cpi, xd, t};
 | 
			
		||||
  int plane;
 | 
			
		||||
  if (mbmi->skip) {
 | 
			
		||||
    if (!dry_run)
 | 
			
		||||
      cm->counts.skip[ctx][1] += skip_inc;
 | 
			
		||||
    reset_skip_context(xd, bsize);
 | 
			
		||||
    if (dry_run)
 | 
			
		||||
      *t = t_backup;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!dry_run) {
 | 
			
		||||
    cm->counts.skip[ctx][0] += skip_inc;
 | 
			
		||||
    for (plane = 0; plane < MAX_MB_PLANE; plane++) {
 | 
			
		||||
      BLOCK_SIZE plane_size = plane ? (bsize - 3) : bsize;
 | 
			
		||||
      tokenize_b(plane, 0, plane_size, b_width_log2(plane_size), &arg);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    for (plane = 0; plane < MAX_MB_PLANE; plane++) {
 | 
			
		||||
      BLOCK_SIZE plane_size = plane ? (bsize - 3) : bsize;
 | 
			
		||||
      set_entropy_context_b(plane, 0, plane_size, b_width_log2(plane_size),
 | 
			
		||||
                            &arg);
 | 
			
		||||
    }
 | 
			
		||||
    *t = t_backup;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,10 @@ struct VP9_COMP;
 | 
			
		||||
 | 
			
		||||
void vp9_tokenize_sb(struct VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
 | 
			
		||||
                     BLOCK_SIZE bsize);
 | 
			
		||||
#if CONFIG_SUPERTX
 | 
			
		||||
void vp9_tokenize_sb_supertx(struct VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
 | 
			
		||||
                             BLOCK_SIZE bsize);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern const int16_t *vp9_dct_value_cost_ptr;
 | 
			
		||||
/* TODO: The Token field should be broken out into a separate char array to
 | 
			
		||||
 
 | 
			
		||||
@@ -266,3 +266,98 @@ void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
 | 
			
		||||
    ref += ref_stride;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
    CONFIG_MASKED_INTERINTER)
 | 
			
		||||
void masked_variance(const uint8_t *a, int  a_stride,
 | 
			
		||||
                     const uint8_t *b, int  b_stride,
 | 
			
		||||
                     const uint8_t *m, int  m_stride,
 | 
			
		||||
                     int  w, int  h, unsigned int *sse, int *sum) {
 | 
			
		||||
  int i, j;
 | 
			
		||||
 | 
			
		||||
  *sum = 0;
 | 
			
		||||
  *sse = 0;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < h; i++) {
 | 
			
		||||
    for (j = 0; j < w; j++) {
 | 
			
		||||
      const int diff = (a[j] - b[j]) * (m[j]);
 | 
			
		||||
      *sum += diff;
 | 
			
		||||
      *sse += diff * diff;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    a += a_stride;
 | 
			
		||||
    b += b_stride;
 | 
			
		||||
    m += m_stride;
 | 
			
		||||
  }
 | 
			
		||||
  *sum = (*sum >= 0) ? ((*sum + 31) >> 6) : -((-*sum + 31) >> 6);
 | 
			
		||||
  *sse = (*sse + 2047) >> 12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MASK_VAR(W, H) \
 | 
			
		||||
unsigned int vp9_masked_variance##W##x##H##_c(const uint8_t *a, int a_stride, \
 | 
			
		||||
                                              const uint8_t *b, int b_stride, \
 | 
			
		||||
                                              const uint8_t *m, int m_stride, \
 | 
			
		||||
                                              unsigned int *sse) { \
 | 
			
		||||
  int sum; \
 | 
			
		||||
  masked_variance(a, a_stride, b, b_stride, m, m_stride, W, H, sse, &sum); \
 | 
			
		||||
  return *sse - (((int64_t)sum * sum) / (W * H)); \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MASK_SUBPIX_VAR(W, H) \
 | 
			
		||||
unsigned int vp9_masked_sub_pixel_variance##W##x##H##_c( \
 | 
			
		||||
  const uint8_t *src, int  src_stride, \
 | 
			
		||||
  int xoffset, int  yoffset, \
 | 
			
		||||
  const uint8_t *dst, int dst_stride, \
 | 
			
		||||
  const uint8_t *msk, int msk_stride, \
 | 
			
		||||
  unsigned int *sse) { \
 | 
			
		||||
  uint16_t fdata3[(H + 1) * W]; \
 | 
			
		||||
  uint8_t temp2[H * W]; \
 | 
			
		||||
\
 | 
			
		||||
  var_filter_block2d_bil_first_pass(src, fdata3, src_stride, 1, H + 1, W, \
 | 
			
		||||
                                    BILINEAR_FILTERS_2TAP(xoffset)); \
 | 
			
		||||
  var_filter_block2d_bil_second_pass(fdata3, temp2, W, W, H, W, \
 | 
			
		||||
                                     BILINEAR_FILTERS_2TAP(yoffset)); \
 | 
			
		||||
\
 | 
			
		||||
  return vp9_masked_variance##W##x##H##_c(temp2, W, dst, dst_stride, \
 | 
			
		||||
                                          msk, msk_stride, sse); \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MASK_VAR(4, 4)
 | 
			
		||||
MASK_SUBPIX_VAR(4, 4)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(4, 8)
 | 
			
		||||
MASK_SUBPIX_VAR(4, 8)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(8, 4)
 | 
			
		||||
MASK_SUBPIX_VAR(8, 4)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(8, 8)
 | 
			
		||||
MASK_SUBPIX_VAR(8, 8)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(8, 16)
 | 
			
		||||
MASK_SUBPIX_VAR(8, 16)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(16, 8)
 | 
			
		||||
MASK_SUBPIX_VAR(16, 8)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(16, 16)
 | 
			
		||||
MASK_SUBPIX_VAR(16, 16)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(16, 32)
 | 
			
		||||
MASK_SUBPIX_VAR(16, 32)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(32, 16)
 | 
			
		||||
MASK_SUBPIX_VAR(32, 16)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(32, 32)
 | 
			
		||||
MASK_SUBPIX_VAR(32, 32)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(32, 64)
 | 
			
		||||
MASK_SUBPIX_VAR(32, 64)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(64, 32)
 | 
			
		||||
MASK_SUBPIX_VAR(64, 32)
 | 
			
		||||
 | 
			
		||||
MASK_VAR(64, 64)
 | 
			
		||||
MASK_SUBPIX_VAR(64, 64)
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,32 @@ typedef unsigned int (*vp9_subp_avg_variance_fn_t)(const uint8_t *src_ptr,
 | 
			
		||||
                                                   unsigned int *sse,
 | 
			
		||||
                                                   const uint8_t *second_pred);
 | 
			
		||||
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
    CONFIG_MASKED_INTERINTER)
 | 
			
		||||
typedef unsigned int(*vp9_masked_sad_fn_t)(const uint8_t *src_ptr,
 | 
			
		||||
                                           int source_stride,
 | 
			
		||||
                                           const uint8_t *ref_ptr,
 | 
			
		||||
                                           int ref_stride,
 | 
			
		||||
                                           const uint8_t *msk_ptr,
 | 
			
		||||
                                           int msk_stride);
 | 
			
		||||
typedef unsigned int (*vp9_masked_variance_fn_t)(const uint8_t *src_ptr,
 | 
			
		||||
                                                 int source_stride,
 | 
			
		||||
                                                 const uint8_t *ref_ptr,
 | 
			
		||||
                                                 int ref_stride,
 | 
			
		||||
                                                 const uint8_t *msk_ptr,
 | 
			
		||||
                                                 int msk_stride,
 | 
			
		||||
                                                 unsigned int *sse);
 | 
			
		||||
typedef unsigned int (*vp9_masked_subpixvariance_fn_t)(const uint8_t *src_ptr,
 | 
			
		||||
                                                       int source_stride,
 | 
			
		||||
                                                       int xoffset,
 | 
			
		||||
                                                       int yoffset,
 | 
			
		||||
                                                       const uint8_t *ref_ptr,
 | 
			
		||||
                                                       int Refstride,
 | 
			
		||||
                                                       const uint8_t *msk_ptr,
 | 
			
		||||
                                                       int msk_stride,
 | 
			
		||||
                                                       unsigned int *sse);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct vp9_variance_vtable {
 | 
			
		||||
  vp9_sad_fn_t               sdf;
 | 
			
		||||
  vp9_sad_avg_fn_t           sdaf;
 | 
			
		||||
@@ -76,6 +102,12 @@ typedef struct vp9_variance_vtable {
 | 
			
		||||
  vp9_sad_multi_fn_t         sdx3f;
 | 
			
		||||
  vp9_sad_multi_fn_t         sdx8f;
 | 
			
		||||
  vp9_sad_multi_d_fn_t       sdx4df;
 | 
			
		||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
 | 
			
		||||
    CONFIG_MASKED_INTERINTER)
 | 
			
		||||
  vp9_masked_sad_fn_t            msdf;
 | 
			
		||||
  vp9_masked_variance_fn_t       mvf;
 | 
			
		||||
  vp9_masked_subpixvariance_fn_t msvf;
 | 
			
		||||
#endif
 | 
			
		||||
} vp9_variance_fn_ptr_t;
 | 
			
		||||
 | 
			
		||||
void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
 | 
			
		||||
 
 | 
			
		||||
@@ -88,8 +88,8 @@ struct vpx_codec_alg_priv {
 | 
			
		||||
  size_t                  pending_frame_magnitude;
 | 
			
		||||
  vpx_image_t             preview_img;
 | 
			
		||||
  vp8_postproc_cfg_t      preview_ppcfg;
 | 
			
		||||
  vpx_codec_pkt_list_decl(64) pkt_list;
 | 
			
		||||
  unsigned int                fixed_kf_cntr;
 | 
			
		||||
  vpx_codec_pkt_list_decl(128) pkt_list;
 | 
			
		||||
  unsigned int                 fixed_kf_cntr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
 | 
			
		||||
@@ -795,42 +795,7 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF |
 | 
			
		||||
               VP8_EFLAG_NO_REF_ARF)) {
 | 
			
		||||
    int ref = 7;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_REF_LAST)
 | 
			
		||||
      ref ^= VP9_LAST_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_REF_GF)
 | 
			
		||||
      ref ^= VP9_GOLD_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_REF_ARF)
 | 
			
		||||
      ref ^= VP9_ALT_FLAG;
 | 
			
		||||
 | 
			
		||||
    vp9_use_as_reference(ctx->cpi, ref);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
 | 
			
		||||
               VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF |
 | 
			
		||||
               VP8_EFLAG_FORCE_ARF)) {
 | 
			
		||||
    int upd = 7;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_UPD_LAST)
 | 
			
		||||
      upd ^= VP9_LAST_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_UPD_GF)
 | 
			
		||||
      upd ^= VP9_GOLD_FLAG;
 | 
			
		||||
 | 
			
		||||
    if (flags & VP8_EFLAG_NO_UPD_ARF)
 | 
			
		||||
      upd ^= VP9_ALT_FLAG;
 | 
			
		||||
 | 
			
		||||
    vp9_update_reference(ctx->cpi, upd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
 | 
			
		||||
    vp9_update_entropy(ctx->cpi, 0);
 | 
			
		||||
  }
 | 
			
		||||
  vp9_apply_encoding_flags(ctx->cpi, flags);
 | 
			
		||||
 | 
			
		||||
  // Handle fixed keyframe intervals
 | 
			
		||||
  if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
 | 
			
		||||
@@ -843,7 +808,7 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
 | 
			
		||||
  // Initialize the encoder instance on the first frame.
 | 
			
		||||
  if (res == VPX_CODEC_OK && ctx->cpi != NULL) {
 | 
			
		||||
    unsigned int lib_flags;
 | 
			
		||||
    unsigned int lib_flags = 0;
 | 
			
		||||
    YV12_BUFFER_CONFIG sd;
 | 
			
		||||
    int64_t dst_time_stamp, dst_end_time_stamp;
 | 
			
		||||
    size_t size, cx_data_sz;
 | 
			
		||||
@@ -853,9 +818,6 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
    if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
 | 
			
		||||
      ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
 | 
			
		||||
 | 
			
		||||
    // Convert API flags to internal codec lib flags
 | 
			
		||||
    lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
 | 
			
		||||
 | 
			
		||||
    /* vp9 use 10,000,000 ticks/second as time stamp */
 | 
			
		||||
    dst_time_stamp = (pts * 10000000 * ctx->cfg.g_timebase.num)
 | 
			
		||||
                     / ctx->cfg.g_timebase.den;
 | 
			
		||||
@@ -865,7 +827,9 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
    if (img != NULL) {
 | 
			
		||||
      res = image2yuvconfig(img, &sd);
 | 
			
		||||
 | 
			
		||||
      if (vp9_receive_raw_frame(ctx->cpi, lib_flags,
 | 
			
		||||
      // Store the original flags in to the frame buffer. Will extract the
 | 
			
		||||
      // key frame flag when we actually encode this frame.
 | 
			
		||||
      if (vp9_receive_raw_frame(ctx->cpi, flags,
 | 
			
		||||
                                &sd, dst_time_stamp, dst_end_time_stamp)) {
 | 
			
		||||
        VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
 | 
			
		||||
        res = update_error_state(ctx, &cpi->common.error);
 | 
			
		||||
@@ -874,7 +838,6 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
 | 
			
		||||
    cx_data = ctx->cx_data;
 | 
			
		||||
    cx_data_sz = ctx->cx_data_sz;
 | 
			
		||||
    lib_flags = 0;
 | 
			
		||||
 | 
			
		||||
    /* Any pending invisible frames? */
 | 
			
		||||
    if (ctx->pending_cx_data) {
 | 
			
		||||
@@ -902,7 +865,12 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
        VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
 | 
			
		||||
 | 
			
		||||
        // Pack invisible frames with the next visible frame
 | 
			
		||||
        if (cpi->common.show_frame == 0) {
 | 
			
		||||
        if (cpi->common.show_frame == 0
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
            || (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
 | 
			
		||||
                cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
 | 
			
		||||
#endif
 | 
			
		||||
            ) {
 | 
			
		||||
          if (ctx->pending_cx_data == 0)
 | 
			
		||||
            ctx->pending_cx_data = cx_data;
 | 
			
		||||
          ctx->pending_cx_data_sz += size;
 | 
			
		||||
@@ -925,7 +893,12 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
			
		||||
          / ctx->cfg.g_timebase.num / 10000000);
 | 
			
		||||
        pkt.data.frame.flags = lib_flags << 16;
 | 
			
		||||
 | 
			
		||||
        if (lib_flags & FRAMEFLAGS_KEY)
 | 
			
		||||
        if (lib_flags & FRAMEFLAGS_KEY
 | 
			
		||||
#ifdef CONFIG_SPATIAL_SVC
 | 
			
		||||
            || (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
 | 
			
		||||
                cpi->svc.layer_context[0].is_key_frame)
 | 
			
		||||
#endif
 | 
			
		||||
            )
 | 
			
		||||
          pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
 | 
			
		||||
 | 
			
		||||
        if (cpi->common.show_frame == 0) {
 | 
			
		||||
@@ -1165,24 +1138,19 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
  VP9_COMP *const cpi = ctx->cpi;
 | 
			
		||||
  vpx_svc_parameters_t *const params = va_arg(args, vpx_svc_parameters_t *);
 | 
			
		||||
 | 
			
		||||
  if (params == NULL)
 | 
			
		||||
  if (params == NULL || params->spatial_layer < 0 ||
 | 
			
		||||
      params->spatial_layer >= cpi->svc.number_spatial_layers)
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
 | 
			
		||||
  cpi->svc.spatial_layer_id = params->spatial_layer;
 | 
			
		||||
  cpi->svc.temporal_layer_id = params->temporal_layer;
 | 
			
		||||
  if (params->spatial_layer == 0) {
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
 | 
			
		||||
      cpi->svc.layer_context[i].svc_params_received.spatial_layer = -1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cpi->lst_fb_idx = params->lst_fb_idx;
 | 
			
		||||
  cpi->gld_fb_idx = params->gld_fb_idx;
 | 
			
		||||
  cpi->alt_fb_idx = params->alt_fb_idx;
 | 
			
		||||
 | 
			
		||||
  if (vp9_set_size_literal(ctx->cpi, params->width, params->height) != 0)
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
 | 
			
		||||
  ctx->cfg.rc_max_quantizer = params->max_quantizer;
 | 
			
		||||
  ctx->cfg.rc_min_quantizer = params->min_quantizer;
 | 
			
		||||
 | 
			
		||||
  set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
 | 
			
		||||
  vp9_change_config(ctx->cpi, &ctx->oxcf);
 | 
			
		||||
  cpi->svc.layer_context[params->spatial_layer].svc_params_received =
 | 
			
		||||
      *params;
 | 
			
		||||
 | 
			
		||||
  return VPX_CODEC_OK;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,6 @@ struct vpx_codec_alg_priv {
 | 
			
		||||
  vpx_codec_priv_t        base;
 | 
			
		||||
  vpx_codec_dec_cfg_t     cfg;
 | 
			
		||||
  vp9_stream_info_t       si;
 | 
			
		||||
  struct VP9Decoder *pbi;
 | 
			
		||||
  int                     postproc_cfg_set;
 | 
			
		||||
  vp8_postproc_cfg_t      postproc_cfg;
 | 
			
		||||
  vpx_decrypt_cb          decrypt_cb;
 | 
			
		||||
@@ -42,6 +41,11 @@ struct vpx_codec_alg_priv {
 | 
			
		||||
  int                     frame_parallel_decode;  // frame-based threading.
 | 
			
		||||
  int                     last_show_frame;  // Index of last output frame.
 | 
			
		||||
 | 
			
		||||
  VP9Worker               *frame_workers;
 | 
			
		||||
  int                     num_frame_workers;
 | 
			
		||||
  int                     next_submit_thread_id;
 | 
			
		||||
  int                     next_output_thread_id;
 | 
			
		||||
 | 
			
		||||
  // External frame buffer info to save for VP9 common.
 | 
			
		||||
  void *ext_priv;  // Private data associated with the external frame buffers.
 | 
			
		||||
  vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
 | 
			
		||||
@@ -85,11 +89,17 @@ static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
 | 
			
		||||
  if (ctx->pbi) {
 | 
			
		||||
    vp9_decoder_remove(ctx->pbi);
 | 
			
		||||
    ctx->pbi = NULL;
 | 
			
		||||
  if (ctx->frame_workers != NULL) {
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 0; i < ctx->num_frame_workers; ++i) {
 | 
			
		||||
      VP9Worker *const worker = &ctx->frame_workers[i];
 | 
			
		||||
      FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
      vp9_decoder_remove(worker_data->pbi);
 | 
			
		||||
      vpx_free(worker_data);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vpx_free(ctx->frame_workers);
 | 
			
		||||
  vpx_free(ctx);
 | 
			
		||||
 | 
			
		||||
  return VPX_CODEC_OK;
 | 
			
		||||
@@ -102,9 +112,6 @@ static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
 | 
			
		||||
                                                void *decrypt_state) {
 | 
			
		||||
  uint8_t clear_buffer[9];
 | 
			
		||||
 | 
			
		||||
  if (data_sz <= 8)
 | 
			
		||||
    return VPX_CODEC_UNSUP_BITSTREAM;
 | 
			
		||||
 | 
			
		||||
  if (data + data_sz <= data)
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
 | 
			
		||||
@@ -125,12 +132,16 @@ static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
 | 
			
		||||
 | 
			
		||||
    if (frame_marker != VP9_FRAME_MARKER)
 | 
			
		||||
      return VPX_CODEC_UNSUP_BITSTREAM;
 | 
			
		||||
 | 
			
		||||
    if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
 | 
			
		||||
 | 
			
		||||
    if (vp9_rb_read_bit(&rb)) {  // show an existing frame
 | 
			
		||||
      return VPX_CODEC_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (data_sz <= 8)
 | 
			
		||||
      return VPX_CODEC_UNSUP_BITSTREAM;
 | 
			
		||||
 | 
			
		||||
    si->is_kf = !vp9_rb_read_bit(&rb);
 | 
			
		||||
    if (si->is_kf) {
 | 
			
		||||
      const int sRGB = 7;
 | 
			
		||||
@@ -187,32 +198,42 @@ static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
  return VPX_CODEC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_error_detail(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                             const char *const error) {
 | 
			
		||||
  ctx->base.err_detail = error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                           const struct vpx_internal_error_info *error) {
 | 
			
		||||
  if (error->error_code)
 | 
			
		||||
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;
 | 
			
		||||
    set_error_detail(ctx, error->has_detail ? error->detail : NULL);
 | 
			
		||||
 | 
			
		||||
  return error->error_code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
 | 
			
		||||
  VP9_COMMON *const cm = &ctx->pbi->common;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  cm->new_fb_idx = -1;
 | 
			
		||||
  for (i = 0; i < ctx->num_frame_workers; ++i) {
 | 
			
		||||
    VP9Worker *const worker = &ctx->frame_workers[i];
 | 
			
		||||
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    VP9_COMMON *const cm = &worker_data->pbi->common;
 | 
			
		||||
 | 
			
		||||
  if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
 | 
			
		||||
    cm->get_fb_cb = ctx->get_ext_fb_cb;
 | 
			
		||||
    cm->release_fb_cb = ctx->release_ext_fb_cb;
 | 
			
		||||
    cm->cb_priv = ctx->ext_priv;
 | 
			
		||||
  } else {
 | 
			
		||||
    cm->get_fb_cb = vp9_get_frame_buffer;
 | 
			
		||||
    cm->release_fb_cb = vp9_release_frame_buffer;
 | 
			
		||||
    cm->new_fb_idx = -1;
 | 
			
		||||
    if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
 | 
			
		||||
      cm->get_fb_cb = ctx->get_ext_fb_cb;
 | 
			
		||||
      cm->release_fb_cb = ctx->release_ext_fb_cb;
 | 
			
		||||
      cm->cb_priv = ctx->ext_priv;
 | 
			
		||||
    } else {
 | 
			
		||||
      cm->get_fb_cb = vp9_get_frame_buffer;
 | 
			
		||||
      cm->release_fb_cb = vp9_release_frame_buffer;
 | 
			
		||||
 | 
			
		||||
    if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
 | 
			
		||||
      vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                         "Failed to initialize internal frame buffers");
 | 
			
		||||
      if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
 | 
			
		||||
        vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
 | 
			
		||||
                           "Failed to initialize internal frame buffers");
 | 
			
		||||
 | 
			
		||||
    cm->cb_priv = &cm->int_frame_buffers;
 | 
			
		||||
      cm->cb_priv = &cm->int_frame_buffers;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -231,15 +252,58 @@ static void set_ppflags(const vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
  flags->noise_level = ctx->postproc_cfg.noise_level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_decoder(vpx_codec_alg_priv_t *ctx) {
 | 
			
		||||
  ctx->pbi = vp9_decoder_create();
 | 
			
		||||
  if (ctx->pbi == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
static int frame_worker_hook(void *arg1, void *arg2) {
 | 
			
		||||
  FrameWorkerData *const worker_data = (FrameWorkerData *)arg1;
 | 
			
		||||
  const uint8_t *data = worker_data->data;
 | 
			
		||||
  (void)arg2;
 | 
			
		||||
  worker_data->result = vp9_receive_compressed_data(worker_data->pbi,
 | 
			
		||||
                                                    worker_data->data_size,
 | 
			
		||||
                                                    &data);
 | 
			
		||||
  worker_data->data_end = data;
 | 
			
		||||
  return !worker_data->result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) {
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  ctx->pbi->max_threads = ctx->cfg.threads;
 | 
			
		||||
  ctx->pbi->inv_tile_order = ctx->invert_tile_order;
 | 
			
		||||
  ctx->pbi->frame_parallel_decode = ctx->frame_parallel_decode;
 | 
			
		||||
  ctx->last_show_frame = -1;
 | 
			
		||||
  ctx->next_submit_thread_id = 0;
 | 
			
		||||
  ctx->next_output_thread_id = 0;
 | 
			
		||||
  ctx->num_frame_workers =
 | 
			
		||||
      (ctx->frame_parallel_decode == 1) ? ctx->cfg.threads: 1;
 | 
			
		||||
 | 
			
		||||
  ctx->frame_workers = (VP9Worker *)
 | 
			
		||||
      vpx_malloc(ctx->num_frame_workers * sizeof(*ctx->frame_workers));
 | 
			
		||||
  if (ctx->frame_workers == NULL) {
 | 
			
		||||
    set_error_detail(ctx, "Failed to allocate frame_workers");
 | 
			
		||||
    return VPX_CODEC_MEM_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < ctx->num_frame_workers; ++i) {
 | 
			
		||||
    VP9Worker *const worker = &ctx->frame_workers[i];
 | 
			
		||||
    FrameWorkerData *worker_data = NULL;
 | 
			
		||||
    vp9_worker_init(worker);
 | 
			
		||||
    worker->data1 = vpx_memalign(32, sizeof(FrameWorkerData));
 | 
			
		||||
    if (worker->data1 == NULL) {
 | 
			
		||||
      set_error_detail(ctx, "Failed to allocate worker_data");
 | 
			
		||||
      return VPX_CODEC_MEM_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    worker_data->pbi = vp9_decoder_create();
 | 
			
		||||
    if (worker_data->pbi == NULL) {
 | 
			
		||||
      set_error_detail(ctx, "Failed to allocate worker_data");
 | 
			
		||||
      return VPX_CODEC_MEM_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If decoding in serial mode, FrameWorker thread could create tile worker
 | 
			
		||||
    // thread or loopfilter thread.
 | 
			
		||||
    worker_data->pbi->max_threads =
 | 
			
		||||
        (ctx->frame_parallel_decode == 0) ? ctx->cfg.threads : 0;
 | 
			
		||||
 | 
			
		||||
    worker_data->pbi->inv_tile_order = ctx->invert_tile_order;
 | 
			
		||||
    worker_data->pbi->frame_parallel_decode = ctx->frame_parallel_decode;
 | 
			
		||||
    worker->hook = (VP9WorkerHook)frame_worker_hook;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If postprocessing was enabled by the application and a
 | 
			
		||||
  // configuration has not been provided, default it.
 | 
			
		||||
@@ -248,14 +312,14 @@ static void init_decoder(vpx_codec_alg_priv_t *ctx) {
 | 
			
		||||
    set_default_ppflags(&ctx->postproc_cfg);
 | 
			
		||||
 | 
			
		||||
  init_buffer_callbacks(ctx);
 | 
			
		||||
 | 
			
		||||
  return VPX_CODEC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                  const uint8_t **data, unsigned int data_sz,
 | 
			
		||||
                                  void *user_priv, int64_t deadline) {
 | 
			
		||||
  vp9_ppflags_t flags = {0};
 | 
			
		||||
  VP9_COMMON *cm = NULL;
 | 
			
		||||
 | 
			
		||||
  (void)deadline;
 | 
			
		||||
 | 
			
		||||
  // Determine the stream parameters. Note that we rely on peek_si to
 | 
			
		||||
@@ -272,22 +336,35 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
      return VPX_CODEC_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Initialize the decoder instance on the first frame
 | 
			
		||||
  if (ctx->pbi == NULL) {
 | 
			
		||||
    init_decoder(ctx);
 | 
			
		||||
    if (ctx->pbi == NULL)
 | 
			
		||||
      return VPX_CODEC_ERROR;
 | 
			
		||||
  // Initialize the decoder workers on the first frame
 | 
			
		||||
  if (ctx->frame_workers == NULL) {
 | 
			
		||||
    const vpx_codec_err_t res = init_decoder(ctx);
 | 
			
		||||
    if (res != VPX_CODEC_OK)
 | 
			
		||||
      return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Set these even if already initialized.  The caller may have changed the
 | 
			
		||||
  // decrypt config between frames.
 | 
			
		||||
  ctx->pbi->decrypt_cb = ctx->decrypt_cb;
 | 
			
		||||
  ctx->pbi->decrypt_state = ctx->decrypt_state;
 | 
			
		||||
  if (!ctx->frame_parallel_decode) {
 | 
			
		||||
    VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    worker_data->data = *data;
 | 
			
		||||
    worker_data->data_size = data_sz;
 | 
			
		||||
    worker_data->user_priv = user_priv;
 | 
			
		||||
 | 
			
		||||
  cm = &ctx->pbi->common;
 | 
			
		||||
    // Set these even if already initialized.  The caller may have changed the
 | 
			
		||||
    // decrypt config between frames.
 | 
			
		||||
    worker_data->pbi->decrypt_cb = ctx->decrypt_cb;
 | 
			
		||||
    worker_data->pbi->decrypt_state = ctx->decrypt_state;
 | 
			
		||||
 | 
			
		||||
  if (vp9_receive_compressed_data(ctx->pbi, data_sz, data))
 | 
			
		||||
    return update_error_state(ctx, &cm->error);
 | 
			
		||||
    vp9_worker_execute(worker);
 | 
			
		||||
    if (worker->had_error)
 | 
			
		||||
      return update_error_state(ctx, &worker_data->pbi->common.error);
 | 
			
		||||
 | 
			
		||||
    // Update data pointer after decode.
 | 
			
		||||
    *data = worker_data->data_end;
 | 
			
		||||
  } else {
 | 
			
		||||
    // TODO(hkuang): Implement frame parallel decode.
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
 | 
			
		||||
    set_ppflags(ctx, &flags);
 | 
			
		||||
@@ -306,10 +383,17 @@ static INLINE uint8_t read_marker(vpx_decrypt_cb decrypt_cb,
 | 
			
		||||
  return *data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parse_superframe_index(const uint8_t *data, size_t data_sz,
 | 
			
		||||
                                   uint32_t sizes[8], int *count,
 | 
			
		||||
                                   vpx_decrypt_cb decrypt_cb,
 | 
			
		||||
                                   void *decrypt_state) {
 | 
			
		||||
static vpx_codec_err_t parse_superframe_index(const uint8_t *data,
 | 
			
		||||
                                              size_t data_sz,
 | 
			
		||||
                                              uint32_t sizes[8], int *count,
 | 
			
		||||
                                              vpx_decrypt_cb decrypt_cb,
 | 
			
		||||
                                              void *decrypt_state) {
 | 
			
		||||
  // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
 | 
			
		||||
  // it is a super frame index. If the last byte of real video compression
 | 
			
		||||
  // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
 | 
			
		||||
  // not the associated matching marker byte at the front of the index we have
 | 
			
		||||
  // an invalid bitstream and need to return an error.
 | 
			
		||||
 | 
			
		||||
  uint8_t marker;
 | 
			
		||||
 | 
			
		||||
  assert(data_sz);
 | 
			
		||||
@@ -321,56 +405,45 @@ static void parse_superframe_index(const uint8_t *data, size_t data_sz,
 | 
			
		||||
    const uint32_t mag = ((marker >> 3) & 0x3) + 1;
 | 
			
		||||
    const size_t index_sz = 2 + mag * frames;
 | 
			
		||||
 | 
			
		||||
    if (data_sz >= index_sz) {
 | 
			
		||||
      uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
 | 
			
		||||
                                    data + data_sz - index_sz);
 | 
			
		||||
    // This chunk is marked as having a superframe index but doesn't have
 | 
			
		||||
    // enough data for it, thus it's an invalid superframe index.
 | 
			
		||||
    if (data_sz < index_sz)
 | 
			
		||||
      return VPX_CODEC_CORRUPT_FRAME;
 | 
			
		||||
 | 
			
		||||
      if (marker == marker2) {
 | 
			
		||||
        // Found a valid superframe index.
 | 
			
		||||
        uint32_t i, j;
 | 
			
		||||
        const uint8_t *x = &data[data_sz - index_sz + 1];
 | 
			
		||||
    {
 | 
			
		||||
      const uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
 | 
			
		||||
                                          data + data_sz - index_sz);
 | 
			
		||||
 | 
			
		||||
        // Frames has a maximum of 8 and mag has a maximum of 4.
 | 
			
		||||
        uint8_t clear_buffer[32];
 | 
			
		||||
        assert(sizeof(clear_buffer) >= frames * mag);
 | 
			
		||||
        if (decrypt_cb) {
 | 
			
		||||
          decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
 | 
			
		||||
          x = clear_buffer;
 | 
			
		||||
        }
 | 
			
		||||
      // This chunk is marked as having a superframe index but doesn't have
 | 
			
		||||
      // the matching marker byte at the front of the index therefore it's an
 | 
			
		||||
      // invalid chunk.
 | 
			
		||||
      if (marker != marker2)
 | 
			
		||||
        return VPX_CODEC_CORRUPT_FRAME;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < frames; ++i) {
 | 
			
		||||
          uint32_t this_sz = 0;
 | 
			
		||||
    {
 | 
			
		||||
      // Found a valid superframe index.
 | 
			
		||||
      uint32_t i, j;
 | 
			
		||||
      const uint8_t *x = &data[data_sz - index_sz + 1];
 | 
			
		||||
 | 
			
		||||
          for (j = 0; j < mag; ++j)
 | 
			
		||||
            this_sz |= (*x++) << (j * 8);
 | 
			
		||||
          sizes[i] = this_sz;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *count = frames;
 | 
			
		||||
      // Frames has a maximum of 8 and mag has a maximum of 4.
 | 
			
		||||
      uint8_t clear_buffer[32];
 | 
			
		||||
      assert(sizeof(clear_buffer) >= frames * mag);
 | 
			
		||||
      if (decrypt_cb) {
 | 
			
		||||
        decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
 | 
			
		||||
        x = clear_buffer;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < frames; ++i) {
 | 
			
		||||
        uint32_t this_sz = 0;
 | 
			
		||||
 | 
			
		||||
        for (j = 0; j < mag; ++j)
 | 
			
		||||
          this_sz |= (*x++) << (j * 8);
 | 
			
		||||
        sizes[i] = this_sz;
 | 
			
		||||
      }
 | 
			
		||||
      *count = frames;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static vpx_codec_err_t decode_one_iter(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                       const uint8_t **data_start_ptr,
 | 
			
		||||
                                       const uint8_t *data_end,
 | 
			
		||||
                                       uint32_t frame_size, void *user_priv,
 | 
			
		||||
                                       long deadline) {
 | 
			
		||||
  const vpx_codec_err_t res = decode_one(ctx, data_start_ptr, frame_size,
 | 
			
		||||
                                         user_priv, deadline);
 | 
			
		||||
  if (res != VPX_CODEC_OK)
 | 
			
		||||
    return res;
 | 
			
		||||
 | 
			
		||||
  // Account for suboptimal termination by the encoder.
 | 
			
		||||
  while (*data_start_ptr < data_end) {
 | 
			
		||||
    const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state,
 | 
			
		||||
                                       *data_start_ptr);
 | 
			
		||||
    if (marker)
 | 
			
		||||
      break;
 | 
			
		||||
    (*data_start_ptr)++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return VPX_CODEC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -378,7 +451,7 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                      const uint8_t *data, unsigned int data_sz,
 | 
			
		||||
                                      void *user_priv, long deadline) {
 | 
			
		||||
  const uint8_t *data_start = data;
 | 
			
		||||
  const uint8_t *const data_end = data + data_sz;
 | 
			
		||||
  const uint8_t * const data_end = data + data_sz;
 | 
			
		||||
  vpx_codec_err_t res;
 | 
			
		||||
  uint32_t frame_sizes[8];
 | 
			
		||||
  int frame_count;
 | 
			
		||||
@@ -386,32 +459,86 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
  if (data == NULL || data_sz == 0)
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
 | 
			
		||||
  parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
 | 
			
		||||
                         ctx->decrypt_cb, ctx->decrypt_state);
 | 
			
		||||
  res = parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
 | 
			
		||||
                               ctx->decrypt_cb, ctx->decrypt_state);
 | 
			
		||||
  if (res != VPX_CODEC_OK)
 | 
			
		||||
    return res;
 | 
			
		||||
 | 
			
		||||
  if (frame_count > 0) {
 | 
			
		||||
    int i;
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    // Decode in frame parallel mode. When decoding in this mode, the frame
 | 
			
		||||
    // passed to the decoder must be either a normal frame or a superframe with
 | 
			
		||||
    // superframe index so the decoder could get each frame's start position
 | 
			
		||||
    // in the superframe.
 | 
			
		||||
    if (frame_count > 0) {
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < frame_count; ++i) {
 | 
			
		||||
      const uint32_t frame_size = frame_sizes[i];
 | 
			
		||||
      if (data_start < data ||
 | 
			
		||||
          frame_size > (uint32_t)(data_end - data_start)) {
 | 
			
		||||
        ctx->base.err_detail = "Invalid frame size in index";
 | 
			
		||||
        return VPX_CODEC_CORRUPT_FRAME;
 | 
			
		||||
      for (i = 0; i < frame_count; ++i) {
 | 
			
		||||
        const uint8_t *data_start_copy = data_start;
 | 
			
		||||
        const uint32_t frame_size = frame_sizes[i];
 | 
			
		||||
        vpx_codec_err_t res;
 | 
			
		||||
        if (data_start < data
 | 
			
		||||
            || frame_size > (uint32_t) (data_end - data_start)) {
 | 
			
		||||
          set_error_detail(ctx, "Invalid frame size in index");
 | 
			
		||||
          return VPX_CODEC_CORRUPT_FRAME;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        res = decode_one(ctx, &data_start_copy, frame_size, user_priv,
 | 
			
		||||
                         deadline);
 | 
			
		||||
        if (res != VPX_CODEC_OK)
 | 
			
		||||
          return res;
 | 
			
		||||
 | 
			
		||||
        data_start += frame_size;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      res = decode_one_iter(ctx, &data_start, data_end, frame_size,
 | 
			
		||||
                            user_priv, deadline);
 | 
			
		||||
    } else {
 | 
			
		||||
      res = decode_one(ctx, &data_start, data_sz, user_priv, deadline);
 | 
			
		||||
      if (res != VPX_CODEC_OK)
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
      // Extra data detected after the frame.
 | 
			
		||||
      if (data_start < data_end - 1) {
 | 
			
		||||
        set_error_detail(ctx, "Fail to decode frame in parallel mode");
 | 
			
		||||
        return VPX_CODEC_INCAPABLE;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    while (data_start < data_end) {
 | 
			
		||||
      res = decode_one_iter(ctx, &data_start, data_end,
 | 
			
		||||
                            (uint32_t)(data_end - data_start),
 | 
			
		||||
                            user_priv, deadline);
 | 
			
		||||
      if (res != VPX_CODEC_OK)
 | 
			
		||||
        return res;
 | 
			
		||||
    // Decode in serial mode.
 | 
			
		||||
    if (frame_count > 0) {
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < frame_count; ++i) {
 | 
			
		||||
        const uint8_t *data_start_copy = data_start;
 | 
			
		||||
        const uint32_t frame_size = frame_sizes[i];
 | 
			
		||||
        vpx_codec_err_t res;
 | 
			
		||||
        if (data_start < data
 | 
			
		||||
            || frame_size > (uint32_t) (data_end - data_start)) {
 | 
			
		||||
          set_error_detail(ctx, "Invalid frame size in index");
 | 
			
		||||
          return VPX_CODEC_CORRUPT_FRAME;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        res = decode_one(ctx, &data_start_copy, frame_size, user_priv,
 | 
			
		||||
                         deadline);
 | 
			
		||||
        if (res != VPX_CODEC_OK)
 | 
			
		||||
          return res;
 | 
			
		||||
 | 
			
		||||
        data_start += frame_size;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      while (data_start < data_end) {
 | 
			
		||||
        const uint32_t frame_size = (uint32_t) (data_end - data_start);
 | 
			
		||||
        const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size,
 | 
			
		||||
                                               user_priv, deadline);
 | 
			
		||||
        if (res != VPX_CODEC_OK)
 | 
			
		||||
          return res;
 | 
			
		||||
 | 
			
		||||
        // Account for suboptimal termination by the encoder.
 | 
			
		||||
        while (data_start < data_end) {
 | 
			
		||||
          const uint8_t marker = read_marker(ctx->decrypt_cb,
 | 
			
		||||
                                             ctx->decrypt_state, data_start);
 | 
			
		||||
          if (marker)
 | 
			
		||||
            break;
 | 
			
		||||
          ++data_start;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -424,13 +551,15 @@ static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
 | 
			
		||||
  // iter acts as a flip flop, so an image is only returned on the first
 | 
			
		||||
  // call to get_frame.
 | 
			
		||||
  if (*iter == NULL && ctx->pbi != NULL) {
 | 
			
		||||
  if (*iter == NULL && ctx->frame_workers != NULL) {
 | 
			
		||||
    YV12_BUFFER_CONFIG sd;
 | 
			
		||||
    vp9_ppflags_t flags = {0, 0, 0};
 | 
			
		||||
 | 
			
		||||
    if (vp9_get_raw_frame(ctx->pbi, &sd, &flags) == 0) {
 | 
			
		||||
      VP9_COMMON *cm = &ctx->pbi->common;
 | 
			
		||||
      yuvconfig2image(&ctx->img, &sd, NULL);
 | 
			
		||||
    VP9Worker *const worker = &ctx->frame_workers[ctx->next_output_thread_id];
 | 
			
		||||
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    if (vp9_get_raw_frame(worker_data->pbi, &sd, &flags) == 0) {
 | 
			
		||||
      VP9_COMMON *const cm = &worker_data->pbi->common;
 | 
			
		||||
      yuvconfig2image(&ctx->img, &sd, worker_data->user_priv);
 | 
			
		||||
      ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
 | 
			
		||||
      img = &ctx->img;
 | 
			
		||||
      *iter = img;
 | 
			
		||||
@@ -442,7 +571,7 @@ static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
              &cm->frame_bufs[ctx->last_show_frame].raw_frame_buffer);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      ctx->last_show_frame = ctx->pbi->common.new_fb_idx;
 | 
			
		||||
      ctx->last_show_frame = worker_data->pbi->common.new_fb_idx;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -455,7 +584,7 @@ static vpx_codec_err_t decoder_set_fb_fn(
 | 
			
		||||
    vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
 | 
			
		||||
  if (cb_get == NULL || cb_release == NULL) {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
  } else if (ctx->pbi == NULL) {
 | 
			
		||||
  } else if (ctx->frame_workers == NULL) {
 | 
			
		||||
    // If the decoder has already been initialized, do not accept changes to
 | 
			
		||||
    // the frame buffer functions.
 | 
			
		||||
    ctx->get_ext_fb_cb = cb_get;
 | 
			
		||||
@@ -471,12 +600,19 @@ static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                          va_list args) {
 | 
			
		||||
  vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *);
 | 
			
		||||
 | 
			
		||||
  // Only support this function in serial decode.
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    set_error_detail(ctx, "Not supported in frame parallel decode");
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (data) {
 | 
			
		||||
    vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
 | 
			
		||||
    YV12_BUFFER_CONFIG sd;
 | 
			
		||||
 | 
			
		||||
    VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    image2yuvconfig(&frame->img, &sd);
 | 
			
		||||
    return vp9_set_reference_dec(&ctx->pbi->common,
 | 
			
		||||
    return vp9_set_reference_dec(&worker_data->pbi->common,
 | 
			
		||||
                                 (VP9_REFFRAME)frame->frame_type, &sd);
 | 
			
		||||
  } else {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
@@ -487,13 +623,19 @@ static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                           va_list args) {
 | 
			
		||||
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
 | 
			
		||||
 | 
			
		||||
  // Only support this function in serial decode.
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    set_error_detail(ctx, "Not supported in frame parallel decode");
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (data) {
 | 
			
		||||
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
 | 
			
		||||
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *) data;
 | 
			
		||||
    YV12_BUFFER_CONFIG sd;
 | 
			
		||||
 | 
			
		||||
    VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    image2yuvconfig(&frame->img, &sd);
 | 
			
		||||
 | 
			
		||||
    return vp9_copy_reference_dec(ctx->pbi,
 | 
			
		||||
    return vp9_copy_reference_dec(worker_data->pbi,
 | 
			
		||||
                                  (VP9_REFFRAME)frame->frame_type, &sd);
 | 
			
		||||
  } else {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
@@ -504,11 +646,18 @@ static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                          va_list args) {
 | 
			
		||||
  vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
 | 
			
		||||
 | 
			
		||||
  // Only support this function in serial decode.
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    set_error_detail(ctx, "Not supported in frame parallel decode");
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (data) {
 | 
			
		||||
    YV12_BUFFER_CONFIG* fb;
 | 
			
		||||
 | 
			
		||||
    vp9_get_reference_dec(ctx->pbi, data->idx, &fb);
 | 
			
		||||
    yuvconfig2image(&data->img, fb, NULL);
 | 
			
		||||
    VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
    vp9_get_reference_dec(worker_data->pbi, data->idx, &fb);
 | 
			
		||||
    yuvconfig2image(&data->img, fb, worker_data->user_priv);
 | 
			
		||||
    return VPX_CODEC_OK;
 | 
			
		||||
  } else {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
@@ -545,11 +694,20 @@ static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                                 va_list args) {
 | 
			
		||||
  int *const update_info = va_arg(args, int *);
 | 
			
		||||
 | 
			
		||||
  // Only support this function in serial decode.
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    set_error_detail(ctx, "Not supported in frame parallel decode");
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (update_info) {
 | 
			
		||||
    if (ctx->pbi)
 | 
			
		||||
      *update_info = ctx->pbi->refresh_frame_flags;
 | 
			
		||||
    else
 | 
			
		||||
    if (ctx->frame_workers) {
 | 
			
		||||
      VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
      FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
      *update_info = worker_data->pbi->refresh_frame_flags;
 | 
			
		||||
    } else {
 | 
			
		||||
      return VPX_CODEC_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    return VPX_CODEC_OK;
 | 
			
		||||
  } else {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
@@ -561,11 +719,20 @@ static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                                va_list args) {
 | 
			
		||||
  int *corrupted = va_arg(args, int *);
 | 
			
		||||
 | 
			
		||||
  // Only support this function in serial decode.
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    set_error_detail(ctx, "Not supported in frame parallel decode");
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (corrupted) {
 | 
			
		||||
    if (ctx->pbi)
 | 
			
		||||
      *corrupted = ctx->pbi->common.frame_to_show->corrupted;
 | 
			
		||||
    else
 | 
			
		||||
    if (ctx->frame_workers) {
 | 
			
		||||
      VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
      FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
      *corrupted = worker_data->pbi->common.frame_to_show->corrupted;
 | 
			
		||||
    } else {
 | 
			
		||||
      return VPX_CODEC_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    return VPX_CODEC_OK;
 | 
			
		||||
  } else {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
@@ -576,9 +743,17 @@ static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
 | 
			
		||||
                                             va_list args) {
 | 
			
		||||
  int *const display_size = va_arg(args, int *);
 | 
			
		||||
 | 
			
		||||
  // Only support this function in serial decode.
 | 
			
		||||
  if (ctx->frame_parallel_decode) {
 | 
			
		||||
    set_error_detail(ctx, "Not supported in frame parallel decode");
 | 
			
		||||
    return VPX_CODEC_INCAPABLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (display_size) {
 | 
			
		||||
    if (ctx->pbi) {
 | 
			
		||||
      const VP9_COMMON *const cm = &ctx->pbi->common;
 | 
			
		||||
    if (ctx->frame_workers) {
 | 
			
		||||
      VP9Worker *const worker = ctx->frame_workers;
 | 
			
		||||
      FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
 | 
			
		||||
      const VP9_COMMON *const cm = &worker_data->pbi->common;
 | 
			
		||||
      display_size[0] = cm->display_width;
 | 
			
		||||
      display_size[1] = cm->display_height;
 | 
			
		||||
    } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -105,11 +105,9 @@ VP9_CX_SRCS-$(HAVE_SSE3) += encoder/x86/vp9_sad_sse3.asm
 | 
			
		||||
ifeq ($(CONFIG_USE_X86INC),yes)
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_dct_mmx.asm
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_error_sse2.asm
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_error_intrin_avx2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad_sse2.asm
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subtract_sse2.asm
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_sse2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_variance_avx2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subpel_variance.asm
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
@@ -124,7 +122,9 @@ VP9_CX_SRCS-$(ARCH_X86_64) += encoder/x86/vp9_ssim_opt_x86_64.asm
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_dct_sse2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_dct32x32_sse2.c
 | 
			
		||||
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_dct_avx2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_dct32x32_avx2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_dct_avx2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_error_intrin_avx2.c
 | 
			
		||||
VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_variance_avx2.c
 | 
			
		||||
 | 
			
		||||
VP9_CX_SRCS-yes := $(filter-out $(VP9_CX_SRCS_REMOVE-yes),$(VP9_CX_SRCS-yes))
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include "vpx/svc_context.h"
 | 
			
		||||
#include "vpx/vp8cx.h"
 | 
			
		||||
#include "vpx/vpx_encoder.h"
 | 
			
		||||
#include "vpx_mem/vpx_mem.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __MINGW32__
 | 
			
		||||
#define strtok_r strtok_s
 | 
			
		||||
@@ -47,6 +48,14 @@ _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
 | 
			
		||||
static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27";
 | 
			
		||||
static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16";
 | 
			
		||||
 | 
			
		||||
// One encoded frame
 | 
			
		||||
typedef struct FrameData {
 | 
			
		||||
  void                     *buf;    // compressed data buffer
 | 
			
		||||
  size_t                    size;  // length of compressed data
 | 
			
		||||
  vpx_codec_frame_flags_t   flags;    /**< flags for this frame */
 | 
			
		||||
  struct FrameData         *next;
 | 
			
		||||
} FrameData;
 | 
			
		||||
 | 
			
		||||
typedef struct SvcInternal {
 | 
			
		||||
  char options[OPTION_BUFFER_SIZE];        // set by vpx_svc_set_options
 | 
			
		||||
  char quantizers[OPTION_BUFFER_SIZE];     // set by vpx_svc_set_quantizers
 | 
			
		||||
@@ -72,15 +81,15 @@ typedef struct SvcInternal {
 | 
			
		||||
 | 
			
		||||
  // state variables
 | 
			
		||||
  int encode_frame_count;
 | 
			
		||||
  int frame_received;
 | 
			
		||||
  int frame_within_gop;
 | 
			
		||||
  vpx_enc_frame_flags_t enc_frame_flags;
 | 
			
		||||
  int layers;
 | 
			
		||||
  int layer;
 | 
			
		||||
  int is_keyframe;
 | 
			
		||||
 | 
			
		||||
  size_t frame_size;
 | 
			
		||||
  size_t buffer_size;
 | 
			
		||||
  void *buffer;
 | 
			
		||||
  FrameData *frame_list;
 | 
			
		||||
  FrameData *frame_temp;
 | 
			
		||||
 | 
			
		||||
  char *rc_stats_buf;
 | 
			
		||||
  size_t rc_stats_buf_size;
 | 
			
		||||
@@ -90,128 +99,54 @@ typedef struct SvcInternal {
 | 
			
		||||
  vpx_codec_ctx_t *codec_ctx;
 | 
			
		||||
} SvcInternal;
 | 
			
		||||
 | 
			
		||||
// Superframe is used to generate an index of individual frames (i.e., layers)
 | 
			
		||||
struct Superframe {
 | 
			
		||||
  int count;
 | 
			
		||||
  uint32_t sizes[SUPERFRAME_SLOTS];
 | 
			
		||||
  uint32_t magnitude;
 | 
			
		||||
  uint8_t buffer[SUPERFRAME_BUFFER_SIZE];
 | 
			
		||||
  size_t index_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// One encoded frame layer
 | 
			
		||||
struct LayerData {
 | 
			
		||||
  void *buf;    // compressed data buffer
 | 
			
		||||
  size_t size;  // length of compressed data
 | 
			
		||||
  struct LayerData *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// create LayerData from encoder output
 | 
			
		||||
static struct LayerData *ld_create(void *buf, size_t size) {
 | 
			
		||||
  struct LayerData *const layer_data =
 | 
			
		||||
      (struct LayerData *)malloc(sizeof(*layer_data));
 | 
			
		||||
  if (layer_data == NULL) {
 | 
			
		||||
// create FrameData from encoder output
 | 
			
		||||
static struct FrameData *fd_create(void *buf, size_t size,
 | 
			
		||||
                                   vpx_codec_frame_flags_t flags) {
 | 
			
		||||
  struct FrameData *const frame_data =
 | 
			
		||||
      (struct FrameData *)vpx_malloc(sizeof(*frame_data));
 | 
			
		||||
  if (frame_data == NULL) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  layer_data->buf = malloc(size);
 | 
			
		||||
  if (layer_data->buf == NULL) {
 | 
			
		||||
    free(layer_data);
 | 
			
		||||
  frame_data->buf = vpx_malloc(size);
 | 
			
		||||
  if (frame_data->buf == NULL) {
 | 
			
		||||
    vpx_free(frame_data);
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  memcpy(layer_data->buf, buf, size);
 | 
			
		||||
  layer_data->size = size;
 | 
			
		||||
  return layer_data;
 | 
			
		||||
  vpx_memcpy(frame_data->buf, buf, size);
 | 
			
		||||
  frame_data->size = size;
 | 
			
		||||
  frame_data->flags = flags;
 | 
			
		||||
  return frame_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// free LayerData
 | 
			
		||||
static void ld_free(struct LayerData *layer_data) {
 | 
			
		||||
  if (layer_data) {
 | 
			
		||||
    if (layer_data->buf) {
 | 
			
		||||
      free(layer_data->buf);
 | 
			
		||||
      layer_data->buf = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    free(layer_data);
 | 
			
		||||
// free FrameData
 | 
			
		||||
static void fd_free(struct FrameData *p) {
 | 
			
		||||
  if (p) {
 | 
			
		||||
    if (p->buf)
 | 
			
		||||
      vpx_free(p->buf);
 | 
			
		||||
    vpx_free(p);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// add layer data to list
 | 
			
		||||
static void ld_list_add(struct LayerData **list, struct LayerData *layer_data) {
 | 
			
		||||
  struct LayerData **p = list;
 | 
			
		||||
// add FrameData to list
 | 
			
		||||
static void fd_list_add(struct FrameData **list, struct FrameData *layer_data) {
 | 
			
		||||
  struct FrameData **p = list;
 | 
			
		||||
 | 
			
		||||
  while (*p != NULL) p = &(*p)->next;
 | 
			
		||||
  *p = layer_data;
 | 
			
		||||
  layer_data->next = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get accumulated size of layer data
 | 
			
		||||
static size_t ld_list_get_buffer_size(struct LayerData *list) {
 | 
			
		||||
  struct LayerData *p;
 | 
			
		||||
  size_t size = 0;
 | 
			
		||||
 | 
			
		||||
  for (p = list; p != NULL; p = p->next) {
 | 
			
		||||
    size += p->size;
 | 
			
		||||
  }
 | 
			
		||||
  return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// copy layer data to buffer
 | 
			
		||||
static void ld_list_copy_to_buffer(struct LayerData *list, uint8_t *buffer) {
 | 
			
		||||
  struct LayerData *p;
 | 
			
		||||
 | 
			
		||||
  for (p = list; p != NULL; p = p->next) {
 | 
			
		||||
    buffer[0] = 1;
 | 
			
		||||
    memcpy(buffer, p->buf, p->size);
 | 
			
		||||
    buffer += p->size;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// free layer data list
 | 
			
		||||
static void ld_list_free(struct LayerData *list) {
 | 
			
		||||
  struct LayerData *p = list;
 | 
			
		||||
// free FrameData list
 | 
			
		||||
static void fd_free_list(struct FrameData *list) {
 | 
			
		||||
  struct FrameData *p = list;
 | 
			
		||||
 | 
			
		||||
  while (p) {
 | 
			
		||||
    list = list->next;
 | 
			
		||||
    ld_free(p);
 | 
			
		||||
    fd_free(p);
 | 
			
		||||
    p = list;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sf_create_index(struct Superframe *sf) {
 | 
			
		||||
  uint8_t marker = 0xc0;
 | 
			
		||||
  int i;
 | 
			
		||||
  uint32_t mag, mask;
 | 
			
		||||
  uint8_t *bufp;
 | 
			
		||||
 | 
			
		||||
  if (sf->count == 0 || sf->count >= 8) return;
 | 
			
		||||
 | 
			
		||||
  // Add the number of frames to the marker byte
 | 
			
		||||
  marker |= sf->count - 1;
 | 
			
		||||
 | 
			
		||||
  // Choose the magnitude
 | 
			
		||||
  for (mag = 0, mask = 0xff; mag < 4; ++mag) {
 | 
			
		||||
    if (sf->magnitude < mask) break;
 | 
			
		||||
    mask <<= 8;
 | 
			
		||||
    mask |= 0xff;
 | 
			
		||||
  }
 | 
			
		||||
  marker |= mag << 3;
 | 
			
		||||
 | 
			
		||||
  // Write the index
 | 
			
		||||
  sf->index_size = 2 + (mag + 1) * sf->count;
 | 
			
		||||
  bufp = sf->buffer;
 | 
			
		||||
 | 
			
		||||
  *bufp++ = marker;
 | 
			
		||||
  for (i = 0; i < sf->count; ++i) {
 | 
			
		||||
    int this_sz = sf->sizes[i];
 | 
			
		||||
    uint32_t j;
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j <= mag; ++j) {
 | 
			
		||||
      *bufp++ = this_sz & 0xff;
 | 
			
		||||
      this_sz >>= 8;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  *bufp++ = marker;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SvcInternal *get_svc_internal(SvcContext *svc_ctx) {
 | 
			
		||||
  if (svc_ctx == NULL) return NULL;
 | 
			
		||||
  if (svc_ctx->internal == NULL) {
 | 
			
		||||
@@ -574,8 +509,6 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
			
		||||
  // modify encoder configuration
 | 
			
		||||
  enc_cfg->ss_number_layers = si->layers;
 | 
			
		||||
  enc_cfg->ts_number_layers = 1;  // Temporal layers not used in this encoder.
 | 
			
		||||
  // Lag in frames not currently supported
 | 
			
		||||
  enc_cfg->g_lag_in_frames = 0;
 | 
			
		||||
 | 
			
		||||
  // TODO(ivanmaltz): determine if these values need to be set explicitly for
 | 
			
		||||
  // svc, or if the normal default/override mechanism can be used
 | 
			
		||||
@@ -608,6 +541,34 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
			
		||||
  return VPX_CODEC_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void accumulate_frame_size_for_each_layer(SvcInternal *const si,
 | 
			
		||||
                                                 const uint8_t *const buf,
 | 
			
		||||
                                                 const size_t size) {
 | 
			
		||||
  uint8_t marker = buf[size - 1];
 | 
			
		||||
  if ((marker & 0xe0) == 0xc0) {
 | 
			
		||||
    const uint32_t frames = (marker & 0x7) + 1;
 | 
			
		||||
    const uint32_t mag = ((marker >> 3) & 0x3) + 1;
 | 
			
		||||
    const size_t index_sz = 2 + mag * frames;
 | 
			
		||||
 | 
			
		||||
    uint8_t marker2 = buf[size - index_sz];
 | 
			
		||||
 | 
			
		||||
    if (size >= index_sz && marker2 == marker) {
 | 
			
		||||
      // found a valid superframe index
 | 
			
		||||
      uint32_t i, j;
 | 
			
		||||
      const uint8_t *x = &buf[size - index_sz + 1];
 | 
			
		||||
 | 
			
		||||
      // frames has a maximum of 8 and mag has a maximum of 4.
 | 
			
		||||
      for (i = 0; i < frames; i++) {
 | 
			
		||||
        uint32_t this_sz = 0;
 | 
			
		||||
 | 
			
		||||
        for (j = 0; j < mag; j++)
 | 
			
		||||
          this_sz |= (*x++) << (j * 8);
 | 
			
		||||
        si->bytes_sum[i] += this_sz;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SVC Algorithm flags - these get mapped to VP8_EFLAG_* defined in vp8cx.h
 | 
			
		||||
 | 
			
		||||
// encoder should reference the last frame
 | 
			
		||||
@@ -846,15 +807,12 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
			
		||||
  vpx_codec_err_t res;
 | 
			
		||||
  vpx_codec_iter_t iter;
 | 
			
		||||
  const vpx_codec_cx_pkt_t *cx_pkt;
 | 
			
		||||
  struct LayerData *cx_layer_list = NULL;
 | 
			
		||||
  struct LayerData *layer_data;
 | 
			
		||||
  struct Superframe superframe;
 | 
			
		||||
  int layer_for_psnr = 0;
 | 
			
		||||
  SvcInternal *const si = get_svc_internal(svc_ctx);
 | 
			
		||||
  if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) {
 | 
			
		||||
    return VPX_CODEC_INVALID_PARAM;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  memset(&superframe, 0, sizeof(superframe));
 | 
			
		||||
  svc_log_reset(svc_ctx);
 | 
			
		||||
  si->rc_stats_buf_used = 0;
 | 
			
		||||
 | 
			
		||||
@@ -863,7 +821,6 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
			
		||||
    si->frame_within_gop = 0;
 | 
			
		||||
  }
 | 
			
		||||
  si->is_keyframe = (si->frame_within_gop == 0);
 | 
			
		||||
  si->frame_size = 0;
 | 
			
		||||
 | 
			
		||||
  if (rawimg != NULL) {
 | 
			
		||||
    svc_log(svc_ctx, SVC_LOG_DEBUG,
 | 
			
		||||
@@ -872,124 +829,90 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
			
		||||
            si->frame_within_gop);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // encode each layer
 | 
			
		||||
  for (si->layer = 0; si->layer < si->layers; ++si->layer) {
 | 
			
		||||
    if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
 | 
			
		||||
        si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
 | 
			
		||||
      svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (rawimg != NULL) {
 | 
			
		||||
  if (rawimg != NULL) {
 | 
			
		||||
    // encode each layer
 | 
			
		||||
    for (si->layer = 0; si->layer < si->layers; ++si->layer) {
 | 
			
		||||
      if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
 | 
			
		||||
          si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
 | 
			
		||||
        svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      calculate_enc_frame_flags(svc_ctx);
 | 
			
		||||
      set_svc_parameters(svc_ctx, codec_ctx);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration,
 | 
			
		||||
                           si->enc_frame_flags, deadline);
 | 
			
		||||
    if (res != VPX_CODEC_OK) {
 | 
			
		||||
      return res;
 | 
			
		||||
    }
 | 
			
		||||
    // save compressed data
 | 
			
		||||
    iter = NULL;
 | 
			
		||||
    while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
 | 
			
		||||
      switch (cx_pkt->kind) {
 | 
			
		||||
        case VPX_CODEC_CX_FRAME_PKT: {
 | 
			
		||||
          const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz);
 | 
			
		||||
          si->bytes_sum[si->layer] += frame_pkt_size;
 | 
			
		||||
          svc_log(svc_ctx, SVC_LOG_DEBUG,
 | 
			
		||||
                  "SVC frame: %d, layer: %d, size: %u\n",
 | 
			
		||||
                  si->encode_frame_count, si->layer, frame_pkt_size);
 | 
			
		||||
          layer_data =
 | 
			
		||||
              ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size);
 | 
			
		||||
          if (layer_data == NULL) {
 | 
			
		||||
            svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n");
 | 
			
		||||
            return VPX_CODEC_OK;
 | 
			
		||||
  res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0,
 | 
			
		||||
                         deadline);
 | 
			
		||||
  if (res != VPX_CODEC_OK) {
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
  // save compressed data
 | 
			
		||||
  iter = NULL;
 | 
			
		||||
  while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
 | 
			
		||||
    switch (cx_pkt->kind) {
 | 
			
		||||
      case VPX_CODEC_CX_FRAME_PKT: {
 | 
			
		||||
        fd_list_add(&si->frame_list, fd_create(cx_pkt->data.frame.buf,
 | 
			
		||||
                                               cx_pkt->data.frame.sz,
 | 
			
		||||
                                               cx_pkt->data.frame.flags));
 | 
			
		||||
        accumulate_frame_size_for_each_layer(si, cx_pkt->data.frame.buf,
 | 
			
		||||
                                             cx_pkt->data.frame.sz);
 | 
			
		||||
 | 
			
		||||
        svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, "
 | 
			
		||||
                "pts: %d\n", si->frame_received,
 | 
			
		||||
                (cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? 1 : 0,
 | 
			
		||||
                (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
 | 
			
		||||
 | 
			
		||||
        ++si->frame_received;
 | 
			
		||||
        layer_for_psnr = 0;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case VPX_CODEC_PSNR_PKT: {
 | 
			
		||||
        int i;
 | 
			
		||||
        svc_log(svc_ctx, SVC_LOG_DEBUG,
 | 
			
		||||
                "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
 | 
			
		||||
                "%2.3f  %2.3f  %2.3f  %2.3f \n",
 | 
			
		||||
                si->frame_received, layer_for_psnr,
 | 
			
		||||
                cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
 | 
			
		||||
                cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
 | 
			
		||||
        svc_log(svc_ctx, SVC_LOG_DEBUG,
 | 
			
		||||
                "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
 | 
			
		||||
                "%2.3f  %2.3f  %2.3f  %2.3f \n",
 | 
			
		||||
                si->frame_received, layer_for_psnr,
 | 
			
		||||
                cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1],
 | 
			
		||||
                cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]);
 | 
			
		||||
        for (i = 0; i < COMPONENTS; i++) {
 | 
			
		||||
          si->psnr_sum[layer_for_psnr][i] += cx_pkt->data.psnr.psnr[i];
 | 
			
		||||
          si->sse_sum[layer_for_psnr][i] += cx_pkt->data.psnr.sse[i];
 | 
			
		||||
        }
 | 
			
		||||
        ++layer_for_psnr;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case VPX_CODEC_STATS_PKT: {
 | 
			
		||||
        size_t new_size = si->rc_stats_buf_used +
 | 
			
		||||
            cx_pkt->data.twopass_stats.sz;
 | 
			
		||||
 | 
			
		||||
        if (new_size > si->rc_stats_buf_size) {
 | 
			
		||||
          char *p = (char*)realloc(si->rc_stats_buf, new_size);
 | 
			
		||||
          if (p == NULL) {
 | 
			
		||||
            svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n");
 | 
			
		||||
            return VPX_CODEC_MEM_ERROR;
 | 
			
		||||
          }
 | 
			
		||||
          ld_list_add(&cx_layer_list, layer_data);
 | 
			
		||||
          si->rc_stats_buf = p;
 | 
			
		||||
          si->rc_stats_buf_size = new_size;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
          // save layer size in superframe index
 | 
			
		||||
          superframe.sizes[superframe.count++] = frame_pkt_size;
 | 
			
		||||
          superframe.magnitude |= frame_pkt_size;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        case VPX_CODEC_PSNR_PKT: {
 | 
			
		||||
          int i;
 | 
			
		||||
          svc_log(svc_ctx, SVC_LOG_DEBUG,
 | 
			
		||||
                  "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
 | 
			
		||||
                  "%2.3f  %2.3f  %2.3f  %2.3f \n",
 | 
			
		||||
                  si->encode_frame_count, si->layer,
 | 
			
		||||
                  cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
 | 
			
		||||
                  cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
 | 
			
		||||
          svc_log(svc_ctx, SVC_LOG_DEBUG,
 | 
			
		||||
                  "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
 | 
			
		||||
                  "%2.3f  %2.3f  %2.3f  %2.3f \n",
 | 
			
		||||
                  si->encode_frame_count, si->layer,
 | 
			
		||||
                  cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1],
 | 
			
		||||
                  cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]);
 | 
			
		||||
          for (i = 0; i < COMPONENTS; i++) {
 | 
			
		||||
            si->psnr_sum[si->layer][i] += cx_pkt->data.psnr.psnr[i];
 | 
			
		||||
            si->sse_sum[si->layer][i] += cx_pkt->data.psnr.sse[i];
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        case VPX_CODEC_STATS_PKT: {
 | 
			
		||||
          size_t new_size = si->rc_stats_buf_used +
 | 
			
		||||
              cx_pkt->data.twopass_stats.sz;
 | 
			
		||||
 | 
			
		||||
          if (new_size > si->rc_stats_buf_size) {
 | 
			
		||||
            char *p = (char*)realloc(si->rc_stats_buf, new_size);
 | 
			
		||||
            if (p == NULL) {
 | 
			
		||||
              svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n");
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            si->rc_stats_buf = p;
 | 
			
		||||
            si->rc_stats_buf_size = new_size;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          memcpy(si->rc_stats_buf + si->rc_stats_buf_used,
 | 
			
		||||
                 cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz);
 | 
			
		||||
          si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        memcpy(si->rc_stats_buf + si->rc_stats_buf_used,
 | 
			
		||||
               cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz);
 | 
			
		||||
        si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default: {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (rawimg == NULL) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (codec_ctx->config.enc->g_pass != VPX_RC_FIRST_PASS) {
 | 
			
		||||
    // add superframe index to layer data list
 | 
			
		||||
    sf_create_index(&superframe);
 | 
			
		||||
    layer_data = ld_create(superframe.buffer, superframe.index_size);
 | 
			
		||||
    ld_list_add(&cx_layer_list, layer_data);
 | 
			
		||||
 | 
			
		||||
    // get accumulated size of layer data
 | 
			
		||||
    si->frame_size = ld_list_get_buffer_size(cx_layer_list);
 | 
			
		||||
    if (si->frame_size > 0) {
 | 
			
		||||
      // all layers encoded, create single buffer with concatenated layers
 | 
			
		||||
      if (si->frame_size > si->buffer_size) {
 | 
			
		||||
        free(si->buffer);
 | 
			
		||||
        si->buffer = malloc(si->frame_size);
 | 
			
		||||
        if (si->buffer == NULL) {
 | 
			
		||||
          ld_list_free(cx_layer_list);
 | 
			
		||||
          return VPX_CODEC_MEM_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
        si->buffer_size = si->frame_size;
 | 
			
		||||
      }
 | 
			
		||||
      // copy layer data into packet
 | 
			
		||||
      ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer);
 | 
			
		||||
 | 
			
		||||
      ld_list_free(cx_layer_list);
 | 
			
		||||
 | 
			
		||||
      svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, "
 | 
			
		||||
              "pts: %d\n", si->encode_frame_count, si->is_keyframe,
 | 
			
		||||
              (int)si->frame_size, (int)pts);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (rawimg != NULL) {
 | 
			
		||||
    ++si->frame_within_gop;
 | 
			
		||||
    ++si->encode_frame_count;
 | 
			
		||||
@@ -1004,16 +927,27 @@ const char *vpx_svc_get_message(const SvcContext *svc_ctx) {
 | 
			
		||||
  return si->message_buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *vpx_svc_get_buffer(const SvcContext *svc_ctx) {
 | 
			
		||||
  const SvcInternal *const si = get_const_svc_internal(svc_ctx);
 | 
			
		||||
  if (svc_ctx == NULL || si == NULL) return NULL;
 | 
			
		||||
  return si->buffer;
 | 
			
		||||
// We will maintain a list of output frame buffers since with lag_in_frame
 | 
			
		||||
// we need to output all frame buffers at the end. vpx_svc_get_buffer() will
 | 
			
		||||
// remove a frame buffer from the list the put it to a temporal pointer, which
 | 
			
		||||
// will be removed at the next vpx_svc_get_buffer() or when closing encoder.
 | 
			
		||||
void *vpx_svc_get_buffer(SvcContext *svc_ctx) {
 | 
			
		||||
  SvcInternal *const si = get_svc_internal(svc_ctx);
 | 
			
		||||
  if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return NULL;
 | 
			
		||||
 | 
			
		||||
  if (si->frame_temp)
 | 
			
		||||
    fd_free(si->frame_temp);
 | 
			
		||||
 | 
			
		||||
  si->frame_temp = si->frame_list;
 | 
			
		||||
  si->frame_list = si->frame_list->next;
 | 
			
		||||
 | 
			
		||||
  return si->frame_temp->buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) {
 | 
			
		||||
  const SvcInternal *const si = get_const_svc_internal(svc_ctx);
 | 
			
		||||
  if (svc_ctx == NULL || si == NULL) return 0;
 | 
			
		||||
  return si->frame_size;
 | 
			
		||||
  if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return 0;
 | 
			
		||||
  return si->frame_list->size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) {
 | 
			
		||||
@@ -1024,8 +958,8 @@ int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) {
 | 
			
		||||
 | 
			
		||||
int vpx_svc_is_keyframe(const SvcContext *svc_ctx) {
 | 
			
		||||
  const SvcInternal *const si = get_const_svc_internal(svc_ctx);
 | 
			
		||||
  if (svc_ctx == NULL || si == NULL) return 0;
 | 
			
		||||
  return si->is_keyframe;
 | 
			
		||||
  if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return 0;
 | 
			
		||||
  return (si->frame_list->flags & VPX_FRAME_IS_KEY) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vpx_svc_set_keyframe(SvcContext *svc_ctx) {
 | 
			
		||||
@@ -1112,7 +1046,8 @@ void vpx_svc_release(SvcContext *svc_ctx) {
 | 
			
		||||
  // SvcInternal if it was not already allocated
 | 
			
		||||
  si = (SvcInternal *)svc_ctx->internal;
 | 
			
		||||
  if (si != NULL) {
 | 
			
		||||
    free(si->buffer);
 | 
			
		||||
    fd_free(si->frame_temp);
 | 
			
		||||
    fd_free_list(si->frame_list);
 | 
			
		||||
    if (si->rc_stats_buf) {
 | 
			
		||||
      free(si->rc_stats_buf);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -104,14 +104,16 @@ const char *vpx_svc_dump_statistics(SvcContext *svc_ctx);
 | 
			
		||||
const char *vpx_svc_get_message(const SvcContext *svc_ctx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * return size of encoded data to be returned by vpx_svc_get_buffer
 | 
			
		||||
 * return size of encoded data to be returned by vpx_svc_get_buffer.
 | 
			
		||||
 * it needs to be called before vpx_svc_get_buffer.
 | 
			
		||||
 */
 | 
			
		||||
size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * return buffer with encoded data
 | 
			
		||||
 * return buffer with encoded data. encoder will maintain a list of frame
 | 
			
		||||
 * buffers. each call of vpx_svc_get_buffer() will return one frame.
 | 
			
		||||
 */
 | 
			
		||||
void *vpx_svc_get_buffer(const SvcContext *svc_ctx);
 | 
			
		||||
void *vpx_svc_get_buffer(SvcContext *svc_ctx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * return size of two pass rate control stats data to be returned by
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user