summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure8
-rw-r--r--third_party/libwebm/Android.mk2
-rw-r--r--third_party/libwebm/README.libvpx14
-rw-r--r--third_party/libwebm/common/file_util.cc15
-rw-r--r--third_party/libwebm/common/file_util.h5
-rw-r--r--third_party/libwebm/common/hdr_util.cc8
-rw-r--r--third_party/libwebm/common/hdr_util.h10
-rw-r--r--third_party/libwebm/mkvmuxer/mkvmuxer.cc25
-rw-r--r--third_party/libwebm/mkvparser/mkvparser.cc35
-rw-r--r--vp9/encoder/vp9_encodeframe.c46
-rw-r--r--vp9/encoder/vp9_encoder.c37
-rw-r--r--vp9/encoder/vp9_encoder.h3
-rw-r--r--vp9/encoder/vp9_rd.h7
-rw-r--r--vp9/encoder/vp9_rdopt.c8
14 files changed, 174 insertions, 49 deletions
diff --git a/configure b/configure
index 3a1a318c9..feb27248c 100755
--- a/configure
+++ b/configure
@@ -721,9 +721,7 @@ process_toolchain() {
check_cxx "$@" <<EOF && soft_enable unit_tests
int z;
EOF
- check_cxx "$@" <<EOF && soft_enable webm_io
-int z;
-EOF
+ check_add_cxx_flags -std=c++11 && soft_enable webm_io
check_cxx "$@" <<EOF && soft_enable libyuv
int z;
EOF
@@ -732,9 +730,7 @@ EOF
enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests
int z;
EOF
- check_cxx "$@" <<EOF && soft_enable webm_io
-int z;
-EOF
+ check_add_cxx_flags -std=c++11 && soft_enable webm_io
check_cxx "$@" <<EOF && soft_enable libyuv
int z;
EOF
diff --git a/third_party/libwebm/Android.mk b/third_party/libwebm/Android.mk
index 8149a083f..b46ba101d 100644
--- a/third_party/libwebm/Android.mk
+++ b/third_party/libwebm/Android.mk
@@ -3,7 +3,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libwebm
LOCAL_CPPFLAGS:=-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS
-LOCAL_CPPFLAGS+=-D__STDC_LIMIT_MACROS -Wno-extern-c-compat
+LOCAL_CPPFLAGS+=-D__STDC_LIMIT_MACROS -std=c++11
LOCAL_C_INCLUDES:= $(LOCAL_PATH)
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)
diff --git a/third_party/libwebm/README.libvpx b/third_party/libwebm/README.libvpx
index ebb5ff2f4..6d8b0b4cc 100644
--- a/third_party/libwebm/README.libvpx
+++ b/third_party/libwebm/README.libvpx
@@ -1,5 +1,5 @@
URL: https://chromium.googlesource.com/webm/libwebm
-Version: 0ae757087f5e6eb01dfea16cc09205b2425cfb74
+Version: af81f26025b7435fa9a14ad07c58b44cf9280430
License: BSD
License File: LICENSE.txt
@@ -7,4 +7,14 @@ Description:
libwebm is used to handle WebM container I/O.
Local Changes:
-* <none>
+Only keep:
+ - Android.mk
+ - AUTHORS.TXT
+ - common/
+ file_util.cc/h
+ hdr_util.cc/h
+ webmids.h
+ - LICENSE.TXT
+ - mkvmuxer/
+ - mkvparser/
+ - PATENTS.TXT
diff --git a/third_party/libwebm/common/file_util.cc b/third_party/libwebm/common/file_util.cc
index 6dab146dd..618ffc087 100644
--- a/third_party/libwebm/common/file_util.cc
+++ b/third_party/libwebm/common/file_util.cc
@@ -17,6 +17,7 @@
#include <cstring>
#include <fstream>
#include <ios>
+#include <string>
namespace libwebm {
@@ -41,7 +42,12 @@ std::string GetTempFileName() {
return temp_file_name;
#else
char tmp_file_name[_MAX_PATH];
+#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
errno_t err = tmpnam_s(tmp_file_name);
+#else
+ char* fname_pointer = tmpnam(tmp_file_name);
+ errno_t err = (fname_pointer == &tmp_file_name[0]) ? 0 : -1;
+#endif
if (err == 0) {
return std::string(tmp_file_name);
}
@@ -65,6 +71,15 @@ uint64_t GetFileSize(const std::string& file_name) {
return file_size;
}
+bool GetFileContents(const std::string& file_name, std::string* contents) {
+ std::ifstream file(file_name.c_str());
+ *contents = std::string(static_cast<size_t>(GetFileSize(file_name)), 0);
+ if (file.good() && contents->size()) {
+ file.read(&(*contents)[0], contents->size());
+ }
+ return !file.fail();
+}
+
TempFileDeleter::TempFileDeleter() { file_name_ = GetTempFileName(); }
TempFileDeleter::~TempFileDeleter() {
diff --git a/third_party/libwebm/common/file_util.h b/third_party/libwebm/common/file_util.h
index 0e71eac11..a87373464 100644
--- a/third_party/libwebm/common/file_util.h
+++ b/third_party/libwebm/common/file_util.h
@@ -22,6 +22,9 @@ std::string GetTempFileName();
// Returns size of file specified by |file_name|, or 0 upon failure.
uint64_t GetFileSize(const std::string& file_name);
+// Gets the contents file_name as a string. Returns false on error.
+bool GetFileContents(const std::string& file_name, std::string* contents);
+
// Manages life of temporary file specified at time of construction. Deletes
// file upon destruction.
class TempFileDeleter {
@@ -38,4 +41,4 @@ class TempFileDeleter {
} // namespace libwebm
-#endif // LIBWEBM_COMMON_FILE_UTIL_H_ \ No newline at end of file
+#endif // LIBWEBM_COMMON_FILE_UTIL_H_
diff --git a/third_party/libwebm/common/hdr_util.cc b/third_party/libwebm/common/hdr_util.cc
index e1618ce75..916f7170b 100644
--- a/third_party/libwebm/common/hdr_util.cc
+++ b/third_party/libwebm/common/hdr_util.cc
@@ -36,10 +36,10 @@ bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm,
if (MasteringMetadataValuePresent(parser_mm.luminance_min))
muxer_mm->set_luminance_min(parser_mm.luminance_min);
- PrimaryChromaticityPtr r_ptr(NULL);
- PrimaryChromaticityPtr g_ptr(NULL);
- PrimaryChromaticityPtr b_ptr(NULL);
- PrimaryChromaticityPtr wp_ptr(NULL);
+ PrimaryChromaticityPtr r_ptr(nullptr);
+ PrimaryChromaticityPtr g_ptr(nullptr);
+ PrimaryChromaticityPtr b_ptr(nullptr);
+ PrimaryChromaticityPtr wp_ptr(nullptr);
if (parser_mm.r) {
if (!CopyPrimaryChromaticity(*parser_mm.r, &r_ptr))
diff --git a/third_party/libwebm/common/hdr_util.h b/third_party/libwebm/common/hdr_util.h
index 3ef5388fd..78e2eeb70 100644
--- a/third_party/libwebm/common/hdr_util.h
+++ b/third_party/libwebm/common/hdr_util.h
@@ -47,15 +47,7 @@ struct Vp9CodecFeatures {
int chroma_subsampling;
};
-// disable deprecation warnings for auto_ptr
-#if defined(__GNUC__) && __GNUC__ >= 5
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-typedef std::auto_ptr<mkvmuxer::PrimaryChromaticity> PrimaryChromaticityPtr;
-#if defined(__GNUC__) && __GNUC__ >= 5
-#pragma GCC diagnostic pop
-#endif
+typedef std::unique_ptr<mkvmuxer::PrimaryChromaticity> PrimaryChromaticityPtr;
bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
PrimaryChromaticityPtr* muxer_pc);
diff --git a/third_party/libwebm/mkvmuxer/mkvmuxer.cc b/third_party/libwebm/mkvmuxer/mkvmuxer.cc
index 15b9a908d..481771db2 100644
--- a/third_party/libwebm/mkvmuxer/mkvmuxer.cc
+++ b/third_party/libwebm/mkvmuxer/mkvmuxer.cc
@@ -8,6 +8,8 @@
#include "mkvmuxer/mkvmuxer.h"
+#include <stdint.h>
+
#include <cfloat>
#include <climits>
#include <cstdio>
@@ -24,11 +26,6 @@
#include "mkvmuxer/mkvwriter.h"
#include "mkvparser/mkvparser.h"
-// disable deprecation warnings for auto_ptr
-#if defined(__GNUC__) && __GNUC__ >= 5
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
namespace mkvmuxer {
const float PrimaryChromaticity::kChromaticityMin = 0.0f;
@@ -72,7 +69,7 @@ bool StrCpy(const char* src, char** dst_ptr) {
return true;
}
-typedef std::auto_ptr<PrimaryChromaticity> PrimaryChromaticityPtr;
+typedef std::unique_ptr<PrimaryChromaticity> PrimaryChromaticityPtr;
bool CopyChromaticity(const PrimaryChromaticity* src,
PrimaryChromaticityPtr* dst) {
if (!dst)
@@ -1057,22 +1054,22 @@ bool MasteringMetadata::Write(IMkvWriter* writer) const {
bool MasteringMetadata::SetChromaticity(
const PrimaryChromaticity* r, const PrimaryChromaticity* g,
const PrimaryChromaticity* b, const PrimaryChromaticity* white_point) {
- PrimaryChromaticityPtr r_ptr(NULL);
+ PrimaryChromaticityPtr r_ptr(nullptr);
if (r) {
if (!CopyChromaticity(r, &r_ptr))
return false;
}
- PrimaryChromaticityPtr g_ptr(NULL);
+ PrimaryChromaticityPtr g_ptr(nullptr);
if (g) {
if (!CopyChromaticity(g, &g_ptr))
return false;
}
- PrimaryChromaticityPtr b_ptr(NULL);
+ PrimaryChromaticityPtr b_ptr(nullptr);
if (b) {
if (!CopyChromaticity(b, &b_ptr))
return false;
}
- PrimaryChromaticityPtr wp_ptr(NULL);
+ PrimaryChromaticityPtr wp_ptr(nullptr);
if (white_point) {
if (!CopyChromaticity(white_point, &wp_ptr))
return false;
@@ -1238,7 +1235,7 @@ bool Colour::Write(IMkvWriter* writer) const {
}
bool Colour::SetMasteringMetadata(const MasteringMetadata& mastering_metadata) {
- std::auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
+ std::unique_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
if (!mm_ptr.get())
return false;
@@ -1546,7 +1543,7 @@ bool VideoTrack::Write(IMkvWriter* writer) const {
}
bool VideoTrack::SetColour(const Colour& colour) {
- std::auto_ptr<Colour> colour_ptr(new Colour());
+ std::unique_ptr<Colour> colour_ptr(new Colour());
if (!colour_ptr.get())
return false;
@@ -1574,7 +1571,7 @@ bool VideoTrack::SetColour(const Colour& colour) {
}
bool VideoTrack::SetProjection(const Projection& projection) {
- std::auto_ptr<Projection> projection_ptr(new Projection());
+ std::unique_ptr<Projection> projection_ptr(new Projection());
if (!projection_ptr.get())
return false;
@@ -2666,7 +2663,7 @@ bool Cluster::QueueOrWriteFrame(const Frame* const frame) {
// and write it if it is okay to do so (i.e.) no other track has an held back
// frame with timestamp <= the timestamp of the frame in question.
std::vector<std::list<Frame*>::iterator> frames_to_erase;
- for (std::list<Frame *>::iterator
+ for (std::list<Frame*>::iterator
current_track_iterator = stored_frames_[track_number].begin(),
end = --stored_frames_[track_number].end();
current_track_iterator != end; ++current_track_iterator) {
diff --git a/third_party/libwebm/mkvparser/mkvparser.cc b/third_party/libwebm/mkvparser/mkvparser.cc
index 37f230d0a..e7b76f7da 100644
--- a/third_party/libwebm/mkvparser/mkvparser.cc
+++ b/third_party/libwebm/mkvparser/mkvparser.cc
@@ -22,12 +22,8 @@
#include "common/webmids.h"
-// disable deprecation warnings for auto_ptr
-#if defined(__GNUC__) && __GNUC__ >= 5
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
namespace mkvparser {
+const long long kStringElementSizeLimit = 20 * 1000 * 1000;
const float MasteringMetadata::kValueNotPresent = FLT_MAX;
const long long Colour::kValueNotPresent = LLONG_MAX;
const float Projection::kValueNotPresent = FLT_MAX;
@@ -330,7 +326,7 @@ long UnserializeString(IMkvReader* pReader, long long pos, long long size,
delete[] str;
str = NULL;
- if (size >= LONG_MAX || size < 0)
+ if (size >= LONG_MAX || size < 0 || size > kStringElementSizeLimit)
return E_FILE_FORMAT_INVALID;
// +1 for '\0' terminator
@@ -5015,7 +5011,7 @@ bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start,
if (!reader || *mm)
return false;
- std::auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
+ std::unique_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
if (!mm_ptr.get())
return false;
@@ -5035,6 +5031,10 @@ bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start,
double value = 0;
const long long value_parse_status =
UnserializeFloat(reader, read_pos, child_size, value);
+ if (value < -FLT_MAX || value > FLT_MAX ||
+ (value > 0.0 && value < FLT_MIN)) {
+ return false;
+ }
mm_ptr->luminance_max = static_cast<float>(value);
if (value_parse_status < 0 || mm_ptr->luminance_max < 0.0 ||
mm_ptr->luminance_max > 9999.99) {
@@ -5044,6 +5044,10 @@ bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start,
double value = 0;
const long long value_parse_status =
UnserializeFloat(reader, read_pos, child_size, value);
+ if (value < -FLT_MAX || value > FLT_MAX ||
+ (value > 0.0 && value < FLT_MIN)) {
+ return false;
+ }
mm_ptr->luminance_min = static_cast<float>(value);
if (value_parse_status < 0 || mm_ptr->luminance_min < 0.0 ||
mm_ptr->luminance_min > 999.9999) {
@@ -5096,7 +5100,7 @@ bool Colour::Parse(IMkvReader* reader, long long colour_start,
if (!reader || *colour)
return false;
- std::auto_ptr<Colour> colour_ptr(new Colour());
+ std::unique_ptr<Colour> colour_ptr(new Colour());
if (!colour_ptr.get())
return false;
@@ -5194,7 +5198,7 @@ bool Projection::Parse(IMkvReader* reader, long long start, long long size,
if (!reader || *projection)
return false;
- std::auto_ptr<Projection> projection_ptr(new Projection());
+ std::unique_ptr<Projection> projection_ptr(new Projection());
if (!projection_ptr.get())
return false;
@@ -7903,6 +7907,10 @@ long Block::Parse(const Cluster* pCluster) {
return E_FILE_FORMAT_INVALID;
curr.len = static_cast<long>(frame_size);
+ // Check if size + curr.len could overflow.
+ if (size > LLONG_MAX - curr.len) {
+ return E_FILE_FORMAT_INVALID;
+ }
size += curr.len; // contribution of this frame
--frame_count;
@@ -7964,6 +7972,11 @@ long long Block::GetTimeCode(const Cluster* pCluster) const {
const long long tc0 = pCluster->GetTimeCode();
assert(tc0 >= 0);
+ // Check if tc0 + m_timecode would overflow.
+ if (tc0 < 0 || LLONG_MAX - tc0 < m_timecode) {
+ return -1;
+ }
+
const long long tc = tc0 + m_timecode;
return tc; // unscaled timecode units
@@ -7981,6 +7994,10 @@ long long Block::GetTime(const Cluster* pCluster) const {
const long long scale = pInfo->GetTimeCodeScale();
assert(scale >= 1);
+ // Check if tc * scale could overflow.
+ if (tc != 0 && scale > LLONG_MAX / tc) {
+ return -1;
+ }
const long long ns = tc * scale;
return ns;
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 091992dbd..1c86af506 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -4663,6 +4663,9 @@ void vp9_init_tile_data(VP9_COMP *cpi) {
for (i = 0; i < BLOCK_SIZES; ++i) {
for (j = 0; j < MAX_MODES; ++j) {
tile_data->thresh_freq_fact[i][j] = RD_THRESH_INIT_FACT;
+#if CONSISTENT_RECODE_STATE
+ tile_data->thresh_freq_fact_prev[i][j] = RD_THRESH_INIT_FACT;
+#endif
tile_data->mode_map[i][j] = j;
}
}
@@ -4787,7 +4790,9 @@ static void encode_frame_internal(VP9_COMP *cpi) {
x->fwd_txfm4x4 = xd->lossless ? vp9_fwht4x4 : vpx_fdct4x4;
#endif // CONFIG_VP9_HIGHBITDEPTH
x->inv_txfm_add = xd->lossless ? vp9_iwht4x4_add : vp9_idct4x4_add;
-
+#if CONSISTENT_RECODE_STATE
+ x->optimize = sf->optimize_coefficients == 1 && cpi->oxcf.pass != 1;
+#endif
if (xd->lossless) x->optimize = 0;
cm->tx_mode = select_tx_mode(cpi, xd);
@@ -4912,9 +4917,48 @@ static int compute_frame_aq_offset(struct VP9_COMP *cpi) {
return sum_delta / (cm->mi_rows * cm->mi_cols);
}
+#if CONSISTENT_RECODE_STATE
+static void restore_encode_params(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ const int tile_cols = 1 << cm->log2_tile_cols;
+ const int tile_rows = 1 << cm->log2_tile_rows;
+ int tile_col, tile_row;
+ int i, j;
+ RD_OPT *rd_opt = &cpi->rd;
+ for (i = 0; i < MAX_REF_FRAMES; i++) {
+ for (j = 0; j < REFERENCE_MODES; j++)
+ rd_opt->prediction_type_threshes[i][j] =
+ rd_opt->prediction_type_threshes_prev[i][j];
+
+ for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; j++)
+ rd_opt->filter_threshes[i][j] = rd_opt->filter_threshes_prev[i][j];
+ }
+
+ if (cpi->tile_data != NULL) {
+ for (tile_row = 0; tile_row < tile_rows; ++tile_row)
+ for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
+ TileDataEnc *tile_data =
+ &cpi->tile_data[tile_row * tile_cols + tile_col];
+ for (i = 0; i < BLOCK_SIZES; ++i) {
+ for (j = 0; j < MAX_MODES; ++j) {
+ tile_data->thresh_freq_fact[i][j] =
+ tile_data->thresh_freq_fact_prev[i][j];
+ }
+ }
+ }
+ }
+
+ cm->interp_filter = cpi->sf.default_interp_filter;
+}
+#endif
+
void vp9_encode_frame(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
+#if CONSISTENT_RECODE_STATE
+ restore_encode_params(cpi);
+#endif
+
// In the longer term the encoder should be generalized to match the
// decoder such that we allow compound where one of the 3 buffers has a
// different sign bias and that buffer is then the fixed ref. However, this
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 997fae2ba..c680f97e2 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -3579,6 +3579,39 @@ static void set_frame_size(VP9_COMP *cpi) {
set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME);
}
+#if CONSISTENT_RECODE_STATE
+static void save_encode_params(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ const int tile_cols = 1 << cm->log2_tile_cols;
+ const int tile_rows = 1 << cm->log2_tile_rows;
+ int tile_col, tile_row;
+ int i, j;
+ RD_OPT *rd_opt = &cpi->rd;
+ for (i = 0; i < MAX_REF_FRAMES; i++) {
+ for (j = 0; j < REFERENCE_MODES; j++)
+ rd_opt->prediction_type_threshes_prev[i][j] =
+ rd_opt->prediction_type_threshes[i][j];
+
+ for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; j++)
+ rd_opt->filter_threshes_prev[i][j] = rd_opt->filter_threshes[i][j];
+ }
+
+ if (cpi->tile_data != NULL) {
+ for (tile_row = 0; tile_row < tile_rows; ++tile_row)
+ for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
+ TileDataEnc *tile_data =
+ &cpi->tile_data[tile_row * tile_cols + tile_col];
+ for (i = 0; i < BLOCK_SIZES; ++i) {
+ for (j = 0; j < MAX_MODES; ++j) {
+ tile_data->thresh_freq_fact_prev[i][j] =
+ tile_data->thresh_freq_fact[i][j];
+ }
+ }
+ }
+ }
+}
+#endif
+
static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size,
uint8_t *dest) {
VP9_COMMON *const cm = &cpi->common;
@@ -4611,6 +4644,10 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size,
memset(cpi->mode_chosen_counts, 0,
MAX_MODES * sizeof(*cpi->mode_chosen_counts));
#endif
+#if CONSISTENT_RECODE_STATE
+ // Backup to ensure consistency between recodes
+ save_encode_params(cpi);
+#endif
if (cpi->sf.recode_loop == DISALLOW_RECODE) {
encode_without_recode_loop(cpi, size, dest);
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 1e0ed70fb..786fbf016 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -282,6 +282,9 @@ static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
typedef struct TileDataEnc {
TileInfo tile_info;
int thresh_freq_fact[BLOCK_SIZES][MAX_MODES];
+#if CONSISTENT_RECODE_STATE
+ int thresh_freq_fact_prev[BLOCK_SIZES][MAX_MODES];
+#endif
int8_t mode_map[BLOCK_SIZES][MAX_MODES];
FIRSTPASS_DATA fp_data;
VP9RowMTSync row_mt_sync;
diff --git a/vp9/encoder/vp9_rd.h b/vp9/encoder/vp9_rd.h
index 59022c106..c1bd9ed30 100644
--- a/vp9/encoder/vp9_rd.h
+++ b/vp9/encoder/vp9_rd.h
@@ -23,6 +23,9 @@
extern "C" {
#endif
+// This macro defines the control for consistent recode behaviour
+#define CONSISTENT_RECODE_STATE 0
+
#define RDDIV_BITS 7
#define RD_EPB_SHIFT 6
@@ -108,7 +111,11 @@ typedef struct RD_OPT {
int64_t prediction_type_threshes[MAX_REF_FRAMES][REFERENCE_MODES];
int64_t filter_threshes[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
+#if CONSISTENT_RECODE_STATE
+ int64_t prediction_type_threshes_prev[MAX_REF_FRAMES][REFERENCE_MODES];
+ int64_t filter_threshes_prev[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
+#endif
int RDMULT;
int RDDIV;
} RD_OPT;
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index e39df033a..977c19e65 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3612,9 +3612,13 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
}
if (best_mode_index < 0 || best_rd >= best_rd_so_far) {
- // If adaptive interp filter is enabled, then the current leaf node of 8x8
- // data is needed for sub8x8. Hence preserve the context.
+// If adaptive interp filter is enabled, then the current leaf node of 8x8
+// data is needed for sub8x8. Hence preserve the context.
+#if CONSISTENT_RECODE_STATE
+ if (bsize == BLOCK_8X8) ctx->mic = *xd->mi[0];
+#else
if (cpi->row_mt && bsize == BLOCK_8X8) ctx->mic = *xd->mi[0];
+#endif
rd_cost->rate = INT_MAX;
rd_cost->rdcost = INT64_MAX;
return;