add a dec/common.h header to collect common enc/dec #defines

had to rename few structs.

-> we can now include both vp8i.h and vp8enci.h without naming
conflicts.

Change-Id: Ib41b498f1b57aab3d6b796361afc45210ec75174
This commit is contained in:
Pascal Massimino 2015-03-30 01:07:36 -07:00
parent 5d4744a253
commit 82d980209b
15 changed files with 155 additions and 154 deletions

View File

@ -240,6 +240,7 @@ HDRS_INSTALLED = \
HDRS = \ HDRS = \
src/dec/alphai.h \ src/dec/alphai.h \
src/dec/common.h \
src/dec/decode_vp8.h \ src/dec/decode_vp8.h \
src/dec/vp8i.h \ src/dec/vp8i.h \
src/dec/vp8li.h \ src/dec/vp8li.h \

View File

@ -4,6 +4,7 @@ libwebpdecode_la_SOURCES =
libwebpdecode_la_SOURCES += alpha.c libwebpdecode_la_SOURCES += alpha.c
libwebpdecode_la_SOURCES += alphai.h libwebpdecode_la_SOURCES += alphai.h
libwebpdecode_la_SOURCES += buffer.c libwebpdecode_la_SOURCES += buffer.c
libwebpdecode_la_SOURCES += common.h
libwebpdecode_la_SOURCES += decode_vp8.h libwebpdecode_la_SOURCES += decode_vp8.h
libwebpdecode_la_SOURCES += frame.c libwebpdecode_la_SOURCES += frame.c
libwebpdecode_la_SOURCES += idec.c libwebpdecode_la_SOURCES += idec.c

54
src/dec/common.h Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING 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.
// -----------------------------------------------------------------------------
//
// Definitions and macros common to encoding and decoding
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DEC_COMMON_H_
#define WEBP_DEC_COMMON_H_
// intra prediction modes
enum { B_DC_PRED = 0, // 4x4 modes
B_TM_PRED = 1,
B_VE_PRED = 2,
B_HE_PRED = 3,
B_RD_PRED = 4,
B_VR_PRED = 5,
B_LD_PRED = 6,
B_VL_PRED = 7,
B_HD_PRED = 8,
B_HU_PRED = 9,
NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
// Luma16 or UV modes
DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
B_PRED = NUM_BMODES, // refined I4x4 mode
NUM_PRED_MODES = 4,
// special modes
B_DC_PRED_NOTOP = 4,
B_DC_PRED_NOLEFT = 5,
B_DC_PRED_NOTOPLEFT = 6,
NUM_B_DC_MODES = 7 };
enum { MB_FEATURE_TREE_PROBS = 3,
NUM_MB_SEGMENTS = 4,
NUM_REF_LF_DELTAS = 4,
NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
MAX_NUM_PARTITIONS = 8,
// Probabilities
NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC
NUM_BANDS = 8,
NUM_CTX = 3,
NUM_PROBAS = 11
};
#endif // WEBP_DEC_COMMON_H_

View File

@ -15,6 +15,7 @@
#define WEBP_DEC_VP8I_H_ #define WEBP_DEC_VP8I_H_
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
#include "./common.h"
#include "./vp8li.h" #include "./vp8li.h"
#include "../utils/bit_reader.h" #include "../utils/bit_reader.h"
#include "../utils/random.h" #include "../utils/random.h"
@ -33,42 +34,6 @@ extern "C" {
#define DEC_MIN_VERSION 4 #define DEC_MIN_VERSION 4
#define DEC_REV_VERSION 3 #define DEC_REV_VERSION 3
// intra prediction modes
enum { B_DC_PRED = 0, // 4x4 modes
B_TM_PRED,
B_VE_PRED,
B_HE_PRED,
B_RD_PRED,
B_VR_PRED,
B_LD_PRED,
B_VL_PRED,
B_HD_PRED,
B_HU_PRED,
NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
// Luma16 or UV modes
DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
B_PRED = NUM_BMODES, // refined I4x4 mode
// special modes
B_DC_PRED_NOTOP = 4,
B_DC_PRED_NOLEFT = 5,
B_DC_PRED_NOTOPLEFT = 6,
NUM_B_DC_MODES = 7 };
enum { MB_FEATURE_TREE_PROBS = 3,
NUM_MB_SEGMENTS = 4,
NUM_REF_LF_DELTAS = 4,
NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
MAX_NUM_PARTITIONS = 8,
// Probabilities
NUM_TYPES = 4,
NUM_BANDS = 8,
NUM_CTX = 3,
NUM_PROBAS = 11,
NUM_MV_PROBAS = 19 };
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y), // Constraints are: We need to store one 16x16 block of luma samples (y),
// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned, // and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned,
@ -128,7 +93,6 @@ typedef struct {
int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
} VP8SegmentHeader; } VP8SegmentHeader;
// probas associated to one of the contexts // probas associated to one of the contexts
typedef uint8_t VP8ProbaArray[NUM_PROBAS]; typedef uint8_t VP8ProbaArray[NUM_PROBAS];

