Remove hash-me table from frame buffers

The memory for the hash table used to be deallocated in the next frame
to facilitate integer mv precision decision. The integer mv precision
decision was later changed to become independent of the hash table, and
the code for memory deallocation was remove with it. As a result, we
could leak memory during the encode.

Since the hash table is now only used by intrabc, this CL removes the
hash tables from the frame buffers, and instead only allocate one in
encode_frame_internal.

Change-Id: I9b8f3ee389680c93f6ec79c0fa1ae119964149d3
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h
index d561e66..62a3233 100644
--- a/av1/common/av1_common_int.h
+++ b/av1/common/av1_common_int.h
@@ -149,7 +149,6 @@
   aom_film_grain_t film_grain_params;
   aom_codec_frame_buffer_t raw_frame_buffer;
   YV12_BUFFER_CONFIG buf;
-  hash_table hash_table;
   FRAME_TYPE frame_type;
 
   // This is only used in the encoder but needs to be indexed per ref frame
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index af463a7..069d101 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -314,6 +314,7 @@
   // [first hash/second hash]
   // [two buffers used ping-pong]
   uint32_t *hash_value_buffer[2][2];
+  hash_table intrabc_hash_table;
 
   CRC_CALCULATOR crc_calculator1;
   CRC_CALCULATOR crc_calculator2;
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index e41bd5c..d0db89a 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -5633,6 +5633,8 @@
 
   if (!is_stat_generation_stage(cpi) && av1_use_hash_me(cpi) &&
       !cpi->sf.rt_sf.use_nonrd_pick_mode) {
+    // TODO(any): move this outside of the recoding loop to avoid recalculating
+    // the hash table.
     // add to hash table
     const int pic_width = cpi->source->y_crop_width;
     const int pic_height = cpi->source->y_crop_height;
@@ -5652,7 +5654,8 @@
       }
     }
 
-    av1_hash_table_create(&cm->cur_frame->hash_table);
+    av1_hash_table_init(&x->intrabc_hash_table, x);
+    av1_hash_table_create(&x->intrabc_hash_table);
     av1_generate_block_2x2_hash_value(cpi->source, block_hash_values[0],
                                       is_block_same[0], &cpi->td.mb);
     // Hash data generated for screen contents is used for intraBC ME
@@ -5667,7 +5670,7 @@
           is_block_same[dst_idx], &cpi->td.mb);
       if (size >= min_alloc_size) {
         av1_add_to_hash_map_by_row_with_precal_data(
-            &cm->cur_frame->hash_table, block_hash_values[dst_idx],
+            &x->intrabc_hash_table, block_hash_values[dst_idx],
             is_block_same[dst_idx][2], pic_width, pic_height, size);
       }
     }
@@ -5973,6 +5976,11 @@
       }
     }
   }
+
+  if (!is_stat_generation_stage(cpi) && av1_use_hash_me(cpi) &&
+      !cpi->sf.rt_sf.use_nonrd_pick_mode) {
+    av1_hash_table_destroy(&x->intrabc_hash_table);
+  }
 }
 
 void av1_encode_frame(AV1_COMP *cpi) {
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e82365e..c384f33 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3455,7 +3455,6 @@
 
 void av1_remove_compressor(AV1_COMP *cpi) {
   AV1_COMMON *cm;
-  unsigned int i;
   int t;
 
   if (!cpi) return;
@@ -3621,9 +3620,6 @@
 #endif  // CONFIG_INTERNAL_STATS
 
   av1_remove_common(cm);
-  for (i = 0; i < FRAME_BUFFERS; ++i) {
-    av1_hash_table_destroy(&cm->buffer_pool->frame_bufs[i].hash_table);
-  }
 #if CONFIG_HTB_TRELLIS
   if (cpi->sf.use_hash_based_trellis) hbt_destroy();
 #endif  // CONFIG_HTB_TRELLIS
@@ -4267,11 +4263,6 @@
   for (i = 0; i < FRAME_BUFFERS; ++i) {
     pool->frame_bufs[i].ref_count = 0;
   }
-  if (cm->seq_params.force_screen_content_tools) {
-    for (i = 0; i < FRAME_BUFFERS; ++i) {
-      av1_hash_table_init(&pool->frame_bufs[i].hash_table, &cpi->td.mb);
-    }
-  }
 }
 
 void av1_check_initial_width(AV1_COMP *cpi, int use_highbitdepth,
@@ -5248,7 +5239,6 @@
   cpi->is_screen_content_type = 1;
   cpi->sf.part_sf.partition_search_type = FIXED_PARTITION;
   cpi->sf.part_sf.always_this_block_size = BLOCK_32X32;
-  av1_hash_table_create(&cm->cur_frame->hash_table);
 }
 
 // Determines whether to use screen content tools for the key frame group.
@@ -5338,8 +5328,6 @@
         projected_size_pass, psnr);
   }
 
-  av1_hash_table_destroy(&cm->cur_frame->hash_table);
-
   // Set partition speed feature back.
   cpi->sf.part_sf.partition_search_type = partition_search_type_orig;
   cpi->sf.part_sf.always_this_block_size = fixed_partition_block_size_orig;
