<commit_before>/*
 *  gstvaapidecoder_vp8.c - VP8 decoder
 *
 *  Copyright (C) 2013-2014 Intel Corporation
 *    Author: <NAME> <<EMAIL>>
 *    Author: <NAME> <<EMAIL>>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1
 *  of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301 USA
 */

/**
 * SECTION:gstvaapidecoder_vp8
 * @short_description: VP8 decoder
 */

#include "sysdeps.h"
#include <gst/codecparsers/gstvp8parser.h>
#include "gstvaapidecoder_vp8.h"
#include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapiobject_priv.h"

#include "gstvaapicompat.h"
#include <va/va_dec_vp8.h>

#define DEBUG 1
#include "gstvaapidebug.h"

#define GST_VAAPI_DECODER_VP8_CAST(decoder) \
  ((GstVaapiDecoderVp8 *)(decoder))

typedef struct _GstVaapiDecoderVp8Private GstVaapiDecoderVp8Private;
typedef struct _GstVaapiDecoderVp8Class GstVaapiDecoderVp8Class;

struct _GstVaapiDecoderVp8Private
{
  GstVaapiProfile profile;
  guint width;
  guint height;
  GstVp8Parser parser;
  GstVp8FrameHdr frame_hdr;
  GstVaapiPicture *last_picture;
  GstVaapiPicture *golden_ref_picture;
  GstVaapiPicture *alt_ref_picture;
  GstVaapiPicture *current_picture;
  guint size_changed:1;
};

/**
 * GstVaapiDecoderVp8:
 *
 * A decoder based on Vp8.
 */
struct _GstVaapiDecoderVp8
{
  /*< private >*/
  GstVaapiDecoder parent_instance;

  GstVaapiDecoderVp8Private priv;
};

/**
 * GstVaapiDecoderVp8Class:
 *
 * A decoder class based on Vp8.
 */
struct _GstVaapiDecoderVp8Class
{
  /*< private >*/
  GstVaapiDecoderClass parent_class;
};

static GstVaapiDecoderStatus
get_status (GstVp8ParserResult result)
{
  GstVaapiDecoderStatus status;

  switch (result) {
    case GST_VP8_PARSER_OK:
      status = GST_VAAPI_DECODER_STATUS_SUCCESS;
      break;
    case GST_VP8_PARSER_ERROR:
      status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
      break;
    default:
      status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
      break;
  }
  return status;
}

static void
gst_vaapi_decoder_vp8_close (GstVaapiDecoderVp8 * decoder)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;

  gst_vaapi_picture_replace (&priv->last_picture, NULL);
  gst_vaapi_picture_replace (&priv->golden_ref_picture, NULL);
  gst_vaapi_picture_replace (&priv->alt_ref_picture, NULL);
  gst_vaapi_picture_replace (&priv->current_picture, NULL);
}

static gboolean
gst_vaapi_decoder_vp8_open (GstVaapiDecoderVp8 * decoder)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;

  gst_vaapi_decoder_vp8_close (decoder);
  gst_vp8_parser_init (&priv->parser);
  return TRUE;
}

static void
gst_vaapi_decoder_vp8_destroy (GstVaapiDecoder * base_decoder)
{
  GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);

  gst_vaapi_decoder_vp8_close (decoder);
}

static gboolean
gst_vaapi_decoder_vp8_create (GstVaapiDecoder * base_decoder)
{
  GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;

  if (!gst_vaapi_decoder_vp8_open (decoder))
    return FALSE;

  priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
  return TRUE;
}

static GstVaapiDecoderStatus
ensure_context (GstVaapiDecoderVp8 * decoder)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  const GstVaapiProfile profile = GST_VAAPI_PROFILE_VP8;
  const GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
  gboolean reset_context = FALSE;

  if (priv->profile != profile) {
    if (!gst_vaapi_display_has_decoder (GST_VAAPI_DECODER_DISPLAY (decoder),
            profile, entrypoint))
      return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;

    priv->profile = profile;
    reset_context = TRUE;
  }

  if (priv->size_changed) {
    GST_DEBUG ("size changed");
    priv->size_changed = FALSE;
    reset_context = TRUE;
  }

  if (reset_context) {
    GstVaapiContextInfo info;

    info.profile = priv->profile;
    info.entrypoint = entrypoint;
    info.width = priv->width;
    info.height = priv->height;
    info.ref_frames = 3;
    reset_context =
        gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info);

    if (!reset_context)
      return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
  }
  return GST_VAAPI_DECODER_STATUS_SUCCESS;
}