View File

@ -249,7 +249,7 @@ static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) {
int alpha; int alpha;
InitHistogram(&histo); InitHistogram(&histo);
VP8CollectHistogram(it->yuv_in_ + Y_OFF, VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC,
it->yuv_p_ + VP8I16ModeOffsets[mode], it->yuv_p_ + VP8I16ModeOffsets[mode],
0, 16, &histo); 0, 16, &histo);
alpha = GetAlpha(&histo); alpha = GetAlpha(&histo);
@ -276,7 +276,7 @@ static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
int mode; int mode;
int best_mode_alpha = DEFAULT_ALPHA; int best_mode_alpha = DEFAULT_ALPHA;
VP8Histogram histos[2]; VP8Histogram histos[2];
const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
VP8MakeIntra4Preds(it); VP8MakeIntra4Preds(it);
for (mode = 0; mode < max_mode; ++mode) { for (mode = 0; mode < max_mode; ++mode) {
@ -295,7 +295,7 @@ static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
// accumulate best histogram // accumulate best histogram
MergeHistograms(&histos[cur_histo ^ 1], &total_histo); MergeHistograms(&histos[cur_histo ^ 1], &total_histo);
// Note: we reuse the original samples for predictors // Note: we reuse the original samples for predictors
} while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC));
i4_alpha = GetAlpha(&total_histo); i4_alpha = GetAlpha(&total_histo);
if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) { if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) {
@ -316,7 +316,7 @@ static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
VP8Histogram histo; VP8Histogram histo;
int alpha; int alpha;
InitHistogram(&histo); InitHistogram(&histo);
VP8CollectHistogram(it->yuv_in_ + U_OFF, VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC,
it->yuv_p_ + VP8UVModeOffsets[mode], it->yuv_p_ + VP8UVModeOffsets[mode],
16, 16 + 4 + 4, &histo); 16, 16 + 4 + 4, &histo);
alpha = GetAlpha(&histo); alpha = GetAlpha(&histo);

View File

@ -57,7 +57,7 @@ static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Pre-calc level costs once for all // Pre-calc level costs once for all
void VP8CalculateLevelCosts(VP8Proba* const proba) { void VP8CalculateLevelCosts(VP8EncProba* const proba) {
int ctype, band, ctx; int ctype, band, ctx;
if (!proba->dirty_) return; // nothing to do. if (!proba->dirty_) return; // nothing to do.

View File

@ -49,7 +49,7 @@ static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
// Level cost calculations // Level cost calculations
extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
void VP8CalculateLevelCosts(VP8Proba* const proba); void VP8CalculateLevelCosts(VP8EncProba* const proba);
static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) { static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) {
return VP8LevelFixedCosts[level] return VP8LevelFixedCosts[level]
+ table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level]; + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level];

View File