@@ -6192,20 +6180,6 @@
   }
 }
 
-#if CONFIG_DEBUG
-static int hash_me_has_at_most_two_refs(RefCntBuffer *frame_bufs) {
-  int total_count = 0;
-  for (int frame_idx = 0; frame_idx < FRAME_BUFFERS; ++frame_idx) {
-    if (frame_bufs[frame_idx].hash_table.has_content > 1) {
-      return 0;
-    }
-    total_count += frame_bufs[frame_idx].hash_table.has_content;
-  }
-
-  return total_count <= 2;
-}
-#endif
-
 extern void av1_print_frame_contexts(const FRAME_CONTEXT *fc,
                                      const char *filename);
 
@@ -6299,11 +6273,6 @@
     cpi->common.features.cur_frame_force_integer_mv = 0;
   }
 
-#if CONFIG_DEBUG
-  assert(hash_me_has_at_most_two_refs(cm->buffer_pool->frame_bufs) &&
-         "Hash-me is leaking memory!");
-#endif
-
   // Set default state for segment based loop filter update flags.
   cm->lf.mode_ref_delta_update = 0;
 
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index dce835a..31cdcae 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1375,14 +1375,6 @@
           frame_is_intra_only(&cpi->common));
 }
 
-static INLINE hash_table *av1_get_ref_frame_hash_map(
-    const AV1_COMMON *cm, MV_REFERENCE_FRAME ref_frame) {
-  const int map_idx = get_ref_frame_map_idx(cm, ref_frame);
-  RefCntBuffer *buf =
-      (map_idx != INVALID_IDX) ? cm->ref_frame_map[map_idx] : NULL;
-  return buf ? &buf->hash_table : NULL;
-}
-
 static INLINE const YV12_BUFFER_CONFIG *get_ref_frame_yv12_buf(
     const AV1_COMMON *const cm, MV_REFERENCE_FRAME ref_frame) {
   const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
diff --git a/av1/encoder/hash_motion.c b/av1/encoder/hash_motion.c
index dd0c77b..96a9de4 100644
--- a/av1/encoder/hash_motion.c
+++ b/av1/encoder/hash_motion.c
@@ -98,9 +98,6 @@
     x->g_crc_initialized = 1;
   }
   p_hash_table->p_lookup_table = NULL;
-#if CONFIG_DEBUG
-  p_hash_table->has_content = 0;
-#endif
 }
 
 void av1_hash_table_clear_all(hash_table *p_hash_table) {
@@ -114,18 +111,12 @@
       p_hash_table->p_lookup_table[i] = NULL;
     }
   }
-#if CONFIG_DEBUG
-  p_hash_table->has_content = 0;
-#endif
 }
 
 void av1_hash_table_destroy(hash_table *p_hash_table) {
   av1_hash_table_clear_all(p_hash_table);
   aom_free(p_hash_table->p_lookup_table);
   p_hash_table->p_lookup_table = NULL;
-#if CONFIG_DEBUG
-  p_hash_table->has_content = 0;
-#endif
 }
 
 void av1_hash_table_create(hash_table *p_hash_table) {
@@ -137,9 +128,6 @@
       (Vector **)aom_malloc(sizeof(p_hash_table->p_lookup_table[0]) * kMaxAddr);
   memset(p_hash_table->p_lookup_table, 0,
          sizeof(p_hash_table->p_lookup_table[0]) * kMaxAddr);
-#if CONFIG_DEBUG
-  p_hash_table->has_content = 0;
-#endif
 }
 
 static void hash_table_add_to_table(hash_table *p_hash_table,
@@ -328,9 +316,6 @@
   assert(add_value >= 0);
   add_value <<= kSrcBits;
   const int crc_mask = (1 << kSrcBits) - 1;
-#if CONFIG_DEBUG
-  p_hash_table->has_content = 1;
-#endif
 
   for (int x_pos = 0; x_pos < x_end; x_pos++) {
     for (int y_pos = 0; y_pos < y_end; y_pos++) {
diff --git a/av1/encoder/hash_motion.h b/av1/encoder/hash_motion.h
index 516e43d..e21c339 100644
--- a/av1/encoder/hash_motion.h
+++ b/av1/encoder/hash_motion.h
@@ -35,9 +35,6 @@
 
 typedef struct _hash_table {
   Vector **p_lookup_table;
-#if CONFIG_DEBUG
-  int has_content;
-#endif
 } hash_table;
 
 void av1_hash_table_init(hash_table *p_hash_table, struct macroblock *x);
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index a783b95..78486e7 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -1543,7 +1543,7 @@
     int best_hash_cost = INT_MAX;
 
     // for the hashMap
-    hash_table *ref_frame_hash = &cpi->common.cur_frame->hash_table;
+    hash_table *ref_frame_hash = &x->intrabc_hash_table;
 
     av1_get_block_hash_value(what, what_stride, block_width, &hash_value1,
                              &hash_value2, is_cur_buf_hbd(&x->e_mbd), x);