]> granicus.if.org Git - libvpx/commitdiff
Add segmentation map array for current and last frame segmentation.
authorhkuang <hkuang@google.com>
Thu, 17 Jul 2014 21:25:41 +0000 (14:25 -0700)
committerhkuang <hkuang@google.com>
Mon, 28 Jul 2014 17:44:02 +0000 (10:44 -0700)
The original implementation only allocates one segmentation map and this
works fine for serial decode. But for frame parallel decode,  each thread
need to have its own segmentation map and the last frame segmentation map
should be provided from last frame decoding thread.

After finishing decoding a frame, thread need to serve the old segmentation
map that associate with the previous decoded frame. The thread also need to
use another segmentation map for decoding the current frame.

Change-Id: I442ddff36b5de9cb8a7eb59e225744c78f4492d8

vp9/common/vp9_alloccommon.c
vp9/common/vp9_alloccommon.h
vp9/common/vp9_entropymode.c
vp9/common/vp9_onyxc_int.h
vp9/decoder/vp9_decodemv.c
vp9/decoder/vp9_decoder.c

index f847e127696dc91a25559d4e2af2c779f9dc528b..04081f1072084aa968565521b1e84c36264e5d89 100644 (file)
@@ -55,7 +55,7 @@ static void setup_mi(VP9_COMMON *cm) {
 static int alloc_mi(VP9_COMMON *cm, int mi_size) {
   int i;
 
-  for (i = 0; i < 2; ++i) {
+  for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
     cm->mip_array[i] =
         (MODE_INFO *)vpx_calloc(mi_size, sizeof(*cm->mip));
     if (cm->mip_array[i] == NULL)
@@ -82,7 +82,7 @@ static int alloc_mi(VP9_COMMON *cm, int mi_size) {
 static void free_mi(VP9_COMMON *cm) {
   int i;
 
-  for (i = 0; i < 2; ++i) {
+  for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
     vpx_free(cm->mip_array[i]);
     cm->mip_array[i] = NULL;
     vpx_free(cm->mi_grid_base_array[i]);
@@ -95,6 +95,37 @@ static void free_mi(VP9_COMMON *cm) {
   cm->prev_mi_grid_base = NULL;
 }
 
+static int alloc_seg_map(VP9_COMMON *cm, int seg_map_size) {
+  int i;
+
+  for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
+    cm->seg_map_array[i] = (uint8_t *)vpx_calloc(seg_map_size, 1);
+    if (cm->seg_map_array[i] == NULL)
+      return 1;
+  }
+
+  // Init the index.
+  cm->seg_map_idx = 0;
+  cm->prev_seg_map_idx = 1;
+
+  cm->current_frame_seg_map = cm->seg_map_array[cm->seg_map_idx];
+  cm->last_frame_seg_map = cm->seg_map_array[cm->prev_seg_map_idx];
+
+  return 0;
+}
+
+static void free_seg_map(VP9_COMMON *cm) {
+  int i;
+
+  for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
+    vpx_free(cm->seg_map_array[i]);
+    cm->seg_map_array[i] = NULL;
+  }
+
+  cm->current_frame_seg_map = NULL;
+  cm->last_frame_seg_map = NULL;
+}
+
 void vp9_free_frame_buffers(VP9_COMMON *cm) {
   int i;
   BufferPool *const pool = cm->buffer_pool;
@@ -115,8 +146,7 @@ void vp9_free_frame_buffers(VP9_COMMON *cm) {
 void vp9_free_context_buffers(VP9_COMMON *cm) {
   free_mi(cm);
 
-  vpx_free(cm->last_frame_seg_map);
-  cm->last_frame_seg_map = NULL;
+  free_seg_map(cm);
 
   vpx_free(cm->above_context);
   cm->above_context = NULL;
@@ -147,9 +177,8 @@ int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) {
   setup_mi(cm);
 
   // Create the segmentation map structure and set to 0.
-  vpx_free(cm->last_frame_seg_map);
-  cm->last_frame_seg_map = (uint8_t *)vpx_calloc(cm->mi_rows * cm->mi_cols, 1);
-  if (!cm->last_frame_seg_map)
+  free_seg_map(cm);
+  if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols))
     goto fail;
 
   vpx_free(cm->above_context);
@@ -270,8 +299,8 @@ void vp9_update_frame_size(VP9_COMMON *cm) {
   setup_mi(cm);
 
   // Initialize the previous frame segment map to 0.
-  if (cm->last_frame_seg_map)
-    vpx_memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols);
+  if (cm->current_frame_seg_map)
+    vpx_memset(cm->current_frame_seg_map, 0, cm->mi_rows * cm->mi_cols);
 }
 
 void vp9_swap_mi_and_prev_mi(VP9_COMMON *cm) {
@@ -292,3 +321,13 @@ void vp9_swap_mi_and_prev_mi(VP9_COMMON *cm) {
   cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1;
   cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mi_stride + 1;
 }
+
+void vp9_swap_current_and_last_seg_map(VP9_COMMON *cm) {
+  // Swap indices.
+  const int tmp = cm->seg_map_idx;
+  cm->seg_map_idx = cm->prev_seg_map_idx;
+  cm->prev_seg_map_idx = tmp;
+
+  cm->current_frame_seg_map = cm->seg_map_array[cm->seg_map_idx];
+  cm->last_frame_seg_map = cm->seg_map_array[cm->prev_seg_map_idx];
+}
index c4b1b8d2df137258a664705af7f0f1c57490f7f4..1207d6e249522a1a3b83b0984503389c8527561e 100644 (file)
@@ -34,6 +34,8 @@ void vp9_update_frame_size(struct VP9Common *cm);
 
 void vp9_swap_mi_and_prev_mi(struct VP9Common *cm);
 
+void vp9_swap_current_and_last_seg_map(struct VP9Common *cm);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
index 5b00b0082a135b4dd508d571a2f3567a0cc81caa..79c8b9bc52b5c5005407345aebcd1b54dee9f106 100644 (file)
@@ -442,6 +442,9 @@ void vp9_setup_past_independence(VP9_COMMON *cm) {
   if (cm->last_frame_seg_map)
     vpx_memset(cm->last_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
 
+  if (cm->current_frame_seg_map)
+    vpx_memset(cm->current_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
+
   // Reset the mode ref deltas for loop filter
   vp9_zero(lf->last_ref_deltas);
   vp9_zero(lf->last_mode_deltas);
index f31e137b0c904d0d9f5926b123cc37b3448f8c71..13c5001478c5fe931dc4aec4cae22d713cef3264 100644 (file)
@@ -44,6 +44,8 @@ extern "C" {
 #define FRAME_CONTEXTS_LOG2 2
 #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
 
+#define NUM_PING_PONG_BUFFERS 2
+
 extern const struct {
   PARTITION_CONTEXT above;
   PARTITION_CONTEXT left;
@@ -163,8 +165,8 @@ typedef struct VP9Common {
 
   int mi_idx;
   int prev_mi_idx;
-  MODE_INFO *mip_array[2];
-  MODE_INFO **mi_grid_base_array[2];
+  MODE_INFO *mip_array[NUM_PING_PONG_BUFFERS];
+  MODE_INFO **mi_grid_base_array[NUM_PING_PONG_BUFFERS];
 
   MODE_INFO *mip; /* Base of allocated array */
   MODE_INFO *mi;  /* Corresponds to upper left visible macroblock */
@@ -177,7 +179,12 @@ typedef struct VP9Common {
   MODE_INFO **prev_mi_grid_visible;
 
   // Persistent mb segment id map used in prediction.
-  unsigned char *last_frame_seg_map;
+  int seg_map_idx;
+  int prev_seg_map_idx;
+
+  uint8_t *seg_map_array[NUM_PING_PONG_BUFFERS];
+  uint8_t *last_frame_seg_map;
+  uint8_t *current_frame_seg_map;
 
   INTERP_FILTER interp_filter;
 
index 1afaee1e3ba7b96e3d488e3809033e5faf024e37..187ff13077cf39aef1f86a77956b551a465eabef 100644 (file)
@@ -96,7 +96,7 @@ static void set_segment_id(VP9_COMMON *cm, BLOCK_SIZE bsize,
 
   for (y = 0; y < ymis; y++)
     for (x = 0; x < xmis; x++)
-      cm->last_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id;
+      cm->current_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id;
 }
 
 static int read_intra_segment_id(VP9_COMMON *const cm, MACROBLOCKD *const xd,
@@ -129,8 +129,10 @@ static int read_inter_segment_id(VP9_COMMON *const cm, MACROBLOCKD *const xd,
 
   predicted_segment_id = vp9_get_segment_id(cm, cm->last_frame_seg_map,
                                             bsize, mi_row, mi_col);
-  if (!seg->update_map)
+  if (!seg->update_map) {
+    set_segment_id(cm, bsize, mi_row, mi_col, predicted_segment_id);
     return predicted_segment_id;
+  }
 
   if (seg->temporal_update) {
     const vp9_prob pred_prob = vp9_get_pred_prob_seg_id(seg, xd);
index 75283ab93fc8cc78ce518c3ded2f9b2e515a4a39..07fe2899df9a2ee031db5a40628e613ffc71a718 100644 (file)
@@ -295,6 +295,8 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
     cm->current_video_frame++;
   }
 
+  vp9_swap_current_and_last_seg_map(cm);
+
   pbi->ready_for_new_data = 0;
 
   cm->error.setjmp = 0;