static GstVaapiDecoderStatus
ensure_quant_matrix (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
  GstVp8Segmentation *const seg = &priv->parser.segmentation;
  VAIQMatrixBufferVP8 *iq_matrix;
  const gint8 QI_MAX = 127;
  gint8 qi, qi_base;
  gint i;

  picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (VP8, decoder);
  if (!picture->iq_matrix) {
    GST_ERROR ("failed to allocate IQ matrix");
    return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
  }
  iq_matrix = picture->iq_matrix->param;

  /* Fill in VAIQMatrixBufferVP8 */
  for (i = 0; i < 4; i++) {
    if (seg->segmentation_enabled) {
      qi_base = seg->quantizer_update_value[i];
      if (!seg->segment_feature_mode)   // 0 means delta update
        qi_base += frame_hdr->quant_indices.y_ac_qi;
    } else
      qi_base = frame_hdr->quant_indices.y_ac_qi;

    qi = qi_base;
    iq_matrix->quantization_index[i][0] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.y_dc_delta;
    iq_matrix->quantization_index[i][1] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.y2_dc_delta;
    iq_matrix->quantization_index[i][2] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.y2_ac_delta;
    iq_matrix->quantization_index[i][3] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.uv_dc_delta;
    iq_matrix->quantization_index[i][4] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.uv_ac_delta;
    iq_matrix->quantization_index[i][5] = CLAMP (qi, 0, QI_MAX);
  }
  return GST_VAAPI_DECODER_STATUS_SUCCESS;
}

static GstVaapiDecoderStatus
ensure_probability_table (GstVaapiDecoderVp8 * decoder,
    GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
  VAProbabilityDataBufferVP8 *prob_table;

  picture->prob_table = GST_VAAPI_PROBABILITY_TABLE_NEW (VP8, decoder);
  if (!picture->prob_table) {
    GST_ERROR ("failed to allocate probality table");
    return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
  }
  prob_table = picture->prob_table->param;

  /* Fill in VAProbabilityDataBufferVP8 */
  memcpy (prob_table->dct_coeff_probs, frame_hdr->token_probs.prob,
      sizeof (frame_hdr->token_probs.prob));

  return GST_VAAPI_DECODER_STATUS_SUCCESS;
}

static void
init_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;

  picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
  picture->type = frame_hdr->key_frame ? GST_VAAPI_PICTURE_TYPE_I :
      GST_VAAPI_PICTURE_TYPE_P;
  picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;

  if (!frame_hdr->show_frame)
    GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
}

