summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2014-04-23 17:23:21 +0200
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2014-04-24 11:28:27 +0200
commit61fbb1bba1ad8a41ffae4fd1ba90391adf819b6e (patch)
tree676948fcaf4315b2f002985ab52f3edddbadf41a
parent0d3462360f624750233d77771d55f48bc00039e5 (diff)
vp8: fix support for segmentation-enabled streams.
If segmentation is enabled, then the segmentation map shall be live across frames until the current frame updates the segment ids. This means that the driver needs to maintain the segmentation map buffer allocation and enable writes (resp. reads) whenever necessary. This fixes decoding of 00-comprehensive-010. Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
-rw-r--r--src/gen7_mfd.h1
-rw-r--r--src/gen8_mfd.c35
-rw-r--r--src/i965_decoder_utils.c24
-rw-r--r--src/i965_decoder_utils.h4
4 files changed, 59 insertions, 5 deletions
diff --git a/src/gen7_mfd.h b/src/gen7_mfd.h
index e3111ab..0200216 100644
--- a/src/gen7_mfd.h
+++ b/src/gen7_mfd.h
@@ -85,6 +85,7 @@ struct gen7_mfd_context
GenBuffer bsd_mpc_row_store_scratch_buffer;
GenBuffer mpr_row_store_scratch_buffer;
GenBuffer bitplane_read_buffer;
+ GenBuffer segmentation_buffer;
VASurfaceID jpeg_wa_surface_id;
struct object_surface *jpeg_wa_surface_object;
diff --git a/src/gen8_mfd.c b/src/gen8_mfd.c
index 72b2640..1742bea 100644
--- a/src/gen8_mfd.c
+++ b/src/gen8_mfd.c
@@ -2785,6 +2785,9 @@ gen8_mfd_vp8_decode_init(VADriverContextP ctx,
dri_bo_reference(gen7_mfd_context->pre_deblocking_output.bo);
gen7_mfd_context->pre_deblocking_output.valid = pic_param->pic_fields.bits.loop_filter_disable;
+ intel_ensure_vp8_segmentation_buffer(ctx,
+ &gen7_mfd_context->segmentation_buffer, width_in_mbs, height_in_mbs);
+
/* The same as AVC */
dri_bo_unreference(gen7_mfd_context->intra_row_store_scratch_buffer.bo);
bo = dri_bo_alloc(i965->intel.bufmgr,
@@ -2838,6 +2841,13 @@ gen8_mfd_vp8_pic_state(VADriverContextP ctx,
int i, j,log2num;
unsigned int quantization_value[4][6];
+ /* There is no safe way to error out if the segmentation buffer
+ could not be allocated. So, instead of aborting, simply decode
+ something even if the result may look totally inacurate */
+ const unsigned int enable_segmentation =
+ pic_param->pic_fields.bits.segmentation_enabled &&
+ gen7_mfd_context->segmentation_buffer.valid;
+
log2num = (int)log2(slice_param->num_of_partitions - 1);
BEGIN_BCS_BATCH(batch, 38);
@@ -2854,8 +2864,10 @@ gen8_mfd_vp8_pic_state(VADriverContextP ctx,
pic_param->pic_fields.bits.mb_no_coeff_skip << 10 |
pic_param->pic_fields.bits.update_mb_segmentation_map << 9 |
pic_param->pic_fields.bits.segmentation_enabled << 8 |
- 0 << 7 | /* segmentation id streamin disabled */
- 0 << 6 | /* segmentation id streamout disabled */
+ (enable_segmentation &&
+ !pic_param->pic_fields.bits.update_mb_segmentation_map) << 7 |
+ (enable_segmentation &&
+ pic_param->pic_fields.bits.update_mb_segmentation_map) << 6 |
(pic_param->pic_fields.bits.key_frame == 0 ? 1 : 0) << 5 | /* 0 indicate an intra frame in VP8 stream/spec($9.1)*/
pic_param->pic_fields.bits.filter_type << 4 |
(pic_param->pic_fields.bits.version == 3) << 1 | /* full pixel mode for version 3 */
@@ -2950,9 +2962,18 @@ gen8_mfd_vp8_pic_state(VADriverContextP ctx,
(pic_param->loop_filter_deltas_mode[0] & 0x7f) << 0);
/* segmentation id stream base address, DW35-DW37 */
- OUT_BCS_BATCH(batch, 0);
- OUT_BCS_BATCH(batch, 0);
- OUT_BCS_BATCH(batch, 0);
+ if (enable_segmentation) {
+ OUT_BCS_RELOC(batch, gen7_mfd_context->segmentation_buffer.bo,
+ 0, I915_GEM_DOMAIN_INSTRUCTION,
+ 0);
+ OUT_BCS_BATCH(batch, 0);
+ OUT_BCS_BATCH(batch, 0);
+ }
+ else {
+ OUT_BCS_BATCH(batch, 0);
+ OUT_BCS_BATCH(batch, 0);
+ OUT_BCS_BATCH(batch, 0);
+ }
ADVANCE_BCS_BATCH(batch);
}
@@ -3142,6 +3163,9 @@ gen8_mfd_context_destroy(void *hw_context)
dri_bo_unreference(gen7_mfd_context->bitplane_read_buffer.bo);
gen7_mfd_context->bitplane_read_buffer.bo = NULL;
+ dri_bo_unreference(gen7_mfd_context->segmentation_buffer.bo);
+ gen7_mfd_context->segmentation_buffer.bo = NULL;
+
dri_bo_unreference(gen7_mfd_context->jpeg_wa_slice_data_bo);
intel_batchbuffer_free(gen7_mfd_context->base.batch);
@@ -3174,6 +3198,7 @@ gen8_dec_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
}
gen7_mfd_context->jpeg_wa_surface_id = VA_INVALID_SURFACE;
+ gen7_mfd_context->segmentation_buffer.valid = 0;
switch (obj_config->profile) {
case VAProfileMPEG2Simple:
diff --git a/src/i965_decoder_utils.c b/src/i965_decoder_utils.c
index e80749c..2533381 100644
--- a/src/i965_decoder_utils.c
+++ b/src/i965_decoder_utils.c
@@ -827,3 +827,27 @@ intel_mpeg2_find_next_slice(struct decode_state *decode_state,
return NULL;
}
+
+/* Ensure the segmentation buffer is large enough for the supplied
+ number of MBs, or re-allocate it */
+bool
+intel_ensure_vp8_segmentation_buffer(VADriverContextP ctx, GenBuffer *buf,
+ unsigned int mb_width, unsigned int mb_height)
+{
+ struct i965_driver_data * const i965 = i965_driver_data(ctx);
+ /* The segmentation map is a 64-byte aligned linear buffer, with
+ each cache line holding only 8 bits for 4 continuous MBs */
+ const unsigned int buf_size = ((mb_width + 3) / 4) * 64 * mb_height;
+
+ if (buf->valid) {
+ if (buf->bo && buf->bo->size >= buf_size)
+ return true;
+ drm_intel_bo_unreference(buf->bo);
+ buf->valid = false;
+ }
+
+ buf->bo = drm_intel_bo_alloc(i965->intel.bufmgr, "segmentation map",
+ buf_size, 0x1000);
+ buf->valid = buf->bo != NULL;
+ return buf->valid;
+}
diff --git a/src/i965_decoder_utils.h b/src/i965_decoder_utils.h
index 8f64dfb..b7b72b3 100644
--- a/src/i965_decoder_utils.h
+++ b/src/i965_decoder_utils.h
@@ -106,4 +106,8 @@ intel_update_vp8_frame_store_index(VADriverContextP ctx,
VAPictureParameterBufferVP8 *pic_param,
GenFrameStore frame_store[MAX_GEN_REFERENCE_FRAMES]);
+bool
+intel_ensure_vp8_segmentation_buffer(VADriverContextP ctx, GenBuffer *buf,
+ unsigned int mb_width, unsigned int mb_height);
+
#endif /* I965_DECODER_UTILS_H */