+/**
+ * Pull DCT tokens from the 64 levels to decode and dequant the coefficients
+ * for the next block in coding order
+ */
+static inline int vp3_dequant(Vp3DecodeContext *s, Vp3Fragment *frag,
+ int plane, int inter, DCTELEM block[64])
+{
+ int16_t *dequantizer = s->qmat[frag->qpi][inter][plane];
+ uint8_t *perm = s->scantable.permutated;
+ int i = 0;
+
+ do {
+ int token = *s->dct_tokens[plane][i];
+ switch (token & 3) {
+ case 0: // EOB
+ if (--token < 4) // 0-3 are token types, so the EOB run must now be 0
+ s->dct_tokens[plane][i]++;
+ else
+ *s->dct_tokens[plane][i] = token & ~3;
+ goto end;
+ case 1: // zero run
+ s->dct_tokens[plane][i]++;
+ i += (token >> 2) & 0x7f;
+ if (i > 63) {
+ av_log(s->avctx, AV_LOG_ERROR, "Coefficient index overflow\n");
+ return i;
+ }
+ block[perm[i]] = (token >> 9) * dequantizer[perm[i]];
+ i++;
+ break;
+ case 2: // coeff
+ block[perm[i]] = (token >> 2) * dequantizer[perm[i]];
+ s->dct_tokens[plane][i++]++;
+ break;
+ default: // shouldn't happen
+ return i;
+ }
+ } while (i < 64);
+end:
+ // the actual DC+prediction is in the fragment structure
+ block[0] = frag->dc * s->qmat[0][inter][plane][0];
+ return i;
+}
+
+/**
+ * called when all pixels up to row y are complete
+ */
+static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y)
+{
+ int h, cy, i;
+ int offset[AV_NUM_DATA_POINTERS];
+
+ if (HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) {
+ int y_flipped = s->flipped_image ? s->avctx->height-y : y;
+
+ // At the end of the frame, report INT_MAX instead of the height of the frame.
+ // This makes the other threads' ff_thread_await_progress() calls cheaper, because
+ // they don't have to clip their values.
+ ff_thread_report_progress(&s->current_frame, y_flipped==s->avctx->height ? INT_MAX : y_flipped-1, 0);
+ }
+
+ if(s->avctx->draw_horiz_band==NULL)
+ return;
+
+ h= y - s->last_slice_end;
+ s->last_slice_end= y;
+ y -= h;
+
+ if (!s->flipped_image) {
+ y = s->avctx->height - y - h;
+ }
+
+ cy = y >> s->chroma_y_shift;
+ offset[0] = s->current_frame.linesize[0]*y;
+ offset[1] = s->current_frame.linesize[1]*cy;
+ offset[2] = s->current_frame.linesize[2]*cy;
+ for (i = 3; i < AV_NUM_DATA_POINTERS; i++)
+ offset[i] = 0;
+
+ emms_c();
+ s->avctx->draw_horiz_band(s->avctx, &s->current_frame, offset, y, 3, h);
+}
+
+/**
+ * Wait for the reference frame of the current fragment.
+ * The progress value is in luma pixel rows.
+ */
+static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment, int motion_y, int y)
+{
+ AVFrame *ref_frame;
+ int ref_row;
+ int border = motion_y&1;
+
+ if (fragment->coding_method == MODE_USING_GOLDEN ||
+ fragment->coding_method == MODE_GOLDEN_MV)
+ ref_frame = &s->golden_frame;
+ else
+ ref_frame = &s->last_frame;
+
+ ref_row = y + (motion_y>>1);
+ ref_row = FFMAX(FFABS(ref_row), ref_row + 8 + border);
+
+ ff_thread_await_progress(ref_frame, ref_row, 0);
+}
+