20. Attachment One: Reference Decoder Source Code
20.1. bit_ops.h
---- Begin code block -------------------------------------- /* * Copyright (c) 2010, 2011, Google Inc. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be * found in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef BIT_OPS_H #define BIT_OPS_H /* Evaluates to a mask with n bits set */ #define BITS_MASK(n) ((1<<(n))-1) /* Returns len bits, with the LSB at position bit */ #define BITS_GET(val, bit, len) (((val)>>(bit))&BITS_MASK(len)) #endif ---- End code block ----------------------------------------20.2. bool_decoder.h
---- Begin code block -------------------------------------- /* * Copyright (c) 2010, 2011, Google Inc. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be * found in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef BOOL_DECODER_H #define BOOL_DECODER_H #include <stddef.h>
struct bool_decoder { const unsigned char *input; /* next compressed data byte */ size_t input_len; /* length of the input buffer */ unsigned int range; /* identical to encoder's * range */ unsigned int value; /* contains at least 8 * significant bits */ int bit_count; /* # of bits shifted out of * value, max 7 */ }; static void init_bool_decoder(struct bool_decoder *d, const unsigned char *start_partition, size_t sz) { if (sz >= 2) { d->value = (start_partition[0] << 8) /* first 2 input * bytes */ | start_partition[1]; d->input = start_partition + 2; /* ptr to next byte */ d->input_len = sz - 2; } else { d->value = 0; d->input = NULL; d->input_len = 0; } d->range = 255; /* initial range is full */ d->bit_count = 0; /* have not yet shifted out any bits */ } static int bool_get(struct bool_decoder *d, int probability) { /* range and split are identical to the corresponding values used by the encoder when this bool was written */ unsigned int split = 1 + (((d->range - 1) * probability) >> 8); unsigned int SPLIT = split << 8; int retval; /* will be 0 or 1 */
if (d->value >= SPLIT) /* encoded a one */ { retval = 1; d->range -= split; /* reduce range */ d->value -= SPLIT; /* subtract off left endpoint of * interval */ } else /* encoded a zero */ { retval = 0; d->range = split; /* reduce range, no change in left * endpoint */ } while (d->range < 128) /* shift out irrelevant value bits */ { d->value <<= 1; d->range <<= 1; if (++d->bit_count == 8) /* shift in new bits 8 at a time */ { d->bit_count = 0; if (d->input_len) { d->value |= *d->input++; d->input_len--; } } } return retval; } static int bool_get_bit(struct bool_decoder *br) { return bool_get(br, 128); }
static int bool_get_uint(struct bool_decoder *br, int bits) { int z = 0; int bit; for (bit = bits - 1; bit >= 0; bit--) { z |= (bool_get_bit(br) << bit); } return z; } static int bool_get_int(struct bool_decoder *br, int bits) { int z = 0; int bit; for (bit = bits - 1; bit >= 0; bit--) { z |= (bool_get_bit(br) << bit); } return bool_get_bit(br) ? -z : z; } static int bool_maybe_get_int(struct bool_decoder *br, int bits) { return bool_get_bit(br) ? bool_get_int(br, bits) : 0; } static int bool_read_tree(struct bool_decoder *bool, const int *t, const unsigned char *p) { int i = 0; while ((i = t[ i + bool_get(bool, p[i>>1])]) > 0); return -i; } #endif ---- End code block ----------------------------------------
20.3. dequant_data.h
---- Begin code block -------------------------------------- /* * Copyright (c) 2010, 2011, Google Inc. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be * found in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ static const int dc_q_lookup[128] = { 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 93, 95, 96, 98, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157 }; static const int ac_q_lookup[128] = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152,
155, 158, 161, 164, 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284 }; ---- End code block ----------------------------------------20.4. dixie.c
---- Begin code block -------------------------------------- /* * Copyright (c) 2010, 2011, Google Inc. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be * found in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "vpx_codec_internal.h" #include "bit_ops.h" #include "dixie.h" #include "vp8_prob_data.h" #include "dequant_data.h" #include "modemv.h" #include "tokens.h" #include "predict.h" #include "dixie_loopfilter.h" #include <string.h> #include <assert.h> enum { FRAME_HEADER_SZ = 3, KEYFRAME_HEADER_SZ = 7 }; #define ARRAY_COPY(a,b) {\ assert(sizeof(a)==sizeof(b));memcpy(a,b,sizeof(a));} static void decode_entropy_header(struct vp8_decoder_ctx *ctx, struct bool_decoder *bool, struct vp8_entropy_hdr *hdr)
{ int i, j, k, l; /* Read coefficient probability updates */ for (i = 0; i < BLOCK_TYPES; i++) for (j = 0; j < COEFF_BANDS; j++) for (k = 0; k < PREV_COEFF_CONTEXTS; k++) for (l = 0; l < ENTROPY_NODES; l++) if (bool_get(bool, k_coeff_entropy_update_probs [i][j][k][l])) hdr->coeff_probs[i][j][k][l] = bool_get_uint(bool, 8); /* Read coefficient skip mode probability */ hdr->coeff_skip_enabled = bool_get_bit(bool); if (hdr->coeff_skip_enabled) hdr->coeff_skip_prob = bool_get_uint(bool, 8); /* Parse interframe probability updates */ if (!ctx->frame_hdr.is_keyframe) { hdr->prob_inter = bool_get_uint(bool, 8); hdr->prob_last = bool_get_uint(bool, 8); hdr->prob_gf = bool_get_uint(bool, 8); if (bool_get_bit(bool)) for (i = 0; i < 4; i++) hdr->y_mode_probs[i] = bool_get_uint(bool, 8); if (bool_get_bit(bool)) for (i = 0; i < 3; i++) hdr->uv_mode_probs[i] = bool_get_uint(bool, 8); for (i = 0; i < 2; i++) for (j = 0; j < MV_PROB_CNT; j++) if (bool_get(bool, k_mv_entropy_update_probs[i][j])) { int x = bool_get_uint(bool, 7); hdr->mv_probs[i][j] = x ? x << 1 : 1; } } }
static void decode_reference_header(struct vp8_decoder_ctx *ctx, struct bool_decoder *bool, struct vp8_reference_hdr *hdr) { unsigned int key = ctx->frame_hdr.is_keyframe; hdr->refresh_gf = key ? 1 : bool_get_bit(bool); hdr->refresh_arf = key ? 1 : bool_get_bit(bool); hdr->copy_gf = key ? 0 : !hdr->refresh_gf ? bool_get_uint(bool, 2) : 0; hdr->copy_arf = key ? 0 : !hdr->refresh_arf ? bool_get_uint(bool, 2) : 0; hdr->sign_bias[GOLDEN_FRAME] = key ? 0 : bool_get_bit(bool); hdr->sign_bias[ALTREF_FRAME] = key ? 0 : bool_get_bit(bool); hdr->refresh_entropy = bool_get_bit(bool); hdr->refresh_last = key ? 1 : bool_get_bit(bool); } static void decode_quantizer_header(struct vp8_decoder_ctx *ctx, struct bool_decoder *bool, struct vp8_quant_hdr *hdr) { int update; int last_q = hdr->q_index; hdr->q_index = bool_get_uint(bool, 7); update = last_q != hdr->q_index; update |= (hdr->y1_dc_delta_q = bool_maybe_get_int(bool, 4)); update |= (hdr->y2_dc_delta_q = bool_maybe_get_int(bool, 4)); update |= (hdr->y2_ac_delta_q = bool_maybe_get_int(bool, 4)); update |= (hdr->uv_dc_delta_q = bool_maybe_get_int(bool, 4)); update |= (hdr->uv_ac_delta_q = bool_maybe_get_int(bool, 4)); hdr->delta_update = update; } static void decode_and_init_token_partitions(struct vp8_decoder_ctx *ctx, struct bool_decoder *bool, const unsigned char *data, unsigned int sz, struct vp8_token_hdr *hdr)
{ int i; hdr->partitions = 1 << bool_get_uint(bool, 2); if (sz < 3 *(hdr->partitions - 1)) vpx_internal_error(&ctx->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet found parsing partition" " lengths."); sz -= 3 * (hdr->partitions - 1); for (i = 0; i < hdr->partitions; i++) { if (i < hdr->partitions - 1) { hdr->partition_sz[i] = (data[2] << 16) | (data[1] << 8) | data[0]; data += 3; } else hdr->partition_sz[i] = sz; if (sz < hdr->partition_sz[i]) vpx_internal_error(&ctx->error, VPX_CODEC_CORRUPT_FRAME, "Truncated partition %d", i); sz -= hdr->partition_sz[i]; } for (i = 0; i < ctx->token_hdr.partitions; i++) { init_bool_decoder(&ctx->tokens[i].bool, data, ctx->token_hdr.partition_sz[i]); data += ctx->token_hdr.partition_sz[i]; } } static void decode_loopfilter_header(struct vp8_decoder_ctx *ctx, struct bool_decoder *bool, struct vp8_loopfilter_hdr *hdr)
{ if (ctx->frame_hdr.is_keyframe) memset(hdr, 0, sizeof(*hdr)); hdr->use_simple = bool_get_bit(bool); hdr->level = bool_get_uint(bool, 6); hdr->sharpness = bool_get_uint(bool, 3); hdr->delta_enabled = bool_get_bit(bool); if (hdr->delta_enabled && bool_get_bit(bool)) { int i; for (i = 0; i < BLOCK_CONTEXTS; i++) hdr->ref_delta[i] = bool_maybe_get_int(bool, 6); for (i = 0; i < BLOCK_CONTEXTS; i++) hdr->mode_delta[i] = bool_maybe_get_int(bool, 6); } } static void decode_segmentation_header(struct vp8_decoder_ctx *ctx, struct bool_decoder *bool, struct vp8_segment_hdr *hdr) { if (ctx->frame_hdr.is_keyframe) memset(hdr, 0, sizeof(*hdr)); hdr->enabled = bool_get_bit(bool); if (hdr->enabled) { int i; hdr->update_map = bool_get_bit(bool); hdr->update_data = bool_get_bit(bool);
if (hdr->update_data) { hdr->abs = bool_get_bit(bool); for (i = 0; i < MAX_MB_SEGMENTS; i++) hdr->quant_idx[i] = bool_maybe_get_int(bool, 7); for (i = 0; i < MAX_MB_SEGMENTS; i++) hdr->lf_level[i] = bool_maybe_get_int(bool, 6); } if (hdr->update_map) { for (i = 0; i < MB_FEATURE_TREE_PROBS; i++) hdr->tree_probs[i] = bool_get_bit(bool) ? bool_get_uint(bool, 8) : 255; } } else { hdr->update_map = 0; hdr->update_data = 0; } } static void dequant_global_init(struct dequant_factors dqf[MAX_MB_SEGMENTS]) { int i; for (i = 0; i < MAX_MB_SEGMENTS; i++) dqf[i].quant_idx = -1; } static int clamp_q(int q) { if (q < 0) return 0; else if (q > 127) return 127; return q; }
static int dc_q(int q) { return dc_q_lookup[clamp_q(q)]; } static int ac_q(int q) { return ac_q_lookup[clamp_q(q)]; } static void dequant_init(struct dequant_factors factors[MAX_MB_SEGMENTS], const struct vp8_segment_hdr *seg, const struct vp8_quant_hdr *quant_hdr) { int i, q; struct dequant_factors *dqf = factors; for (i = 0; i < (seg->enabled ? MAX_MB_SEGMENTS : 1); i++) { q = quant_hdr->q_index; if (seg->enabled) q = (!seg->abs) ? q + seg->quant_idx[i] : seg->quant_idx[i]; if (dqf->quant_idx != q || quant_hdr->delta_update) { dqf->factor[TOKEN_BLOCK_Y1][0] = dc_q(q + quant_hdr->y1_dc_delta_q); dqf->factor[TOKEN_BLOCK_Y1][1] = ac_q(q); dqf->factor[TOKEN_BLOCK_UV][0] = dc_q(q + quant_hdr->uv_dc_delta_q); dqf->factor[TOKEN_BLOCK_UV][1] = ac_q(q + quant_hdr->uv_ac_delta_q); dqf->factor[TOKEN_BLOCK_Y2][0] = dc_q(q + quant_hdr->y2_dc_delta_q) * 2; dqf->factor[TOKEN_BLOCK_Y2][1] = ac_q(q + quant_hdr->y2_ac_delta_q) * 155 / 100; if (dqf->factor[TOKEN_BLOCK_Y2][1] < 8) dqf->factor[TOKEN_BLOCK_Y2][1] = 8;
if (dqf->factor[TOKEN_BLOCK_UV][0] > 132) dqf->factor[TOKEN_BLOCK_UV][0] = 132; dqf->quant_idx = q; } dqf++; } } static void decode_frame(struct vp8_decoder_ctx *ctx, const unsigned char *data, unsigned int sz) { vpx_codec_err_t res; struct bool_decoder bool; int i, row, partition; ctx->saved_entropy_valid = 0; if ((res = vp8_parse_frame_header(data, sz, &ctx->frame_hdr))) vpx_internal_error(&ctx->error, res, "Failed to parse frame header"); if (ctx->frame_hdr.is_experimental) vpx_internal_error(&ctx->error, VPX_CODEC_UNSUP_BITSTREAM, "Experimental bitstreams not supported."); data += FRAME_HEADER_SZ; sz -= FRAME_HEADER_SZ; if (ctx->frame_hdr.is_keyframe) { data += KEYFRAME_HEADER_SZ; sz -= KEYFRAME_HEADER_SZ; ctx->mb_cols = (ctx->frame_hdr.kf.w + 15) / 16; ctx->mb_rows = (ctx->frame_hdr.kf.h + 15) / 16; } /* Start the bitreader for the header/entropy partition */ init_bool_decoder(&bool, data, ctx->frame_hdr.part0_sz);
/* Skip the colorspace and clamping bits */ if (ctx->frame_hdr.is_keyframe) if (bool_get_uint(&bool, 2)) vpx_internal_error( &ctx->error, VPX_CODEC_UNSUP_BITSTREAM, "Reserved bits not supported."); decode_segmentation_header(ctx, &bool, &ctx->segment_hdr); decode_loopfilter_header(ctx, &bool, &ctx->loopfilter_hdr); decode_and_init_token_partitions(ctx, &bool, data + ctx->frame_hdr.part0_sz, sz - ctx->frame_hdr.part0_sz, &ctx->token_hdr); decode_quantizer_header(ctx, &bool, &ctx->quant_hdr); decode_reference_header(ctx, &bool, &ctx->reference_hdr); /* Set keyframe entropy defaults. These get updated on keyframes * regardless of the refresh_entropy setting. */ if (ctx->frame_hdr.is_keyframe) { ARRAY_COPY(ctx->entropy_hdr.coeff_probs, k_default_coeff_probs); ARRAY_COPY(ctx->entropy_hdr.mv_probs, k_default_mv_probs); ARRAY_COPY(ctx->entropy_hdr.y_mode_probs, k_default_y_mode_probs); ARRAY_COPY(ctx->entropy_hdr.uv_mode_probs, k_default_uv_mode_probs); } if (!ctx->reference_hdr.refresh_entropy) { ctx->saved_entropy = ctx->entropy_hdr; ctx->saved_entropy_valid = 1; } decode_entropy_header(ctx, &bool, &ctx->entropy_hdr); vp8_dixie_modemv_init(ctx); vp8_dixie_tokens_init(ctx); vp8_dixie_predict_init(ctx); dequant_init(ctx->dequant_factors, &ctx->segment_hdr, &ctx->quant_hdr);
for (row = 0, partition = 0; row < ctx->mb_rows; row++) { vp8_dixie_modemv_process_row( ctx, &bool, row, 0, ctx->mb_cols); vp8_dixie_tokens_process_row(ctx, partition, row, 0, ctx->mb_cols); vp8_dixie_predict_process_row(ctx, row, 0, ctx->mb_cols); if (ctx->loopfilter_hdr.level && row) vp8_dixie_loopfilter_process_row(ctx, row - 1, 0, ctx->mb_cols); if (++partition == ctx->token_hdr.partitions) partition = 0; } if (ctx->loopfilter_hdr.level) vp8_dixie_loopfilter_process_row( ctx, row - 1, 0, ctx->mb_cols); ctx->frame_cnt++; if (!ctx->reference_hdr.refresh_entropy) { ctx->entropy_hdr = ctx->saved_entropy; ctx->saved_entropy_valid = 0; } /* Handle reference frame updates */ if (ctx->reference_hdr.copy_arf == 1) { vp8_dixie_release_ref_frame(ctx->ref_frames[ALTREF_FRAME]); ctx->ref_frames[ALTREF_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[LAST_FRAME]); } else if (ctx->reference_hdr.copy_arf == 2) { vp8_dixie_release_ref_frame(ctx->ref_frames[ALTREF_FRAME]); ctx->ref_frames[ALTREF_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[GOLDEN_FRAME]); } if (ctx->reference_hdr.copy_gf == 1) { vp8_dixie_release_ref_frame(ctx->ref_frames[GOLDEN_FRAME]); ctx->ref_frames[GOLDEN_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[LAST_FRAME]); }
else if (ctx->reference_hdr.copy_gf == 2) { vp8_dixie_release_ref_frame(ctx->ref_frames[GOLDEN_FRAME]); ctx->ref_frames[GOLDEN_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[ALTREF_FRAME]); } if (ctx->reference_hdr.refresh_gf) { vp8_dixie_release_ref_frame(ctx->ref_frames[GOLDEN_FRAME]); ctx->ref_frames[GOLDEN_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[CURRENT_FRAME]); } if (ctx->reference_hdr.refresh_arf) { vp8_dixie_release_ref_frame(ctx->ref_frames[ALTREF_FRAME]); ctx->ref_frames[ALTREF_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[CURRENT_FRAME]); } if (ctx->reference_hdr.refresh_last) { vp8_dixie_release_ref_frame(ctx->ref_frames[LAST_FRAME]); ctx->ref_frames[LAST_FRAME] = vp8_dixie_ref_frame(ctx->ref_frames[CURRENT_FRAME]); } } void vp8_dixie_decode_init(struct vp8_decoder_ctx *ctx) { dequant_global_init(ctx->dequant_factors); }
#define CHECK_FOR_UPDATE(lval,rval,update_flag) do {\ unsigned int old = lval; \ update_flag |= (old != (lval = rval)); \ } while (0) vpx_codec_err_t vp8_parse_frame_header(const unsigned char *data, unsigned int sz, struct vp8_frame_hdr *hdr) { unsigned long raw; if (sz < 10) return VPX_CODEC_CORRUPT_FRAME; /* The frame header is defined as a three-byte little endian * value */ raw = data[0] | (data[1] << 8) | (data[2] << 16); hdr->is_keyframe = !BITS_GET(raw, 0, 1); hdr->version = BITS_GET(raw, 1, 2); hdr->is_experimental = BITS_GET(raw, 3, 1); hdr->is_shown = BITS_GET(raw, 4, 1); hdr->part0_sz = BITS_GET(raw, 5, 19); if (sz <= hdr->part0_sz + (hdr->is_keyframe ? 10 : 3)) return VPX_CODEC_CORRUPT_FRAME; hdr->frame_size_updated = 0; if (hdr->is_keyframe) { unsigned int update = 0; /* Keyframe header consists of a three-byte sync code * followed by the width and height and associated scaling * factors. */ if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a) return VPX_CODEC_UNSUP_BITSTREAM;
raw = data[6] | (data[7] << 8) | (data[8] << 16) | (data[9] << 24); CHECK_FOR_UPDATE(hdr->kf.w, BITS_GET(raw, 0, 14), update); CHECK_FOR_UPDATE(hdr->kf.scale_w, BITS_GET(raw, 14, 2), update); CHECK_FOR_UPDATE(hdr->kf.h, BITS_GET(raw, 16, 14), update); CHECK_FOR_UPDATE(hdr->kf.scale_h, BITS_GET(raw, 30, 2), update); hdr->frame_size_updated = update; if (!hdr->kf.w || !hdr->kf.h) return VPX_CODEC_UNSUP_BITSTREAM; } return VPX_CODEC_OK; } vpx_codec_err_t vp8_dixie_decode_frame(struct vp8_decoder_ctx *ctx, const unsigned char *data, unsigned int sz) { volatile struct vp8_decoder_ctx *ctx_ = ctx; ctx->error.error_code = VPX_CODEC_OK; ctx->error.has_detail = 0; if (!setjmp(ctx->error.jmp)) decode_frame(ctx, data, sz); return ctx_->error.error_code; } void vp8_dixie_decode_destroy(struct vp8_decoder_ctx *ctx) { vp8_dixie_predict_destroy(ctx); vp8_dixie_tokens_destroy(ctx); vp8_dixie_modemv_destroy(ctx); } ---- End code block ----------------------------------------
20.5. dixie.h
---- Begin code block -------------------------------------- /* * Copyright (c) 2010, 2011, Google Inc. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be * found in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef DIXIE_H #define DIXIE_H #include "vpx_codec_internal.h" #include "bool_decoder.h" struct vp8_frame_hdr { unsigned int is_keyframe; /* Frame is a keyframe */ unsigned int is_experimental; /* Frame is a keyframe */ unsigned int version; /* Bitstream version */ unsigned int is_shown; /* Frame is to be displayed. */ unsigned int part0_sz; /* Partition 0 length, in bytes */ struct vp8_kf_hdr { unsigned int w; /* Width */ unsigned int h; /* Height */ unsigned int scale_w; /* Scaling factor, Width */ unsigned int scale_h; /* Scaling factor, Height */ } kf; unsigned int frame_size_updated; /* Flag to indicate a resolution * update. */ }; enum { MB_FEATURE_TREE_PROBS = 3, MAX_MB_SEGMENTS = 4 };
struct vp8_segment_hdr { unsigned int enabled; unsigned int update_data; unsigned int update_map; unsigned int abs; /* 0=deltas, 1=absolute values */ unsigned int tree_probs[MB_FEATURE_TREE_PROBS]; int lf_level[MAX_MB_SEGMENTS]; int quant_idx[MAX_MB_SEGMENTS]; }; enum { BLOCK_CONTEXTS = 4 }; struct vp8_loopfilter_hdr { unsigned int use_simple; unsigned int level; unsigned int sharpness; unsigned int delta_enabled; int ref_delta[BLOCK_CONTEXTS]; int mode_delta[BLOCK_CONTEXTS]; }; enum { MAX_PARTITIONS = 8 }; struct vp8_token_hdr { unsigned int partitions; unsigned int partition_sz[MAX_PARTITIONS]; };
struct vp8_quant_hdr { unsigned int q_index; int delta_update; int y1_dc_delta_q; int y2_dc_delta_q; int y2_ac_delta_q; int uv_dc_delta_q; int uv_ac_delta_q; }; struct vp8_reference_hdr { unsigned int refresh_last; unsigned int refresh_gf; unsigned int refresh_arf; unsigned int copy_gf; unsigned int copy_arf; unsigned int sign_bias[4]; unsigned int refresh_entropy; }; enum { BLOCK_TYPES = 4, PREV_COEFF_CONTEXTS = 3, COEFF_BANDS = 8, ENTROPY_NODES = 11, }; typedef unsigned char coeff_probs_table_t[BLOCK_TYPES][COEFF_BANDS] [PREV_COEFF_CONTEXTS] [ENTROPY_NODES]; enum { MV_PROB_CNT = 2 + 8 - 1 + 10 /* from entropymv.h */ }; typedef unsigned char mv_component_probs_t[MV_PROB_CNT];
struct vp8_entropy_hdr { coeff_probs_table_t coeff_probs; mv_component_probs_t mv_probs[2]; unsigned int coeff_skip_enabled; unsigned char coeff_skip_prob; unsigned char y_mode_probs[4]; unsigned char uv_mode_probs[3]; unsigned char prob_inter; unsigned char prob_last; unsigned char prob_gf; }; enum reference_frame { CURRENT_FRAME, LAST_FRAME, GOLDEN_FRAME, ALTREF_FRAME, NUM_REF_FRAMES }; enum prediction_mode { /* 16x16 intra modes */ DC_PRED, V_PRED, H_PRED, TM_PRED, B_PRED, /* 16x16 inter modes */ NEARESTMV, NEARMV, ZEROMV, NEWMV, SPLITMV, MB_MODE_COUNT, /* 4x4 intra modes */ B_DC_PRED = 0, B_TM_PRED, B_VE_PRED, B_HE_PRED, B_LD_PRED, B_RD_PRED, B_VR_PRED, B_VL_PRED, B_HD_PRED, B_HU_PRED, /* 4x4 inter modes */ LEFT4X4, ABOVE4X4, ZERO4X4, NEW4X4, B_MODE_COUNT };
enum splitmv_partitioning { SPLITMV_16X8, SPLITMV_8X16, SPLITMV_8X8, SPLITMV_4X4 }; typedef short filter_t[6]; typedef union mv { struct { int16_t x, y; } d; uint32_t raw; } mv_t; struct mb_base_info { unsigned char y_mode : 4; unsigned char uv_mode : 4; unsigned char segment_id : 2; unsigned char ref_frame : 2; unsigned char skip_coeff : 1; unsigned char need_mc_border : 1; enum splitmv_partitioning partitioning : 2; union mv mv; unsigned int eob_mask; }; struct mb_info { struct mb_base_info base; union { union mv mvs[16]; enum prediction_mode modes[16]; } split; };
/* A "token entropy context" has 4 Y values, 2 U, 2 V, and 1 Y2 */ typedef int token_entropy_ctx_t[4 + 2 + 2 + 1]; struct token_decoder { struct bool_decoder bool; token_entropy_ctx_t left_token_entropy_ctx; short *coeffs; }; enum token_block_type { TOKEN_BLOCK_Y1, TOKEN_BLOCK_UV, TOKEN_BLOCK_Y2, TOKEN_BLOCK_TYPES, }; struct dequant_factors { int quant_idx; short factor[TOKEN_BLOCK_TYPES][2]; /* [ Y1, UV, Y2 ] * [ DC, AC ] */ }; struct ref_cnt_img { vpx_image_t img; unsigned int ref_cnt; }; struct vp8_decoder_ctx { struct vpx_internal_error_info error; unsigned int frame_cnt; struct vp8_frame_hdr frame_hdr; struct vp8_segment_hdr segment_hdr; struct vp8_loopfilter_hdr loopfilter_hdr; struct vp8_token_hdr token_hdr; struct vp8_quant_hdr quant_hdr; struct vp8_reference_hdr reference_hdr; struct vp8_entropy_hdr entropy_hdr; struct vp8_entropy_hdr saved_entropy; unsigned int saved_entropy_valid;
unsigned int mb_rows; unsigned int mb_cols; struct mb_info *mb_info_storage; struct mb_info **mb_info_rows_storage; struct mb_info **mb_info_rows; token_entropy_ctx_t *above_token_entropy_ctx; struct token_decoder tokens[MAX_PARTITIONS]; struct dequant_factors dequant_factors[MAX_MB_SEGMENTS]; struct ref_cnt_img frame_strg[NUM_REF_FRAMES]; struct ref_cnt_img *ref_frames[NUM_REF_FRAMES]; ptrdiff_t ref_frame_offsets[4]; const filter_t *subpixel_filters; }; void vp8_dixie_decode_init(struct vp8_decoder_ctx *ctx); void vp8_dixie_decode_destroy(struct vp8_decoder_ctx *ctx); vpx_codec_err_t vp8_parse_frame_header(const unsigned char *data, unsigned int sz, struct vp8_frame_hdr *hdr); vpx_codec_err_t vp8_dixie_decode_frame(struct vp8_decoder_ctx *ctx, const unsigned char *data, unsigned int sz); #define CLAMP_255(x) ((x)<0?0:((x)>255?255:(x))) #endif ---- End code block ----------------------------------------