tech-invite   World Map     

IETF     RFCs     Groups     SIP     ABNFs    |    3GPP     Specs     Gloss.     Arch.     IMS     UICC    |    Misc.    |    search     info

RFC 6386

 
 
 

VP8 Data Format and Decoding Guide

Part 6 of 11, p. 133 to 157
Prev RFC Part       Next RFC Part

 


prevText      Top      Up      ToC       Page 133 
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>

Top      Up      ToC       Page 134 
   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 */

Top      Up      ToC       Page 135 
       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);
   }

Top      Up      ToC       Page 136 
   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 ----------------------------------------

Top      Up      ToC       Page 137 
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,

Top      Up      ToC       Page 138 
       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)

Top      Up      ToC       Page 139 
   {
       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;
                   }
       }
   }

Top      Up      ToC       Page 140 
   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)

Top      Up      ToC       Page 141 
   {
       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)

Top      Up      ToC       Page 142 
   {
       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);

Top      Up      ToC       Page 143 
           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;
   }

Top      Up      ToC       Page 144 
   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;

Top      Up      ToC       Page 145 
               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);

Top      Up      ToC       Page 146 
       /* 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);

Top      Up      ToC       Page 147 
       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]);
       }

Top      Up      ToC       Page 148 
       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);
   }

Top      Up      ToC       Page 149 
   #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;

Top      Up      ToC       Page 150 
           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 ----------------------------------------

Top      Up      ToC       Page 151 
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
   };

Top      Up      ToC       Page 152 
   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];
   };

Top      Up      ToC       Page 153 
   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];

Top      Up      ToC       Page 154 
   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
   };

Top      Up      ToC       Page 155 
   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;
   };

Top      Up      ToC       Page 156 
   /* 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;

Top      Up      ToC       Page 157 
       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 ----------------------------------------


Next RFC Part