h264: fix pred_weight_table() reconstruction.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 24 Jan 2012 08:20:25 +0000 (09:20 +0100)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Sun, 29 Jan 2012 14:27:59 +0000 (15:27 +0100)
Only the explicit pred_weight_table(), possibly with the inferred default
values, shall be required. e.g. don't fill in the table if weighted_pred_flag
is not set for P/SP slices.

gst-libs/gst/vaapi/gstvaapidecoder_h264.c

index c3846ea..f849db4 100644 (file)
@@ -1772,50 +1772,41 @@ decode_picture_end(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
 }
 
 static gboolean
-fill_slice(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
+fill_pred_weight_table(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
 {
-    GstVaapiDecoderH264Private * const priv = decoder->priv;
     GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
     GstH264PPS * const pps = slice_hdr->pps;
     GstH264SPS * const sps = pps->sequence;
     GstH264PredWeightTable * const w = &slice_hdr->pred_weight_table;
     VASliceParameterBufferH264 * const slice_param = slice->base.param;
+    guint num_weight_tables = 0;
     gint i, j;
 
-    /* Fill in VASliceParameterBufferH264 */
-    slice_param->slice_data_bit_offset          = 8 /* nal_unit_type */ + slice_hdr->header_size;
-    slice_param->first_mb_in_slice              = slice_hdr->first_mb_in_slice;
-    slice_param->slice_type                     = slice_hdr->type % 5;
-    slice_param->direct_spatial_mv_pred_flag    = slice_hdr->direct_spatial_mv_pred_flag;
-    slice_param->num_ref_idx_l0_active_minus1   = priv->list_count > 0 ? slice_hdr->num_ref_idx_l0_active_minus1 : 0;
-    slice_param->num_ref_idx_l1_active_minus1   = priv->list_count > 1 ? slice_hdr->num_ref_idx_l1_active_minus1 : 0;
-    slice_param->cabac_init_idc                 = slice_hdr->cabac_init_idc;
-    slice_param->slice_qp_delta                 = slice_hdr->slice_qp_delta;
-    slice_param->disable_deblocking_filter_idc  = slice_hdr->disable_deblocking_filter_idc;
-    slice_param->slice_alpha_c0_offset_div2     = slice_hdr->slice_alpha_c0_offset_div2;
-    slice_param->slice_beta_offset_div2         = slice_hdr->slice_beta_offset_div2;
-    slice_param->luma_log2_weight_denom         = w->luma_log2_weight_denom;
-    slice_param->chroma_log2_weight_denom       = w->chroma_log2_weight_denom;
+    if (pps->weighted_pred_flag &&
+        (GST_H264_IS_P_SLICE(slice_hdr) || GST_H264_IS_SP_SLICE(slice_hdr)))
+        num_weight_tables = 1;
+    else if (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE(slice_hdr))
+        num_weight_tables = 2;
+    else
+        num_weight_tables = 0;
 
-    for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
-        slice_param->RefPicList0[i] = priv->RefPicList0[i]->info;
-    for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
-        vaapi_init_picture(&slice_param->RefPicList0[i]);
+    slice_param->luma_log2_weight_denom   = w->luma_log2_weight_denom;
+    slice_param->chroma_log2_weight_denom = w->chroma_log2_weight_denom;
+    slice_param->luma_weight_l0_flag      = 0;
+    slice_param->chroma_weight_l0_flag    = 0;
+    slice_param->luma_weight_l1_flag      = 0;
+    slice_param->chroma_weight_l1_flag    = 0;
 
-    for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
-        slice_param->RefPicList1[i] = priv->RefPicList1[i]->info;
-    for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
-        vaapi_init_picture(&slice_param->RefPicList1[i]);
+    if (num_weight_tables < 1)
+        return TRUE;
 
-    slice_param->luma_weight_l0_flag = priv->list_count > 0;
-    if (slice_param->luma_weight_l0_flag) {
-        for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
-            slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
-            slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
-        }
+    slice_param->luma_weight_l0_flag = 1;
+    for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
+        slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
+        slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
     }
 
-    slice_param->chroma_weight_l0_flag = priv->list_count > 0 && sps->chroma_array_type != 0;
+    slice_param->chroma_weight_l0_flag = sps->chroma_array_type != 0;
     if (slice_param->chroma_weight_l0_flag) {
         for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
             for (j = 0; j < 2; j++) {
@@ -1825,15 +1816,16 @@ fill_slice(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
         }
     }
 
-    slice_param->luma_weight_l1_flag = priv->list_count > 1;
-    if (slice_param->luma_weight_l1_flag) {
-        for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
-            slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
-            slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
-        }
+    if (num_weight_tables < 2)
+        return TRUE;
+
+    slice_param->luma_weight_l1_flag = 1;
+    for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
+        slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
+        slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
     }
 
-    slice_param->chroma_weight_l1_flag = priv->list_count > 1 && sps->chroma_array_type != 0;
+    slice_param->chroma_weight_l1_flag = sps->chroma_array_type != 0;
     if (slice_param->chroma_weight_l1_flag) {
         for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
             for (j = 0; j < 2; j++) {
@@ -1845,6 +1837,42 @@ fill_slice(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
     return TRUE;
 }
 
+static gboolean
+fill_slice(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
+    VASliceParameterBufferH264 * const slice_param = slice->base.param;
+    gint i;
+
+    /* Fill in VASliceParameterBufferH264 */
+    slice_param->slice_data_bit_offset          = 8 /* nal_unit_type */ + slice_hdr->header_size;
+    slice_param->first_mb_in_slice              = slice_hdr->first_mb_in_slice;
+    slice_param->slice_type                     = slice_hdr->type % 5;
+    slice_param->direct_spatial_mv_pred_flag    = slice_hdr->direct_spatial_mv_pred_flag;
+    slice_param->num_ref_idx_l0_active_minus1   = priv->list_count > 0 ? slice_hdr->num_ref_idx_l0_active_minus1 : 0;
+    slice_param->num_ref_idx_l1_active_minus1   = priv->list_count > 1 ? slice_hdr->num_ref_idx_l1_active_minus1 : 0;
+    slice_param->cabac_init_idc                 = slice_hdr->cabac_init_idc;
+    slice_param->slice_qp_delta                 = slice_hdr->slice_qp_delta;
+    slice_param->disable_deblocking_filter_idc  = slice_hdr->disable_deblocking_filter_idc;
+    slice_param->slice_alpha_c0_offset_div2     = slice_hdr->slice_alpha_c0_offset_div2;
+    slice_param->slice_beta_offset_div2         = slice_hdr->slice_beta_offset_div2;
+
+    for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
+        slice_param->RefPicList0[i] = priv->RefPicList0[i]->info;
+    for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
+        vaapi_init_picture(&slice_param->RefPicList0[i]);
+
+    for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
+        slice_param->RefPicList1[i] = priv->RefPicList1[i]->info;
+    for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
+        vaapi_init_picture(&slice_param->RefPicList1[i]);
+
+    if (!fill_pred_weight_table(decoder, slice))
+        return FALSE;
+    return TRUE;
+}
+
 static GstVaapiDecoderStatus
 decode_slice(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
 {