static gboolean
fill_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  VAPictureParameterBufferVP8 *const pic_param = picture->param;
  GstVp8Parser *const parser = &priv->parser;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
  GstVp8Segmentation *const seg = &parser->segmentation;
  gint i, filter_levels;

  /* Fill in VAPictureParameterBufferVP8 */
  pic_param->frame_width = priv->width;
  pic_param->frame_height = priv->height;

  pic_param->last_ref_frame = VA_INVALID_SURFACE;
  pic_param->golden_ref_frame = VA_INVALID_SURFACE;
  pic_param->alt_ref_frame = VA_INVALID_SURFACE;
  if (!frame_hdr->key_frame) {
    if (priv->last_picture)
      pic_param->last_ref_frame = priv->last_picture->surface_id;
    if (priv->golden_ref_picture)
      pic_param->golden_ref_frame = priv->golden_ref_picture->surface_id;
    if (priv->alt_ref_picture)
      pic_param->alt_ref_frame = priv->alt_ref_picture->surface_id;
  }
  pic_param->out_of_loop_frame = VA_INVALID_SURFACE;    // not used currently

  pic_param->pic_fields.value = 0;
  pic_param->pic_fields.bits.key_frame = !frame_hdr->key_frame;
  pic_param->pic_fields.bits.version = frame_hdr->version;
  pic_param->pic_fields.bits.segmentation_enabled = seg->segmentation_enabled;
  pic_param->pic_fields.bits.update_mb_segmentation_map =
      seg->update_mb_segmentation_map;
  pic_param->pic_fields.bits.update_segment_feature_data =
      seg->update_segment_feature_data;
  pic_param->pic_fields.bits.filter_type = frame_hdr->filter_type;
  pic_param->pic_fields.bits.sharpness_level = frame_hdr->sharpness_level;
  pic_param->pic_fields.bits.loop_filter_adj_enable =
      parser->mb_lf_adjust.loop_filter_adj_enable;
  pic_param->pic_fields.bits.mode_ref_lf_delta_update =
      parser->mb_lf_adjust.mode_ref_lf_delta_update;
  pic_param->pic_fields.bits.sign_bias_golden = frame_hdr->sign_bias_golden;
  pic_param->pic_fields.bits.sign_bias_alternate =
      frame_hdr->sign_bias_alternate;
  pic_param->pic_fields.bits.mb_no_coeff_skip = frame_hdr->mb_no_skip_coeff;

  for (i = 0; i < 3; i++)
    pic_param->mb_segment_tree_probs[i] = seg->segment_prob[i];

  for (i = 0; i < 4; i++) {
    if (seg->segmentation_enabled) {
      pic_param->loop_filter_level[i] = seg->lf_update_value[i];
      if (!seg->segment_feature_mode)
        pic_param->loop_filter_level[i] += frame_hdr->loop_filter_level;
    } else
      pic_param->loop_filter_level[i] = frame_hdr->loop_filter_level;

    pic_param->loop_filter_deltas_ref_frame[i] =
        parser->mb_lf_adjust.ref_frame_delta[i];
    pic_param->loop_filter_deltas_mode[i] =
        parser->mb_lf_adjust.mb_mode_delta[i];
  }

  /* In decoding, the only loop filter settings that matter are those
     in the frame header (9.1) */
  filter_levels = pic_param->loop_filter_level[0];
  if (seg->segmentation_enabled) {
    for (i = 1; i < 4; i++)
      filter_levels |= pic_param->loop_filter_level[i];
  }
  pic_param->pic_fields.bits.loop_filter_disable = filter_levels == 0;

  pic_param->prob_skip_false = frame_hdr->prob_skip_false;
  pic_param->prob_intra = frame_hdr->prob_intra;
  pic_param->prob_last = frame_hdr->prob_last;
  pic_param->prob_gf = frame_hdr->prob_gf;
<commit_msg>vp8: fix check for disabling the loop filter (again).<commit_after>/*
 *  gstvaapidecoder_vp8.c - VP8 decoder
 *
 *  Copyright (C) 2013-2014 Intel Corporation
 *    Author: <NAME> <<EMAIL>>
 *    Author: <NAME> <<EMAIL>>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1
 *  of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301 USA
 */

/**
 * SECTION:gstvaapidecoder_vp8
 * @short_description: VP8 decoder
 */

#include "sysdeps.h"
#include <gst/codecparsers/gstvp8parser.h>
#include "gstvaapidecoder_vp8.h"
#include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapiobject_priv.h"

#include "gstvaapicompat.h"
#include <va/va_dec_vp8.h>

#define DEBUG 1
#include "gstvaapidebug.h"

#define GST_VAAPI_DECODER_VP8_CAST(decoder) \
  ((GstVaapiDecoderVp8 *)(decoder))

typedef struct _GstVaapiDecoderVp8Private GstVaapiDecoderVp8Private;
typedef struct _GstVaapiDecoderVp8Class GstVaapiDecoderVp8Class;

struct _GstVaapiDecoderVp8Private
{
  GstVaapiProfile profile;
  guint width;
  guint height;
  GstVp8Parser parser;
  GstVp8FrameHdr frame_hdr;
  GstVaapiPicture *last_picture;
  GstVaapiPicture *golden_ref_picture;
  GstVaapiPicture *alt_ref_picture;
  GstVaapiPicture *current_picture;
  guint size_changed:1;
};

/**
 * GstVaapiDecoderVp8:
 *
 * A decoder based on Vp8.
 */
struct _GstVaapiDecoderVp8
{
  /*< private >*/
  GstVaapiDecoder parent_instance;

  GstVaapiDecoderVp8Private priv;
};

/**
 * GstVaapiDecoderVp8Class:
 *
 * A decoder class based on Vp8.
 */
struct _GstVaapiDecoderVp8Class
{
  /*< private >*/
  GstVaapiDecoderClass parent_class;
};

static GstVaapiDecoderStatus
get_status (GstVp8ParserResult result)
{
  GstVaapiDecoderStatus status;

  switch (result) {
    case GST_VP8_PARSER_OK:
      status = GST_VAAPI_DECODER_STATUS_SUCCESS;
      break;
    case GST_VP8_PARSER_ERROR:
      status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
      break;
    default:
      status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
      break;
  }
  return status;
}