@ -85,12 +85,12 @@ static void DoFilter(const VP8EncIterator* const it, int level) {
const int ilevel = GetILevel(enc->config_->filter_sharpness, level); const int ilevel = GetILevel(enc->config_->filter_sharpness, level);
const int limit = 2 * level + ilevel; const int limit = 2 * level + ilevel;
uint8_t* const y_dst = it->yuv_out2_ + Y_OFF; uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC;
uint8_t* const u_dst = it->yuv_out2_ + U_OFF; uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC;
uint8_t* const v_dst = it->yuv_out2_ + V_OFF; uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC;
// copy current block to yuv_out2_ // copy current block to yuv_out2_
memcpy(y_dst, it->yuv_out_, YUV_SIZE * sizeof(uint8_t)); memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t));
if (enc->filter_hdr_.simple_ == 1) { // simple if (enc->filter_hdr_.simple_ == 1) { // simple
VP8SimpleHFilter16i(y_dst, BPS, limit); VP8SimpleHFilter16i(y_dst, BPS, limit);
@ -195,13 +195,16 @@ static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
// compute SSIM in a 10 x 10 window // compute SSIM in a 10 x 10 window
for (x = 3; x < 13; x++) { for (x = 3; x < 13; x++) {
for (y = 3; y < 13; y++) { for (y = 3; y < 13; y++) {
VP8SSIMAccumulate(yuv1 + Y_OFF, BPS, yuv2 + Y_OFF, BPS, x, y, 16, 16, &s); VP8SSIMAccumulate(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS,
x, y, 16, 16, &s);
} }
} }
for (x = 1; x < 7; x++) { for (x = 1; x < 7; x++) {
for (y = 1; y < 7; y++) { for (y = 1; y < 7; y++) {
VP8SSIMAccumulate(yuv1 + U_OFF, BPS, yuv2 + U_OFF, BPS, x, y, 8, 8, &s); VP8SSIMAccumulate(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS,
VP8SSIMAccumulate(yuv1 + V_OFF, BPS, yuv2 + V_OFF, BPS, x, y, 8, 8, &s); x, y, 8, 8, &s);
VP8SSIMAccumulate(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS,
x, y, 8, 8, &s);
} }
} }
return VP8SSIMGet(&s); return VP8SSIMGet(&s);

View File

@ -92,7 +92,7 @@ const uint8_t VP8Cat6[] =
// Reset the statistics about: number of skips, token proba, level cost,... // Reset the statistics about: number of skips, token proba, level cost,...
static void ResetStats(VP8Encoder* const enc) { static void ResetStats(VP8Encoder* const enc) {
VP8Proba* const proba = &enc->proba_; VP8EncProba* const proba = &enc->proba_;
VP8CalculateLevelCosts(proba); VP8CalculateLevelCosts(proba);
proba->nb_skip_ = 0; proba->nb_skip_ = 0;
} }
@ -108,7 +108,7 @@ static int CalcSkipProba(uint64_t nb, uint64_t total) {
// Returns the bit-cost for coding the skip probability. // Returns the bit-cost for coding the skip probability.
static int FinalizeSkipProba(VP8Encoder* const enc) { static int FinalizeSkipProba(VP8Encoder* const enc) {
VP8Proba* const proba = &enc->proba_; VP8EncProba* const proba = &enc->proba_;
const int nb_mbs = enc->mb_w_ * enc->mb_h_; const int nb_mbs = enc->mb_w_ * enc->mb_h_;
const int nb_events = proba->nb_skip_; const int nb_events = proba->nb_skip_;
int size; int size;
@ -136,11 +136,11 @@ static int BranchCost(int nb, int total, int proba) {
} }
static void ResetTokenStats(VP8Encoder* const enc) { static void ResetTokenStats(VP8Encoder* const enc) {
VP8Proba* const proba = &enc->proba_; VP8EncProba* const proba = &enc->proba_;
memset(proba->stats_, 0, sizeof(proba->stats_)); memset(proba->stats_, 0, sizeof(proba->stats_));
} }
static int FinalizeTokenProbas(VP8Proba* const proba) { static int FinalizeTokenProbas(VP8EncProba* const proba) {
int has_changed = 0; int has_changed = 0;
int size = 0; int size = 0;
int t, b, c, p; int t, b, c, p;
@ -472,9 +472,9 @@ static void StoreSSE(const VP8EncIterator* const it) {
const uint8_t* const in = it->yuv_in_; const uint8_t* const in = it->yuv_in_;
const uint8_t* const out = it->yuv_out_; const uint8_t* const out = it->yuv_out_;
// Note: not totally accurate at boundary. And doesn't include in-loop filter. // Note: not totally accurate at boundary. And doesn't include in-loop filter.
enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF); enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC);
enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF); enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC);
enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF); enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC);
enc->sse_count_ += 16 * 16; enc->sse_count_ += 16 * 16;
} }
@ -507,9 +507,9 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
} }
} }
#if SEGMENT_VISU // visualize segments and prediction modes #if SEGMENT_VISU // visualize segments and prediction modes
SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16); SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16);
SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8); SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8);
SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8); SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8);
#endif #endif
} }
@ -739,7 +739,7 @@ int VP8EncTokenLoop(VP8Encoder* const enc) {
int num_pass_left = enc->config_->pass; int num_pass_left = enc->config_->pass;
const int do_search = enc->do_search_; const int do_search = enc->do_search_;
VP8EncIterator it; VP8EncIterator it;
VP8Proba* const proba = &enc->proba_; VP8EncProba* const proba = &enc->proba_;
const VP8RDLevel rd_opt = enc->rd_opt_level_; const VP8RDLevel rd_opt = enc->rd_opt_level_;
const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384;
PassStats stats; PassStats stats;

View File

@ -71,9 +71,9 @@ void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
it->y_stride_ = enc->pic_->y_stride; it->y_stride_ = enc->pic_->y_stride;
it->uv_stride_ = enc->pic_->uv_stride; it->uv_stride_ = enc->pic_->uv_stride;
it->yuv_in_ = (uint8_t*)DO_ALIGN(it->yuv_mem_); it->yuv_in_ = (uint8_t*)DO_ALIGN(it->yuv_mem_);
it->yuv_out_ = it->yuv_in_ + YUV_SIZE; it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC;
it->yuv_out2_ = it->yuv_out_ + YUV_SIZE; it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC;
it->yuv_p_ = it->yuv_out2_ + YUV_SIZE; it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC;
it->lf_stats_ = enc->lf_stats_; it->lf_stats_ = enc->lf_stats_;
it->percent0_ = enc->percent_; it->percent0_ = enc->percent_;
it->y_left_ = (uint8_t*)DO_ALIGN(it->yuv_left_mem_ + 1); it->y_left_ = (uint8_t*)DO_ALIGN(it->yuv_left_mem_ + 1);
@ -136,9 +136,9 @@ void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
const int uv_w = (w + 1) >> 1; const int uv_w = (w + 1) >> 1;
const int uv_h = (h + 1) >> 1; const int uv_h = (h + 1) >> 1;
ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF, w, h, 16); ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16);
ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF, uv_w, uv_h, 8); ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8);
ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF, uv_w, uv_h, 8); ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8);
if (tmp_32 == NULL) return; if (tmp_32 == NULL) return;
@ -185,9 +185,9 @@ void VP8IteratorExport(const VP8EncIterator* const it) {
const VP8Encoder* const enc = it->enc_; const VP8Encoder* const enc = it->enc_;
if (enc->config_->show_compressed) { if (enc->config_->show_compressed) {
const int x = it->x_, y = it->y_; const int x = it->x_, y = it->y_;
const uint8_t* const ysrc = it->yuv_out_ + Y_OFF; const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
const uint8_t* const usrc = it->yuv_out_ + U_OFF; const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC;
const uint8_t* const vsrc = it->yuv_out_ + V_OFF; const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC;
const WebPPicture* const pic = enc->pic_; const WebPPicture* const pic = enc->pic_;
uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16; uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8; uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8;
@ -286,8 +286,8 @@ void VP8IteratorBytesToNz(VP8EncIterator* const it) {
void VP8IteratorSaveBoundary(VP8EncIterator* const it) { void VP8IteratorSaveBoundary(VP8EncIterator* const it) {
VP8Encoder* const enc = it->enc_; VP8Encoder* const enc = it->enc_;
const int x = it->x_, y = it->y_; const int x = it->x_, y = it->y_;
const uint8_t* const ysrc = it->yuv_out_ + Y_OFF; const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
const uint8_t* const uvsrc = it->yuv_out_ + U_OFF; const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC;
if (x < enc->mb_w_ - 1) { // left if (x < enc->mb_w_ - 1) { // left
int i; int i;
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {

View File

@ -717,7 +717,7 @@ static int ReconstructIntra16(VP8EncIterator* const it,
int mode) { int mode) {
const VP8Encoder* const enc = it->enc_; const VP8Encoder* const enc = it->enc_;
const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
const uint8_t* const src = it->yuv_in_ + Y_OFF; const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
int nz = 0; int nz = 0;
int n; int n;
@ -791,7 +791,7 @@ static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
uint8_t* const yuv_out, int mode) { uint8_t* const yuv_out, int mode) {
const VP8Encoder* const enc = it->enc_; const VP8Encoder* const enc = it->enc_;
const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
const uint8_t* const src = it->yuv_in_ + U_OFF; const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
int nz = 0; int nz = 0;
int n; int n;
@ -875,7 +875,7 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
const int lambda = dqm->lambda_i16_; const int lambda = dqm->lambda_i16_;
const int tlambda = dqm->tlambda_; const int tlambda = dqm->tlambda_;
const uint8_t* const src = it->yuv_in_ + Y_OFF; const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
VP8ModeScore rd_tmp; VP8ModeScore rd_tmp;
VP8ModeScore* rd_cur = &rd_tmp; VP8ModeScore* rd_cur = &rd_tmp;
VP8ModeScore* rd_best = rd; VP8ModeScore* rd_best = rd;
@ -883,7 +883,7 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
rd->mode_i16 = -1; rd->mode_i16 = -1;
for (mode = 0; mode < NUM_PRED_MODES; ++mode) { for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer
rd_cur->mode_i16 = mode; rd_cur->mode_i16 = mode;
// Reconstruct // Reconstruct
@ -939,8 +939,8 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
const int lambda = dqm->lambda_i4_; const int lambda = dqm->lambda_i4_;
const int tlambda = dqm->tlambda_; const int tlambda = dqm->tlambda_;
const uint8_t* const src0 = it->yuv_in_ + Y_OFF; const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC;
uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF; uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
int total_header_bits = 0; int total_header_bits = 0;
VP8ModeScore rd_best; VP8ModeScore rd_best;
@ -1033,9 +1033,9 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
const int kNumBlocks = 8; const int kNumBlocks = 8;
const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
const int lambda = dqm->lambda_uv_; const int lambda = dqm->lambda_uv_;
const uint8_t* const src = it->yuv_in_ + U_OFF; const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
uint8_t* tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer
uint8_t* dst0 = it->yuv_out_ + U_OFF; uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC;
uint8_t* dst = dst0; uint8_t* dst = dst0;
VP8ModeScore rd_best; VP8ModeScore rd_best;
int mode; int mode;
@ -1081,21 +1081,21 @@ static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
int nz = 0; int nz = 0;
if (is_i16) { if (is_i16) {
nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF, it->preds_[0]); nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
} else { } else {
VP8IteratorStartI4(it); VP8IteratorStartI4(it);
do { do {
const int mode = const int mode =
it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_];
const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
uint8_t* const dst = it->yuv_out_ + Y_OFF + VP8Scan[it->i4_]; uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_];
VP8MakeIntra4Preds(it); VP8MakeIntra4Preds(it);
nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
src, dst, mode) << it->i4_; src, dst, mode) << it->i4_;
} while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF)); } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC));
} }
nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF, it->mb_->uv_mode_); nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
rd->nz = nz; rd->nz = nz;
} }
@ -1109,7 +1109,7 @@ static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) {
int best_mode = -1; int best_mode = -1;
for (mode = 0; mode < NUM_PRED_MODES; ++mode) { for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
const uint8_t* const src = it->yuv_in_ + Y_OFF; const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
const score_t score = VP8SSE16x16(src, ref); const score_t score = VP8SSE16x16(src, ref);
if (score < best_score) { if (score < best_score) {
best_mode = mode; best_mode = mode;
@ -1129,7 +1129,7 @@ static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) {
int mode; int mode;
int best_sub_mode = -1; int best_sub_mode = -1;
score_t best_sub_score = MAX_COST; score_t best_sub_score = MAX_COST;
const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
// TODO(skal): we don't really need the prediction pixels here, // TODO(skal): we don't really need the prediction pixels here,
// but just the distortion against 'src'. // but just the distortion against 'src'.
@ -1145,7 +1145,7 @@ static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) {
modes_i4[it->i4_] = best_sub_mode; modes_i4[it->i4_] = best_sub_mode;
score_i4 += best_sub_score; score_i4 += best_sub_score;
if (score_i4 >= best_score) break; if (score_i4 >= best_score) break;
} while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC));
if (score_i4 < best_score) { if (score_i4 < best_score) {
VP8SetIntra4Mode(it, modes_i4); VP8SetIntra4Mode(it, modes_i4);
} }

View File

@ -186,8 +186,8 @@ static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0,
// Segmentation header // Segmentation header
static void PutSegmentHeader(VP8BitWriter* const bw, static void PutSegmentHeader(VP8BitWriter* const bw,
const VP8Encoder* const enc) { const VP8Encoder* const enc) {
const VP8SegmentHeader* const hdr = &enc->segment_hdr_; const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
const VP8Proba* const proba = &enc->proba_; const VP8EncProba* const proba = &enc->proba_;
if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) {
// We always 'update' the quant and filter strength values // We always 'update' the quant and filter strength values
const int update_data = 1; const int update_data = 1;
@ -215,7 +215,7 @@ static void PutSegmentHeader(VP8BitWriter* const bw,
// Filtering parameters header // Filtering parameters header
static void PutFilterHeader(VP8BitWriter* const bw, static void PutFilterHeader(VP8BitWriter* const bw,
const VP8FilterHeader* const hdr) { const VP8EncFilterHeader* const hdr) {
const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
VP8PutBitUniform(bw, hdr->simple_); VP8PutBitUniform(bw, hdr->simple_);
VP8PutBits(bw, hdr->level_, 6); VP8PutBits(bw, hdr->level_, 6);

View File

@ -154,7 +154,7 @@ const uint8_t
}; };
void VP8DefaultProbas(VP8Encoder* const enc) { void VP8DefaultProbas(VP8Encoder* const enc) {
VP8Proba* const probas = &enc->proba_; VP8EncProba* const probas = &enc->proba_;
probas->use_skip_proba_ = 0; probas->use_skip_proba_ = 0;
memset(probas->segments_, 255u, sizeof(probas->segments_)); memset(probas->segments_, 255u, sizeof(probas->segments_));
memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0)); memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0));
@ -482,7 +482,7 @@ const uint8_t
} }
}; };
void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas) { void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) {
int t, b, c, p; int t, b, c, p;
for (t = 0; t < NUM_TYPES; ++t) { for (t = 0; t < NUM_TYPES; ++t) {
for (b = 0; b < NUM_BANDS; ++b) { for (b = 0; b < NUM_BANDS; ++b) {

View File

@ -15,10 +15,11 @@
#define WEBP_ENC_VP8ENCI_H_ #define WEBP_ENC_VP8ENCI_H_
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
#include "../webp/encode.h" #include "../dec/common.h"
#include "../dsp/dsp.h" #include "../dsp/dsp.h"
#include "../utils/bit_writer.h" #include "../utils/bit_writer.h"
#include "../utils/thread.h" #include "../utils/thread.h"
#include "../webp/encode.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -32,32 +33,7 @@ extern "C" {
#define ENC_MIN_VERSION 4 #define ENC_MIN_VERSION 4
#define ENC_REV_VERSION 3 #define ENC_REV_VERSION 3
// intra prediction modes enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
enum { B_DC_PRED = 0, // 4x4 modes
B_TM_PRED = 1,
B_VE_PRED = 2,
B_HE_PRED = 3,
B_RD_PRED = 4,
B_VR_PRED = 5,
B_LD_PRED = 6,
B_VL_PRED = 7,
B_HD_PRED = 8,
B_HU_PRED = 9,
NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
// Luma16 or UV modes
DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
NUM_PRED_MODES = 4
};
enum { NUM_MB_SEGMENTS = 4,
MAX_NUM_PARTITIONS = 8,
NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC
NUM_BANDS = 8,
NUM_CTX = 3,
NUM_PROBAS = 11,
MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67)
}; };
@ -74,14 +50,14 @@ typedef enum { // Rate-distortion optimization levels
// The predicted blocks can be accessed using offsets to yuv_p_ and // The predicted blocks can be accessed using offsets to yuv_p_ and
// the arrays VP8*ModeOffsets[]. // the arrays VP8*ModeOffsets[].
// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) // * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_)
// (see VP8Scan[] for accessing the blocks, along with Y_OFF/U_OFF/V_OFF): // (see VP8Scan[] for accessing the blocks, along with Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC):
// +----+----+ // +----+----+
// Y_OFF |YYYY|UUVV| // Y_OFF_ENC |YYYY|UUVV|
// U_OFF |YYYY|UUVV| // U_OFF_ENC |YYYY|UUVV|
// V_OFF |YYYY|....| <- 25% wasted U/V area // V_OFF_ENC |YYYY|....| <- 25% wasted U/V area
// |YYYY|....| // |YYYY|....|
// +----+----+ // +----+----+
// * Prediction area ('yuv_p_', size = PRED_SIZE) // * Prediction area ('yuv_p_', size = PRED_SIZE_ENC)
// Intra16 predictions (16x16 block each, two per row): // Intra16 predictions (16x16 block each, two per row):
// |I16DC16|I16TM16| // |I16DC16|I16TM16|
// |I16VE16|I16HE16| // |I16VE16|I16HE16|
@ -91,11 +67,12 @@ typedef enum { // Rate-distortion optimization levels
// Intra 4x4 predictions (4x4 block each) // Intra 4x4 predictions (4x4 block each)
// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| // |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4|
// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted // |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted
#define YUV_SIZE (BPS * 16) #define YUV_SIZE_ENC (BPS * 16)
#define PRED_SIZE (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds #define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds
#define Y_OFF (0) #define Y_OFF_ENC (0)
#define U_OFF (16) #define U_OFF_ENC (16)
#define V_OFF (16 + 8) #define V_OFF_ENC (16 + 8)
#define ALIGN_CST 15 #define ALIGN_CST 15
#define DO_ALIGN(PTR) ((uintptr_t)((PTR) + ALIGN_CST) & ~ALIGN_CST) #define DO_ALIGN(PTR) ((uintptr_t)((PTR) + ALIGN_CST) & ~ALIGN_CST)
@ -163,7 +140,7 @@ typedef struct {
int update_map_; // whether to update the segment map or not. int update_map_; // whether to update the segment map or not.
// must be 0 if there's only 1 segment. // must be 0 if there's only 1 segment.
int size_; // bit-cost for transmitting the segment map int size_; // bit-cost for transmitting the segment map
} VP8SegmentHeader; } VP8EncSegmentHeader;
// Struct collecting all frame-persistent probabilities. // Struct collecting all frame-persistent probabilities.
typedef struct { typedef struct {
@ -176,7 +153,7 @@ typedef struct {
int dirty_; // if true, need to call VP8CalculateLevelCosts() int dirty_; // if true, need to call VP8CalculateLevelCosts()
int use_skip_proba_; // Note: we always use skip_proba for now. int use_skip_proba_; // Note: we always use skip_proba for now.
int nb_skip_; // number of skipped blocks int nb_skip_; // number of skipped blocks
} VP8Proba; } VP8EncProba;
// Filter parameters. Not actually used in the code (we don't perform // Filter parameters. Not actually used in the code (we don't perform
// the in-loop filtering), but filled from user's config // the in-loop filtering), but filled from user's config
@ -185,7 +162,7 @@ typedef struct {
int level_; // base filter level [0..63] int level_; // base filter level [0..63]
int sharpness_; // [0..7] int sharpness_; // [0..7]
int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16
} VP8FilterHeader; } VP8EncFilterHeader;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Informations about the macroblocks. // Informations about the macroblocks.
@ -271,9 +248,10 @@ typedef struct {
uint8_t* y_top_; // top luma samples at position 'x_' uint8_t* y_top_; // top luma samples at position 'x_'
uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes
// memory for storing y/u/v_left_ and yuv_in_/out_* // memory for storing y/u/v_left_
uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + ALIGN_CST]; // memory for *_left_ uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + ALIGN_CST];
uint8_t yuv_mem_[3 * YUV_SIZE + PRED_SIZE + ALIGN_CST]; // memory for yuv_* // memory for yuv_*
uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + ALIGN_CST];
} VP8EncIterator; } VP8EncIterator;
// in iterator.c // in iterator.c
@ -366,8 +344,8 @@ struct VP8Encoder {
WebPPicture* pic_; // input / output picture WebPPicture* pic_; // input / output picture
// headers // headers
VP8FilterHeader filter_hdr_; // filtering information VP8EncFilterHeader filter_hdr_; // filtering information
VP8SegmentHeader segment_hdr_; // segment information VP8EncSegmentHeader segment_hdr_; // segment information
int profile_; // VP8's profile, deduced from Config. int profile_; // VP8's profile, deduced from Config.
@ -403,12 +381,12 @@ struct VP8Encoder {
int dq_uv_dc_, dq_uv_ac_; int dq_uv_dc_, dq_uv_ac_;
// probabilities and statistics // probabilities and statistics
VP8Proba proba_; VP8EncProba proba_;
uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks
uint64_t sse_count_; // pixel count for the sse_[] stats uint64_t sse_count_; // pixel count for the sse_[] stats
int coded_size_; int coded_size_;
int residual_bytes_[3][4]; int residual_bytes_[3][4];
int block_count_[3]; int block_count_[3];
// quality/speed settings // quality/speed settings
int method_; // 0=fastest, 6=best/slowest. int method_; // 0=fastest, 6=best/slowest.
@ -438,7 +416,7 @@ extern const uint8_t
// Reset the token probabilities to their initial (default) values // Reset the token probabilities to their initial (default) values
void VP8DefaultProbas(VP8Encoder* const enc); void VP8DefaultProbas(VP8Encoder* const enc);
// Write the token probabilities // Write the token probabilities
void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas); void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas);
// Writes the partition #0 modes (that is: all intra modes) // Writes the partition #0 modes (that is: all intra modes)
void VP8CodeIntraModes(VP8Encoder* const enc); void VP8CodeIntraModes(VP8Encoder* const enc);

View File

@ -38,14 +38,14 @@ int WebPGetEncoderVersion(void) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void ResetSegmentHeader(VP8Encoder* const enc) { static void ResetSegmentHeader(VP8Encoder* const enc) {
VP8SegmentHeader* const hdr = &enc->segment_hdr_; VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
hdr->num_segments_ = enc->config_->segments; hdr->num_segments_ = enc->config_->segments;
hdr->update_map_ = (hdr->num_segments_ > 1); hdr->update_map_ = (hdr->num_segments_ > 1);
hdr->size_ = 0; hdr->size_ = 0;
} }
static void ResetFilterHeader(VP8Encoder* const enc) { static void ResetFilterHeader(VP8Encoder* const enc) {
VP8FilterHeader* const hdr = &enc->filter_hdr_; VP8EncFilterHeader* const hdr = &enc->filter_hdr_;
hdr->simple_ = 1; hdr->simple_ = 1;
hdr->level_ = 0; hdr->level_ = 0;
hdr->sharpness_ = 0; hdr->sharpness_ = 0;
@ -131,7 +131,7 @@ static void MapConfigToTools(VP8Encoder* const enc) {
// VP8EncIterator: 3360 // VP8EncIterator: 3360
// VP8ModeScore: 872 // VP8ModeScore: 872
// VP8SegmentInfo: 732 // VP8SegmentInfo: 732
// VP8Proba: 18352 // VP8EncProba: 18352
// LFStats: 2048 // LFStats: 2048
// Picture size (yuv): 419328 // Picture size (yuv): 419328
@ -177,10 +177,10 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
" VP8EncIterator: %ld\n" " VP8EncIterator: %ld\n"
" VP8ModeScore: %ld\n" " VP8ModeScore: %ld\n"
" VP8SegmentInfo: %ld\n" " VP8SegmentInfo: %ld\n"
" VP8Proba: %ld\n" " VP8EncProba: %ld\n"
" LFStats: %ld\n", " LFStats: %ld\n",
sizeof(VP8EncIterator), sizeof(VP8ModeScore), sizeof(VP8EncIterator), sizeof(VP8ModeScore),
sizeof(VP8SegmentInfo), sizeof(VP8Proba), sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
sizeof(LFStats)); sizeof(LFStats));
printf("Picture size (yuv): %ld\n", printf("Picture size (yuv): %ld\n",
mb_w * mb_h * 384 * sizeof(uint8_t)); mb_w * mb_h * 384 * sizeof(uint8_t));