+static int get_relative_dist(const AV1RawSequenceHeader *seq,
+ unsigned int a, unsigned int b)
+{
+ unsigned int diff = a - b;
+ unsigned int m = 1 << seq->order_hint_bits_minus_1;
+ return (diff & (m - 1)) - (diff & m);
+}
+
+static void skip_mode_params(AV1DecContext *s)
+{
+ const AV1RawFrameHeader *header = s->raw_frame_header;
+ const AV1RawSequenceHeader *seq = s->raw_seq;
+
+ int forward_idx, backward_idx;
+ int forward_hint, backward_hint;
+ int second_forward_idx, second_forward_hint;
+ int ref_hint, dist, i;
+
+ if (!header->skip_mode_present)
+ return;
+
+ forward_idx = -1;
+ backward_idx = -1;
+ for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
+ ref_hint = s->ref[header->ref_frame_idx[i]].raw_frame_header->order_hint;
+ dist = get_relative_dist(seq, ref_hint, header->order_hint);
+ if (dist < 0) {
+ if (forward_idx < 0 ||
+ get_relative_dist(seq, ref_hint, forward_hint) > 0) {
+ forward_idx = i;
+ forward_hint = ref_hint;
+ }
+ } else if (dist > 0) {
+ if (backward_idx < 0 ||
+ get_relative_dist(seq, ref_hint, backward_hint) < 0) {
+ backward_idx = i;
+ backward_hint = ref_hint;
+ }
+ }
+ }
+
+ if (forward_idx < 0) {
+ return;
+ } else if (backward_idx >= 0) {
+ s->cur_frame.skip_mode_frame_idx[0] =
+ AV1_REF_FRAME_LAST + FFMIN(forward_idx, backward_idx);
+ s->cur_frame.skip_mode_frame_idx[1] =
+ AV1_REF_FRAME_LAST + FFMAX(forward_idx, backward_idx);
+ return;
+ }
+
+ second_forward_idx = -1;
+ for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
+ ref_hint = s->ref[header->ref_frame_idx[i]].raw_frame_header->order_hint;
+ if (get_relative_dist(seq, ref_hint, forward_hint) < 0) {
+ if (second_forward_idx < 0 ||
+ get_relative_dist(seq, ref_hint, second_forward_hint) > 0) {
+ second_forward_idx = i;
+ second_forward_hint = ref_hint;
+ }
+ }
+ }
+
+ if (second_forward_idx < 0)
+ return;
+
+ s->cur_frame.skip_mode_frame_idx[0] =
+ AV1_REF_FRAME_LAST + FFMIN(forward_idx, second_forward_idx);
+ s->cur_frame.skip_mode_frame_idx[1] =
+ AV1_REF_FRAME_LAST + FFMAX(forward_idx, second_forward_idx);
+}
+
+static void coded_lossless_param(AV1DecContext *s)
+{
+ const AV1RawFrameHeader *header = s->raw_frame_header;
+ int i;
+
+ if (header->delta_q_y_dc || header->delta_q_u_ac ||
+ header->delta_q_u_dc || header->delta_q_v_ac ||
+ header->delta_q_v_dc) {
+ s->cur_frame.coded_lossless = 0;
+ return;
+ }
+
+ s->cur_frame.coded_lossless = 1;
+ for (i = 0; i < AV1_MAX_SEGMENTS; i++) {
+ int qindex;
+ if (header->feature_enabled[i][AV1_SEG_LVL_ALT_Q]) {
+ qindex = (header->base_q_idx +
+ header->feature_value[i][AV1_SEG_LVL_ALT_Q]);
+ } else {
+ qindex = header->base_q_idx;
+ }
+ qindex = av_clip_uintp2(qindex, 8);
+
+ if (qindex) {
+ s->cur_frame.coded_lossless = 0;
+ return;
+ }
+ }
+}
+
+static void load_grain_params(AV1DecContext *s)
+{
+ const AV1RawFrameHeader *header = s->raw_frame_header;
+ const AV1RawFilmGrainParams *film_grain = &header->film_grain, *src;
+ AV1RawFilmGrainParams *dst = &s->cur_frame.film_grain;
+
+ if (!film_grain->apply_grain)
+ return;
+
+ if (film_grain->update_grain) {
+ memcpy(dst, film_grain, sizeof(*dst));
+ return;
+ }
+
+ src = &s->ref[film_grain->film_grain_params_ref_idx].film_grain;
+
+ memcpy(dst, src, sizeof(*dst));
+ dst->grain_seed = film_grain->grain_seed;
+}
+