static void
gst_vaapi_decoder_vp8_close (GstVaapiDecoderVp8 * decoder)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;

  gst_vaapi_picture_replace (&priv->last_picture, NULL);
  gst_vaapi_picture_replace (&priv->golden_ref_picture, NULL);
  gst_vaapi_picture_replace (&priv->alt_ref_picture, NULL);
  gst_vaapi_picture_replace (&priv->current_picture, NULL);
}

static gboolean
gst_vaapi_decoder_vp8_open (GstVaapiDecoderVp8 * decoder)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;

  gst_vaapi_decoder_vp8_close (decoder);
  gst_vp8_parser_init (&priv->parser);
  return TRUE;
}

static void
gst_vaapi_decoder_vp8_destroy (GstVaapiDecoder * base_decoder)
{
  GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);

  gst_vaapi_decoder_vp8_close (decoder);
}

static gboolean
gst_vaapi_decoder_vp8_create (GstVaapiDecoder * base_decoder)
{
  GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;

  if (!gst_vaapi_decoder_vp8_open (decoder))
    return FALSE;

  priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
  return TRUE;
}

static GstVaapiDecoderStatus
ensure_context (GstVaapiDecoderVp8 * decoder)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  const GstVaapiProfile profile = GST_VAAPI_PROFILE_VP8;
  const GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
  gboolean reset_context = FALSE;

  if (priv->profile != profile) {
    if (!gst_vaapi_display_has_decoder (GST_VAAPI_DECODER_DISPLAY (decoder),
            profile, entrypoint))
      return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;

    priv->profile = profile;
    reset_context = TRUE;
  }

  if (priv->size_changed) {
    GST_DEBUG ("size changed");
    priv->size_changed = FALSE;
    reset_context = TRUE;
  }

  if (reset_context) {
    GstVaapiContextInfo info;

    info.profile = priv->profile;
    info.entrypoint = entrypoint;
    info.width = priv->width;
    info.height = priv->height;
    info.ref_frames = 3;
    reset_context =
        gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info);

    if (!reset_context)
      return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
  }
  return GST_VAAPI_DECODER_STATUS_SUCCESS;
}

static GstVaapiDecoderStatus
ensure_quant_matrix (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
  GstVp8Segmentation *const seg = &priv->parser.segmentation;
  VAIQMatrixBufferVP8 *iq_matrix;
  const gint8 QI_MAX = 127;
  gint8 qi, qi_base;
  gint i;

  picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (VP8, decoder);
  if (!picture->iq_matrix) {
    GST_ERROR ("failed to allocate IQ matrix");
    return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
  }
  iq_matrix = picture->iq_matrix->param;

  /* Fill in VAIQMatrixBufferVP8 */
  for (i = 0; i < 4; i++) {
    if (seg->segmentation_enabled) {
      qi_base = seg->quantizer_update_value[i];
      if (!seg->segment_feature_mode)   // 0 means delta update
        qi_base += frame_hdr->quant_indices.y_ac_qi;
    } else
      qi_base = frame_hdr->quant_indices.y_ac_qi;

    qi = qi_base;
    iq_matrix->quantization_index[i][0] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.y_dc_delta;
    iq_matrix->quantization_index[i][1] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.y2_dc_delta;
    iq_matrix->quantization_index[i][2] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.y2_ac_delta;
    iq_matrix->quantization_index[i][3] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.uv_dc_delta;
    iq_matrix->quantization_index[i][4] = CLAMP (qi, 0, QI_MAX);
    qi = qi_base + frame_hdr->quant_indices.uv_ac_delta;
    iq_matrix->quantization_index[i][5] = CLAMP (qi, 0, QI_MAX);
  }
  return GST_VAAPI_DECODER_STATUS_SUCCESS;
}

static GstVaapiDecoderStatus
ensure_probability_table (GstVaapiDecoderVp8 * decoder,
    GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
  VAProbabilityDataBufferVP8 *prob_table;

  picture->prob_table = GST_VAAPI_PROBABILITY_TABLE_NEW (VP8, decoder);
  if (!picture->prob_table) {
    GST_ERROR ("failed to allocate probality table");
    return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
  }
  prob_table = picture->prob_table->param;

  /* Fill in VAProbabilityDataBufferVP8 */
  memcpy (prob_table->dct_coeff_probs, frame_hdr->token_probs.prob,
      sizeof (frame_hdr->token_probs.prob));

  return GST_VAAPI_DECODER_STATUS_SUCCESS;
}

