summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
authorhkuang <hkuang@google.com>2014-07-17 14:25:41 -0700
committerhkuang <hkuang@google.com>2014-07-28 10:44:02 -0700
commit7eca086707f3e0f631a5be8952f594f4c387ca74 (patch)
tree6470e272684332419ea88514dd7a16c8328ffcd4 /vp9
parent4c08120ca016242701fee62f83f826d48a9bb315 (diff)
downloadlibvpx-7eca086707f3e0f631a5be8952f594f4c387ca74.tar
libvpx-7eca086707f3e0f631a5be8952f594f4c387ca74.tar.gz
libvpx-7eca086707f3e0f631a5be8952f594f4c387ca74.tar.bz2
libvpx-7eca086707f3e0f631a5be8952f594f4c387ca74.zip
Add segmentation map array for current and last frame segmentation.
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
Diffstat (limited to 'vp9')
-rw-r--r--vp9/common/vp9_alloccommon.c57
-rw-r--r--vp9/common/vp9_alloccommon.h2
-rw-r--r--vp9/common/vp9_entropymode.c3
-rw-r--r--vp9/common/vp9_onyxc_int.h13
-rw-r--r--vp9/decoder/vp9_decodemv.c6
-rw-r--r--vp9/decoder/vp9_decoder.c2
6 files changed, 69 insertions, 14 deletions
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index f847e1276..04081f107 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -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];
+}
diff --git a/vp9/common/vp9_alloccommon.h b/vp9/common/vp9_alloccommon.h
index c4b1b8d2d..1207d6e24 100644
--- a/vp9/common/vp9_alloccommon.h
+++ b/vp9/common/vp9_alloccommon.h
@@ -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
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 5b00b0082..79c8b9bc5 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -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);
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index f31e137b0..13c500147 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -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;
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index 1afaee1e3..187ff1307 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -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);
diff --git a/vp9/decoder/vp9_decoder.c b/vp9/decoder/vp9_decoder.c
index 75283ab93..07fe2899d 100644
--- a/vp9/decoder/vp9_decoder.c
+++ b/vp9/decoder/vp9_decoder.c
@@ -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;