st/va: parse VP9 uncompressed frame header
To get some of UVD required parameters.
Signed-off-by: Leo Liu <leo.liu@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c
index e483ea3..e2cdb2b 100644
--- a/src/gallium/state_trackers/va/picture.c
+++ b/src/gallium/state_trackers/va/picture.c
@@ -303,7 +303,7 @@
case PIPE_VIDEO_FORMAT_JPEG:
break;
case PIPE_VIDEO_FORMAT_VP9:
- /* TODO */
+ vlVaDecoderVP9BitstreamHeader(context, buf);
break;
default:
break;
diff --git a/src/gallium/state_trackers/va/picture_vp9.c b/src/gallium/state_trackers/va/picture_vp9.c
index 38684ca..c1ca54c 100644
--- a/src/gallium/state_trackers/va/picture_vp9.c
+++ b/src/gallium/state_trackers/va/picture_vp9.c
@@ -25,6 +25,7 @@
*
**************************************************************************/
+#include "vl/vl_vlc.h"
#include "va_private.h"
void vlVaHandlePictureParameterBufferVP9(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
@@ -109,3 +110,239 @@
context->desc.vp9.slice_parameter.seg_param[i].chroma_dc_quant_scale = vp9->seg_param[i].chroma_dc_quant_scale;
}
}
+
+static unsigned vp9_u(struct vl_vlc *vlc, unsigned n)
+{
+ unsigned valid = vl_vlc_valid_bits(vlc);
+
+ if (n == 0)
+ return 0;
+
+ if (valid < 32)
+ vl_vlc_fillbits(vlc);
+
+ return vl_vlc_get_uimsbf(vlc, n);
+}
+
+static signed vp9_s(struct vl_vlc *vlc, unsigned n)
+{
+ unsigned v;
+ bool s;
+
+ v = vp9_u(vlc, n);
+ s = vp9_u(vlc, 1);
+
+ return s ? -v : v;
+}
+
+static void bitdepth_colorspace_sampling(struct vl_vlc *vlc, unsigned profile)
+{
+ unsigned cs;
+
+ if (profile == 2)
+ /* bit_depth */
+ vp9_u(vlc, 1);
+
+ cs = vp9_u(vlc, 3);
+ if (cs != 7)
+ /* yuv_range_flag */
+ vp9_u(vlc, 1);
+}
+
+static void frame_size(struct vl_vlc *vlc)
+{
+ /* width_minus_one */
+ vp9_u(vlc, 16);
+ /* height_minus_one */
+ vp9_u(vlc, 16);
+
+ /* has_scaling */
+ if (vp9_u(vlc, 1)) {
+ /* render_width_minus_one */
+ vp9_u(vlc, 16);
+ /* render_height_minus_one */
+ vp9_u(vlc, 16);
+ }
+}
+
+void vlVaDecoderVP9BitstreamHeader(vlVaContext *context, vlVaBuffer *buf)
+{
+ struct vl_vlc vlc;
+ unsigned profile;
+ bool frame_type, show_frame, error_resilient_mode;
+ bool mode_ref_delta_enabled, mode_ref_delta_update = false;
+ int i;
+
+ vl_vlc_init(&vlc, 1, (const void * const*)&buf->data,
+ (const unsigned *)&context->desc.vp9.picture_parameter.frame_header_length_in_bytes);
+
+ /* frame_marker */
+ if (vp9_u(&vlc, 2) != 0x2)
+ return;
+
+ profile = vp9_u(&vlc, 1) | vp9_u(&vlc, 1) << 1;
+
+ if (profile == 3)
+ profile += vp9_u(&vlc, 1);
+
+ if (profile != 0 && profile != 2)
+ return;
+
+ /* show_existing_frame */
+ if (vp9_u(&vlc, 1))
+ return;
+
+ frame_type = vp9_u(&vlc, 1);
+ show_frame = vp9_u(&vlc, 1);
+ error_resilient_mode = vp9_u(&vlc, 1);
+
+ if (frame_type == 0) {
+ /* sync_code */
+ if (vp9_u(&vlc, 24) != 0x498342)
+ return;
+
+ bitdepth_colorspace_sampling(&vlc, profile);
+ frame_size(&vlc);
+ } else {
+ bool intra_only, size_in_refs = false;
+
+ intra_only = show_frame ? 0 : vp9_u(&vlc, 1);
+ if (!error_resilient_mode)
+ /* reset_frame_context */
+ vp9_u(&vlc, 2);
+
+ if (intra_only) {
+ /* sync_code */
+ if (vp9_u(&vlc, 24) != 0x498342)
+ return;
+
+ bitdepth_colorspace_sampling(&vlc, profile);
+ /* refresh_frame_flags */
+ vp9_u(&vlc, 8);
+ frame_size(&vlc);
+ } else {
+ /* refresh_frame_flags */
+ vp9_u(&vlc, 8);
+
+ for (i = 0; i < 3; ++i) {
+ /* frame refs */
+ vp9_u(&vlc, 3);
+ vp9_u(&vlc, 1);
+ }
+
+ for (i = 0; i < 3; ++i) {
+ size_in_refs = vp9_u(&vlc, 1);
+ if (size_in_refs)
+ break;
+ }
+
+ if (!size_in_refs) {
+ /* width/height_minus_one */
+ vp9_u(&vlc, 16);
+ vp9_u(&vlc, 16);
+ }
+
+ if (vp9_u(&vlc, 1)) {
+ /* render_width/height_minus_one */
+ vp9_u(&vlc, 16);
+ vp9_u(&vlc, 16);
+ }
+
+ /* high_precision_mv */
+ vp9_u(&vlc, 1);
+ /* filter_switchable */
+ if (!vp9_u(&vlc, 1))
+ /* filter_index */
+ vp9_u(&vlc, 2);
+ }
+ }
+ if (!error_resilient_mode) {
+ /* refresh_frame_context */
+ vp9_u(&vlc, 1);
+ /* frame_parallel_decoding_mode */
+ vp9_u(&vlc, 1);
+ }
+ /* frame_context_index */
+ vp9_u(&vlc, 2);
+
+ /* loop filter */
+
+ /* filter_level */
+ vp9_u(&vlc, 6);
+ /* sharpness_level */
+ vp9_u(&vlc, 3);
+
+ mode_ref_delta_enabled = vp9_u(&vlc, 1);
+ if (mode_ref_delta_enabled) {
+ mode_ref_delta_update = vp9_u(&vlc, 1);
+ if (mode_ref_delta_update) {
+ for (i = 0; i < 4; ++i) {
+ /* update_ref_delta */
+ if (vp9_u(&vlc, 1))
+ /* ref_deltas */
+ vp9_s(&vlc, 6);
+ }
+ for (i = 0; i < 2; ++i) {
+ /* update_mode_delta */
+ if (vp9_u(&vlc, 1))
+ /* mode_deltas */
+ vp9_s(&vlc, 6);
+ }
+ }
+ }
+ context->desc.vp9.picture_parameter.mode_ref_delta_enabled = mode_ref_delta_enabled;
+ context->desc.vp9.picture_parameter.mode_ref_delta_update = mode_ref_delta_update;
+
+ /* quantization */
+
+ context->desc.vp9.picture_parameter.base_qindex = vp9_u(&vlc, 8);
+ context->desc.vp9.picture_parameter.y_dc_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0;
+ context->desc.vp9.picture_parameter.uv_ac_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0;
+ context->desc.vp9.picture_parameter.uv_dc_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0;
+
+ /* segmentation */
+
+ /* enabled */
+ if (!vp9_u(&vlc, 1))
+ return;
+
+ /* update_map */
+ if (vp9_u(&vlc, 1)) {
+ for (i = 0; i < 7; ++i) {
+ /* tree_probs_set */
+ if (vp9_u(&vlc, 1)) {
+ /* tree_probs */
+ vp9_u(&vlc, 8);
+ }
+ }
+
+ /* temporal_update */
+ if (vp9_u(&vlc, 1)) {
+ for (i = 0; i < 3; ++i) {
+ /* pred_probs_set */
+ if (vp9_u(&vlc, 1))
+ /* pred_probs */
+ vp9_u(&vlc, 8);
+ }
+ }
+ }
+
+ /* update_data */
+ if (vp9_u(&vlc, 1)) {
+ /* abs_delta */
+ vp9_u(&vlc, 1);
+ for (i = 0; i < 8; ++i) {
+ /* Use alternate quantizer */
+ if ((context->desc.vp9.slice_parameter.seg_param[i].alt_quant_enabled = vp9_u(&vlc, 1)))
+ context->desc.vp9.slice_parameter.seg_param[i].alt_quant = vp9_s(&vlc, 8);
+ /* Use alternate loop filter value */
+ if ((context->desc.vp9.slice_parameter.seg_param[i].alt_lf_enabled = vp9_u(&vlc, 1)))
+ context->desc.vp9.slice_parameter.seg_param[i].alt_lf = vp9_s(&vlc, 6);
+ /* Optional Segment reference frame */
+ if (vp9_u(&vlc, 1))
+ vp9_u(&vlc, 2);
+ /* Optional Segment skip mode */
+ vp9_u(&vlc, 1);
+ }
+ }
+}
diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h
index ef91428..c82fec3 100644
--- a/src/gallium/state_trackers/va/va_private.h
+++ b/src/gallium/state_trackers/va/va_private.h
@@ -431,6 +431,7 @@
void vlVaHandleSliceParameterBufferMJPEG(vlVaContext *context, vlVaBuffer *buf);
void vlVaHandlePictureParameterBufferVP9(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);
void vlVaHandleSliceParameterBufferVP9(vlVaContext *context, vlVaBuffer *buf);
+void vlVaDecoderVP9BitstreamHeader(vlVaContext *context, vlVaBuffer *buf);
void getEncParamPresetH264(vlVaContext *context);
void getEncParamPresetH265(vlVaContext *context);
VAStatus vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);