static void
init_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;

  picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
  picture->type = frame_hdr->key_frame ? GST_VAAPI_PICTURE_TYPE_I :
      GST_VAAPI_PICTURE_TYPE_P;
  picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;

  if (!frame_hdr->show_frame)
    GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
}

static gboolean
fill_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
  GstVaapiDecoderVp8Private *const priv = &decoder->priv;
  VAPictureParameterBufferVP8 *const pic_param = picture->param;
  GstVp8Parser *const parser = &priv->parser;
  GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
  GstVp8Segmentation *const seg = &parser->segmentation;
  gint i;

  /* Fill in VAPictureParameterBufferVP8 */
  pic_param->frame_width = priv->width;
  pic_param->frame_height = priv->height;

  pic_param->last_ref_frame = VA_INVALID_SURFACE;
  pic_param->golden_ref_frame = VA_INVALID_SURFACE;
  pic_param->alt_ref_frame = VA_INVALID_SURFACE;
  if (!frame_hdr->key_frame) {
    if (priv->last_picture)
      pic_param->last_ref_frame = priv->last_picture->surface_id;
    if (priv->golden_ref_picture)
      pic_param->golden_ref_frame = priv->golden_ref_picture->surface_id;
    if (priv->alt_ref_picture)
      pic_param->alt_ref_frame = priv->alt_ref_picture->surface_id;
  }
  pic_param->out_of_loop_frame = VA_INVALID_SURFACE;    // not used currently

  pic_param->pic_fields.value = 0;
  pic_param->pic_fields.bits.key_frame = !frame_hdr->key_frame;
  pic_param->pic_fields.bits.version = frame_hdr->version;
  pic_param->pic_fields.bits.segmentation_enabled = seg->segmentation_enabled;
  pic_param->pic_fields.bits.update_mb_segmentation_map =
      seg->update_mb_segmentation_map;
  pic_param->pic_fields.bits.update_segment_feature_data =
      seg->update_segment_feature_data;
  pic_param->pic_fields.bits.filter_type = frame_hdr->filter_type;
  pic_param->pic_fields.bits.sharpness_level = frame_hdr->sharpness_level;
  pic_param->pic_fields.bits.loop_filter_adj_enable =
      parser->mb_lf_adjust.loop_filter_adj_enable;
  pic_param->pic_fields.bits.mode_ref_lf_delta_update =
      parser->mb_lf_adjust.mode_ref_lf_delta_update;
  pic_param->pic_fields.bits.sign_bias_golden = frame_hdr->sign_bias_golden;
  pic_param->pic_fields.bits.sign_bias_alternate =
      frame_hdr->sign_bias_alternate;
  pic_param->pic_fields.bits.mb_no_coeff_skip = frame_hdr->mb_no_skip_coeff;

  for (i = 0; i < 3; i++)
    pic_param->mb_segment_tree_probs[i] = seg->segment_prob[i];

  for (i = 0; i < 4; i++) {
    if (seg->segmentation_enabled) {
      pic_param->loop_filter_level[i] = seg->lf_update_value[i];
      if (!seg->segment_feature_mode)
        pic_param->loop_filter_level[i] += frame_hdr->loop_filter_level;
    } else
      pic_param->loop_filter_level[i] = frame_hdr->loop_filter_level;

    pic_param->loop_filter_deltas_ref_frame[i] =
        parser->mb_lf_adjust.ref_frame_delta[i];
    pic_param->loop_filter_deltas_mode[i] =
        parser->mb_lf_adjust.mb_mode_delta[i];
  }

  /* In decoding, the only loop filter settings that matter are those
     in the frame header (9.1) */
  pic_param->pic_fields.bits.loop_filter_disable =
      frame_hdr->loop_filter_level == 0;

  pic_param->prob_skip_false = frame_hdr->prob_skip_false;
  pic_param->prob_intra = frame_hdr->prob_intra;
  pic_param->prob_last = frame_hdr->prob_last;
  pic_param->prob_gf = frame_hdr->prob_gf;

{'fraction_non_alphanumeric': 0.09867770081856617, 'fraction_numerical': 0.011244040658451021, 'mean_word_length': 4.825255436206445, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 289, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2480021', 'n_tokens_mistral': 8651, 'n_tokens_neox': 8171, 'n_words': 1451}