1380 lines · 39.6 KB · C
RawDownload
/* *  Copyright (c) 2010 The WebM project authors. 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 "vp8/common/header.h"#include "encodemv.h"#include "vp8/common/entropymode.h"#include "vp8/common/findnearmv.h"#include "mcomp.h"#include "vp8/common/systemdependent.h"#include <assert.h>#include <stdio.h>#include <limits.h>#include "vpx/vpx_encoder.h"#include "vpx_mem/vpx_mem.h"#include "vpx_ports/system_state.h"#include "bitstream.h" #include "defaultcoefcounts.h"#include "vp8/common/common.h" const int vp8cx_base_skip_false_prob[128] = {  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 248, 244, 240,  236, 232, 229, 225, 221, 217, 213, 208, 204, 199, 194, 190, 187, 183, 179,  175, 172, 168, 164, 160, 157, 153, 149, 145, 142, 138, 134, 130, 127, 124,  120, 117, 114, 110, 107, 104, 101, 98,  95,  92,  89,  86,  83,  80,  77,  74,  71,  68,  65,  62,  59,  56,  53,  50,  47,  44,  41,  38,  35,  32,  30,  28,  26,  24,  22,  20,  18,  16,}; #if defined(SECTIONBITS_OUTPUT)unsigned __int64 Sectionbits[500];#endif #ifdef MODE_STATSint count_mb_seg[4] = { 0, 0, 0, 0 };#endif static void update_mode(vp8_writer *const w, int n, vp8_token tok[/* n */],                        vp8_tree tree, vp8_prob Pnew[/* n-1 */],                        vp8_prob Pcur[/* n-1 */],                        unsigned int bct[/* n-1 */][2],                        const unsigned int num_events[/* n */]) {  unsigned int new_b = 0, old_b = 0;  int i = 0;   vp8_tree_probs_from_distribution(n--, tok, tree, Pnew, bct, num_events, 256,                                   1);   do {    new_b += vp8_cost_branch(bct[i], Pnew[i]);    old_b += vp8_cost_branch(bct[i], Pcur[i]);  } while (++i < n);   if (new_b + (n << 8) < old_b) {    int j = 0;     vp8_write_bit(w, 1);     do {      const vp8_prob p = Pnew[j];       vp8_write_literal(w, Pcur[j] = p ? p : 1, 8);    } while (++j < n);  } else    vp8_write_bit(w, 0);} static void update_mbintra_mode_probs(VP8_COMP *cpi) {  VP8_COMMON *const x = &cpi->common;   vp8_writer *const w = cpi->bc;   {    vp8_prob Pnew[VP8_YMODES - 1];    unsigned int bct[VP8_YMODES - 1][2];     update_mode(w, VP8_YMODES, vp8_ymode_encodings, vp8_ymode_tree, Pnew,                x->fc.ymode_prob, bct, (unsigned int *)cpi->mb.ymode_count);  }  {    vp8_prob Pnew[VP8_UV_MODES - 1];    unsigned int bct[VP8_UV_MODES - 1][2];     update_mode(w, VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree, Pnew,                x->fc.uv_mode_prob, bct, (unsigned int *)cpi->mb.uv_mode_count);  }} static void write_ymode(vp8_writer *bc, int m, const vp8_prob *p) {  vp8_write_token(bc, vp8_ymode_tree, p, vp8_ymode_encodings + m);} static void kfwrite_ymode(vp8_writer *bc, int m, const vp8_prob *p) {  vp8_write_token(bc, vp8_kf_ymode_tree, p, vp8_kf_ymode_encodings + m);} static void write_uv_mode(vp8_writer *bc, int m, const vp8_prob *p) {  vp8_write_token(bc, vp8_uv_mode_tree, p, vp8_uv_mode_encodings + m);} static void write_bmode(vp8_writer *bc, int m, const vp8_prob *p) {  vp8_write_token(bc, vp8_bmode_tree, p, vp8_bmode_encodings + m);} static void write_split(vp8_writer *bc, int x) {  vp8_write_token(bc, vp8_mbsplit_tree, vp8_mbsplit_probs,                  vp8_mbsplit_encodings + x);} void vp8_pack_tokens(vp8_writer *w, const TOKENEXTRA *p, int xcount) {  const TOKENEXTRA *stop = p + xcount;  unsigned int split;  int shift;  int count = w->count;  unsigned int range = w->range;  unsigned int lowvalue = w->lowvalue;   while (p < stop) {    const int t = p->Token;    vp8_token *a = vp8_coef_encodings + t;    const vp8_extra_bit_struct *b = vp8_extra_bits + t;    int i = 0;    const unsigned char *pp = p->context_tree;    int v = a->value;    int n = a->Len;     if (p->skip_eob_node) {      n--;      i = 2;    }     do {      const int bb = (v >> --n) & 1;      split = 1 + (((range - 1) * pp[i >> 1]) >> 8);      i = vp8_coef_tree[i + bb];       if (bb) {        lowvalue += split;        range = range - split;      } else {        range = split;      }       shift = vp8_norm[range];      range <<= shift;      count += shift;       if (count >= 0) {        int offset = shift - count;         if ((lowvalue << (offset - 1)) & 0x80000000) {          int x = w->pos - 1;           while (x >= 0 && w->buffer[x] == 0xff) {            w->buffer[x] = (unsigned char)0;            x--;          }           w->buffer[x] += 1;        }         validate_buffer(w->buffer + w->pos, 1, w->buffer_end, w->error);         w->buffer[w->pos++] = (lowvalue >> (24 - offset)) & 0xff;        lowvalue <<= offset;        shift = count;        lowvalue &= 0xffffff;        count -= 8;      }       lowvalue <<= shift;    } while (n);     if (b->base_val) {      const int e = p->Extra, L = b->Len;       if (L) {        const unsigned char *proba = b->prob;        const int v2 = e >> 1;        int n2 = L; /* number of bits in v2, assumed nonzero */        i = 0;         do {          const int bb = (v2 >> --n2) & 1;          split = 1 + (((range - 1) * proba[i >> 1]) >> 8);          i = b->tree[i + bb];           if (bb) {            lowvalue += split;            range = range - split;          } else {            range = split;          }           shift = vp8_norm[range];          range <<= shift;          count += shift;           if (count >= 0) {            int offset = shift - count;             if ((lowvalue << (offset - 1)) & 0x80000000) {              int x = w->pos - 1;               while (x >= 0 && w->buffer[x] == 0xff) {                w->buffer[x] = (unsigned char)0;                x--;              }               w->buffer[x] += 1;            }             validate_buffer(w->buffer + w->pos, 1, w->buffer_end, w->error);             w->buffer[w->pos++] = (lowvalue >> (24 - offset)) & 0xff;            lowvalue <<= offset;            shift = count;            lowvalue &= 0xffffff;            count -= 8;          }           lowvalue <<= shift;        } while (n2);      }       {        split = (range + 1) >> 1;         if (e & 1) {          lowvalue += split;          range = range - split;        } else {          range = split;        }         range <<= 1;         if ((lowvalue & 0x80000000)) {          int x = w->pos - 1;           while (x >= 0 && w->buffer[x] == 0xff) {            w->buffer[x] = (unsigned char)0;            x--;          }           w->buffer[x] += 1;        }         lowvalue <<= 1;         if (!++count) {          count = -8;           validate_buffer(w->buffer + w->pos, 1, w->buffer_end, w->error);           w->buffer[w->pos++] = (lowvalue >> 24);          lowvalue &= 0xffffff;        }      }    }     ++p;  }   w->count = count;  w->lowvalue = lowvalue;  w->range = range;} static void write_partition_size(unsigned char *cx_data, int size) {  signed char csize;   csize = size & 0xff;  *cx_data = csize;  csize = (size >> 8) & 0xff;  *(cx_data + 1) = csize;  csize = (size >> 16) & 0xff;  *(cx_data + 2) = csize;} static void pack_tokens_into_partitions(VP8_COMP *cpi, unsigned char *cx_data,                                        unsigned char *cx_data_end,                                        int num_part) {  int i;  unsigned char *ptr = cx_data;  unsigned char *ptr_end = cx_data_end;  vp8_writer *w;   for (i = 0; i < num_part; ++i) {    int mb_row;     w = cpi->bc + i + 1;     vp8_start_encode(w, ptr, ptr_end);     for (mb_row = i; mb_row < cpi->common.mb_rows; mb_row += num_part) {      const TOKENEXTRA *p = cpi->tplist[mb_row].start;      const TOKENEXTRA *stop = cpi->tplist[mb_row].stop;      int tokens = (int)(stop - p);       vp8_pack_tokens(w, p, tokens);    }     vp8_stop_encode(w);    ptr += w->pos;  }} #if CONFIG_MULTITHREADstatic void pack_mb_row_tokens(VP8_COMP *cpi, vp8_writer *w) {  int mb_row;   for (mb_row = 0; mb_row < cpi->common.mb_rows; ++mb_row) {    const TOKENEXTRA *p = cpi->tplist[mb_row].start;    const TOKENEXTRA *stop = cpi->tplist[mb_row].stop;    int tokens = (int)(stop - p);     vp8_pack_tokens(w, p, tokens);  }}#endif  // CONFIG_MULTITHREAD static void write_mv_ref(vp8_writer *w, MB_PREDICTION_MODE m,                         const vp8_prob *p) {  assert(NEARESTMV <= m && m <= SPLITMV);  vp8_write_token(w, vp8_mv_ref_tree, p,                  vp8_mv_ref_encoding_array + (m - NEARESTMV));} static void write_sub_mv_ref(vp8_writer *w, B_PREDICTION_MODE m,                             const vp8_prob *p) {  assert(LEFT4X4 <= m && m <= NEW4X4);  vp8_write_token(w, vp8_sub_mv_ref_tree, p,                  vp8_sub_mv_ref_encoding_array + (m - LEFT4X4));} static void write_mv(vp8_writer *w, const MV *mv, const int_mv *ref,                     const MV_CONTEXT *mvc) {  MV e;  e.row = mv->row - ref->as_mv.row;  e.col = mv->col - ref->as_mv.col;   vp8_encode_motion_vector(w, &e, mvc);} static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi,                              const MACROBLOCKD *x) {  /* Encode the MB segment id. */  if (x->segmentation_enabled && x->update_mb_segmentation_map) {    switch (mi->segment_id) {      case 0:        vp8_write(w, 0, x->mb_segment_tree_probs[0]);        vp8_write(w, 0, x->mb_segment_tree_probs[1]);        break;      case 1:        vp8_write(w, 0, x->mb_segment_tree_probs[0]);        vp8_write(w, 1, x->mb_segment_tree_probs[1]);        break;      case 2:        vp8_write(w, 1, x->mb_segment_tree_probs[0]);        vp8_write(w, 0, x->mb_segment_tree_probs[2]);        break;      case 3:        vp8_write(w, 1, x->mb_segment_tree_probs[0]);        vp8_write(w, 1, x->mb_segment_tree_probs[2]);        break;       /* TRAP.. This should not happen */      default:        vp8_write(w, 0, x->mb_segment_tree_probs[0]);        vp8_write(w, 0, x->mb_segment_tree_probs[1]);        break;    }  }}void vp8_convert_rfct_to_prob(VP8_COMP *const cpi) {  const int *const rfct = cpi->mb.count_mb_ref_frame_usage;  const int rf_intra = rfct[INTRA_FRAME];  const int rf_inter =      rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];   /* Calculate the probabilities used to code the ref frame based on usage */  if (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter))) {    cpi->prob_intra_coded = 1;  }   cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;   if (!cpi->prob_last_coded) cpi->prob_last_coded = 1;   cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])                           ? (rfct[GOLDEN_FRAME] * 255) /                                 (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])                           : 128;   if (!cpi->prob_gf_coded) cpi->prob_gf_coded = 1;} static void pack_inter_mode_mvs(VP8_COMP *const cpi) {  VP8_COMMON *const pc = &cpi->common;  vp8_writer *const w = cpi->bc;  const MV_CONTEXT *mvc = pc->fc.mvc;   MODE_INFO *m = pc->mi;  const int mis = pc->mode_info_stride;  int mb_row = -1;   int prob_skip_false = 0;   cpi->mb.partition_info = cpi->mb.pi;   vp8_convert_rfct_to_prob(cpi);   if (pc->mb_no_coeff_skip) {    int total_mbs = pc->mb_rows * pc->mb_cols;     prob_skip_false = (total_mbs - cpi->mb.skip_true_count) * 256 / total_mbs;     if (prob_skip_false <= 1) prob_skip_false = 1;     if (prob_skip_false > 255) prob_skip_false = 255;     cpi->prob_skip_false = prob_skip_false;    vp8_write_literal(w, prob_skip_false, 8);  }   vp8_write_literal(w, cpi->prob_intra_coded, 8);  vp8_write_literal(w, cpi->prob_last_coded, 8);  vp8_write_literal(w, cpi->prob_gf_coded, 8);   update_mbintra_mode_probs(cpi);   vp8_write_mvprobs(cpi);   while (++mb_row < pc->mb_rows) {    int mb_col = -1;     while (++mb_col < pc->mb_cols) {      const MB_MODE_INFO *const mi = &m->mbmi;      const MV_REFERENCE_FRAME rf = mi->ref_frame;      const MB_PREDICTION_MODE mode = mi->mode;       MACROBLOCKD *xd = &cpi->mb.e_mbd;       /* Distance of Mb to the various image edges.       * These specified to 8th pel as they are always compared to MV       * values that are in 1/8th pel units       */      xd->mb_to_left_edge = -((mb_col * 16) << 3);      xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;      xd->mb_to_top_edge = -((mb_row * 16) << 3);      xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;       if (cpi->mb.e_mbd.update_mb_segmentation_map) {        write_mb_features(w, mi, &cpi->mb.e_mbd);      }       if (pc->mb_no_coeff_skip) {        vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false);      }       if (rf == INTRA_FRAME) {        vp8_write(w, 0, cpi->prob_intra_coded);        write_ymode(w, mode, pc->fc.ymode_prob);         if (mode == B_PRED) {          int j = 0;           do {            write_bmode(w, m->bmi[j].as_mode, pc->fc.bmode_prob);          } while (++j < 16);        }         write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);      } else { /* inter coded */        int_mv best_mv;        vp8_prob mv_ref_p[VP8_MVREFS - 1];         vp8_write(w, 1, cpi->prob_intra_coded);         if (rf == LAST_FRAME)          vp8_write(w, 0, cpi->prob_last_coded);        else {          vp8_write(w, 1, cpi->prob_last_coded);          vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, cpi->prob_gf_coded);        }         {          int_mv n1, n2;          int ct[4];

Lines 1–500 of 1380.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t