mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
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:
parent
5d4744a253
commit
82d980209b
@ -240,6 +240,7 @@ HDRS_INSTALLED = \
|
||||
|
||||
HDRS = \
|
||||
src/dec/alphai.h \
|
||||
src/dec/common.h \
|
||||
src/dec/decode_vp8.h \
|
||||
src/dec/vp8i.h \
|
||||
src/dec/vp8li.h \
|
||||
|
@ -4,6 +4,7 @@ libwebpdecode_la_SOURCES =
|
||||
libwebpdecode_la_SOURCES += alpha.c
|
||||
libwebpdecode_la_SOURCES += alphai.h
|
||||
libwebpdecode_la_SOURCES += buffer.c
|
||||
libwebpdecode_la_SOURCES += common.h
|
||||
libwebpdecode_la_SOURCES += decode_vp8.h
|
||||
libwebpdecode_la_SOURCES += frame.c
|
||||
libwebpdecode_la_SOURCES += idec.c
|
||||
|
54
src/dec/common.h
Normal file
54
src/dec/common.h
Normal 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_
|
@ -15,6 +15,7 @@
|
||||
#define WEBP_DEC_VP8I_H_
|
||||
|
||||
#include <string.h> // for memcpy()
|
||||
#include "./common.h"
|
||||
#include "./vp8li.h"
|
||||
#include "../utils/bit_reader.h"
|
||||
#include "../utils/random.h"
|
||||
@ -33,42 +34,6 @@ extern "C" {
|
||||
#define DEC_MIN_VERSION 4
|
||||
#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).
|
||||
// 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,
|
||||
@ -128,7 +93,6 @@ typedef struct {
|
||||
int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
|
||||
} VP8SegmentHeader;
|
||||
|
||||
|
||||
// probas associated to one of the contexts
|
||||
typedef uint8_t VP8ProbaArray[NUM_PROBAS];
|
||||
|
||||
|
@ -249,7 +249,7 @@ static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) {
|
||||
int alpha;
|
||||
|
||||
InitHistogram(&histo);
|
||||
VP8CollectHistogram(it->yuv_in_ + Y_OFF,
|
||||
VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC,
|
||||
it->yuv_p_ + VP8I16ModeOffsets[mode],
|
||||
0, 16, &histo);
|
||||
alpha = GetAlpha(&histo);
|
||||
@ -276,7 +276,7 @@ static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
|
||||
int mode;
|
||||
int best_mode_alpha = DEFAULT_ALPHA;
|
||||
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);
|
||||
for (mode = 0; mode < max_mode; ++mode) {
|
||||
@ -295,7 +295,7 @@ static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
|
||||
// accumulate best histogram
|
||||
MergeHistograms(&histos[cur_histo ^ 1], &total_histo);
|
||||
// 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);
|
||||
if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) {
|
||||
@ -316,7 +316,7 @@ static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
|
||||
VP8Histogram histo;
|
||||
int alpha;
|
||||
InitHistogram(&histo);
|
||||
VP8CollectHistogram(it->yuv_in_ + U_OFF,
|
||||
VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC,
|
||||
it->yuv_p_ + VP8UVModeOffsets[mode],
|
||||
16, 16 + 4 + 4, &histo);
|
||||
alpha = GetAlpha(&histo);
|
||||
|
@ -57,7 +57,7 @@ static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
|
||||
//------------------------------------------------------------------------------
|
||||
// Pre-calc level costs once for all
|
||||
|
||||
void VP8CalculateLevelCosts(VP8Proba* const proba) {
|
||||
void VP8CalculateLevelCosts(VP8EncProba* const proba) {
|
||||
int ctype, band, ctx;
|
||||
|
||||
if (!proba->dirty_) return; // nothing to do.
|
||||
|
@ -49,7 +49,7 @@ static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
|
||||
|
||||
// Level cost calculations
|
||||
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) {
|
||||
return VP8LevelFixedCosts[level]
|
||||
+ table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level];
|
||||
|
@ -85,12 +85,12 @@ static void DoFilter(const VP8EncIterator* const it, int level) {
|
||||
const int ilevel = GetILevel(enc->config_->filter_sharpness, level);
|
||||
const int limit = 2 * level + ilevel;
|
||||
|
||||
uint8_t* const y_dst = it->yuv_out2_ + Y_OFF;
|
||||
uint8_t* const u_dst = it->yuv_out2_ + U_OFF;
|
||||
uint8_t* const v_dst = it->yuv_out2_ + V_OFF;
|
||||
uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC;
|
||||
uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC;
|
||||
uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC;
|
||||
|
||||
// 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
|
||||
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
|
||||
for (x = 3; x < 13; x++) {
|
||||
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 (y = 1; y < 7; y++) {
|
||||
VP8SSIMAccumulate(yuv1 + U_OFF, BPS, yuv2 + U_OFF, BPS, x, y, 8, 8, &s);
|
||||
VP8SSIMAccumulate(yuv1 + V_OFF, BPS, yuv2 + V_OFF, BPS, x, y, 8, 8, &s);
|
||||
VP8SSIMAccumulate(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS,
|
||||
x, y, 8, 8, &s);
|
||||
VP8SSIMAccumulate(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS,
|
||||
x, y, 8, 8, &s);
|
||||
}
|
||||
}
|
||||
return VP8SSIMGet(&s);
|
||||
|
@ -92,7 +92,7 @@ const uint8_t VP8Cat6[] =
|
||||
// Reset the statistics about: number of skips, token proba, level cost,...
|
||||
|
||||
static void ResetStats(VP8Encoder* const enc) {
|
||||
VP8Proba* const proba = &enc->proba_;
|
||||
VP8EncProba* const proba = &enc->proba_;
|
||||
VP8CalculateLevelCosts(proba);
|
||||
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.
|
||||
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_events = proba->nb_skip_;
|
||||
int size;
|
||||
@ -136,11 +136,11 @@ static int BranchCost(int nb, int total, int proba) {
|
||||
}
|
||||
|
||||
static void ResetTokenStats(VP8Encoder* const enc) {
|
||||
VP8Proba* const proba = &enc->proba_;
|
||||
VP8EncProba* const proba = &enc->proba_;
|
||||
memset(proba->stats_, 0, sizeof(proba->stats_));
|
||||
}
|
||||
|
||||
static int FinalizeTokenProbas(VP8Proba* const proba) {
|
||||
static int FinalizeTokenProbas(VP8EncProba* const proba) {
|
||||
int has_changed = 0;
|
||||
int size = 0;
|
||||
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 out = it->yuv_out_;
|
||||
// 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_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
|
||||
enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
|
||||
enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC);
|
||||
enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC);
|
||||
enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC);
|
||||
enc->sse_count_ += 16 * 16;
|
||||
}
|
||||
|
||||
@ -507,9 +507,9 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
|
||||
}
|
||||
}
|
||||
#if SEGMENT_VISU // visualize segments and prediction modes
|
||||
SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
|
||||
SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8);
|
||||
SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8);
|
||||
SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16);
|
||||
SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8);
|
||||
SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -739,7 +739,7 @@ int VP8EncTokenLoop(VP8Encoder* const enc) {
|
||||
int num_pass_left = enc->config_->pass;
|
||||
const int do_search = enc->do_search_;
|
||||
VP8EncIterator it;
|
||||
VP8Proba* const proba = &enc->proba_;
|
||||
VP8EncProba* const proba = &enc->proba_;
|
||||
const VP8RDLevel rd_opt = enc->rd_opt_level_;
|
||||
const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384;
|
||||
PassStats stats;
|
||||
|
@ -71,9 +71,9 @@ void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
|
||||
it->y_stride_ = enc->pic_->y_stride;
|
||||
it->uv_stride_ = enc->pic_->uv_stride;
|
||||
it->yuv_in_ = (uint8_t*)DO_ALIGN(it->yuv_mem_);
|
||||
it->yuv_out_ = it->yuv_in_ + YUV_SIZE;
|
||||
it->yuv_out2_ = it->yuv_out_ + YUV_SIZE;
|
||||
it->yuv_p_ = it->yuv_out2_ + YUV_SIZE;
|
||||
it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC;
|
||||
it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC;
|
||||
it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC;
|
||||
it->lf_stats_ = enc->lf_stats_;
|
||||
it->percent0_ = enc->percent_;
|
||||
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_h = (h + 1) >> 1;
|
||||
|
||||
ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF, w, h, 16);
|
||||
ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF, uv_w, uv_h, 8);
|
||||
ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF, uv_w, uv_h, 8);
|
||||
ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16);
|
||||
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_ENC, uv_w, uv_h, 8);
|
||||
|
||||
if (tmp_32 == NULL) return;
|
||||
|
||||
@ -185,9 +185,9 @@ void VP8IteratorExport(const VP8EncIterator* const it) {
|
||||
const VP8Encoder* const enc = it->enc_;
|
||||
if (enc->config_->show_compressed) {
|
||||
const int x = it->x_, y = it->y_;
|
||||
const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
|
||||
const uint8_t* const usrc = it->yuv_out_ + U_OFF;
|
||||
const uint8_t* const vsrc = it->yuv_out_ + V_OFF;
|
||||
const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
|
||||
const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC;
|
||||
const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC;
|
||||
const WebPPicture* const pic = enc->pic_;
|
||||
uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
|
||||
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) {
|
||||
VP8Encoder* const enc = it->enc_;
|
||||
const int x = it->x_, y = it->y_;
|
||||
const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
|
||||
const uint8_t* const uvsrc = it->yuv_out_ + U_OFF;
|
||||
const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
|
||||
const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC;
|
||||
if (x < enc->mb_w_ - 1) { // left
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
|
@ -717,7 +717,7 @@ static int ReconstructIntra16(VP8EncIterator* const it,
|
||||
int mode) {
|
||||
const VP8Encoder* const enc = it->enc_;
|
||||
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_];
|
||||
int nz = 0;
|
||||
int n;
|
||||
@ -791,7 +791,7 @@ static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
|
||||
uint8_t* const yuv_out, int mode) {
|
||||
const VP8Encoder* const enc = it->enc_;
|
||||
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_];
|
||||
int nz = 0;
|
||||
int n;
|
||||
@ -875,7 +875,7 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
|
||||
VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
|
||||
const int lambda = dqm->lambda_i16_;
|
||||
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_cur = &rd_tmp;
|
||||
VP8ModeScore* rd_best = rd;
|
||||
@ -883,7 +883,7 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
|
||||
|
||||
rd->mode_i16 = -1;
|
||||
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;
|
||||
|
||||
// Reconstruct
|
||||
@ -939,8 +939,8 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
|
||||
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
|
||||
const int lambda = dqm->lambda_i4_;
|
||||
const int tlambda = dqm->tlambda_;
|
||||
const uint8_t* const src0 = it->yuv_in_ + Y_OFF;
|
||||
uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF;
|
||||
const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC;
|
||||
uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
|
||||
int total_header_bits = 0;
|
||||
VP8ModeScore rd_best;
|
||||
|
||||
@ -1033,9 +1033,9 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
|
||||
const int kNumBlocks = 8;
|
||||
const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
|
||||
const int lambda = dqm->lambda_uv_;
|
||||
const uint8_t* const src = it->yuv_in_ + U_OFF;
|
||||
uint8_t* tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer
|
||||
uint8_t* dst0 = it->yuv_out_ + U_OFF;
|
||||
const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
|
||||
uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer
|
||||
uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC;
|
||||
uint8_t* dst = dst0;
|
||||
VP8ModeScore rd_best;
|
||||
int mode;
|
||||
@ -1081,21 +1081,21 @@ static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
|
||||
int nz = 0;
|
||||
|
||||
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 {
|
||||
VP8IteratorStartI4(it);
|
||||
do {
|
||||
const int mode =
|
||||
it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_];
|
||||
const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_];
|
||||
uint8_t* const dst = it->yuv_out_ + 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_ENC + VP8Scan[it->i4_];
|
||||
VP8MakeIntra4Preds(it);
|
||||
nz |= ReconstructIntra4(it, rd->y_ac_levels[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;
|
||||
}
|
||||
|
||||
@ -1109,7 +1109,7 @@ static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) {
|
||||
int best_mode = -1;
|
||||
for (mode = 0; mode < NUM_PRED_MODES; ++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);
|
||||
if (score < best_score) {
|
||||
best_mode = mode;
|
||||
@ -1129,7 +1129,7 @@ static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) {
|
||||
int mode;
|
||||
int best_sub_mode = -1;
|
||||
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,
|
||||
// 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;
|
||||
score_i4 += best_sub_score;
|
||||
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) {
|
||||
VP8SetIntra4Mode(it, modes_i4);
|
||||
}
|
||||
|
@ -186,8 +186,8 @@ static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0,
|
||||
// Segmentation header
|
||||
static void PutSegmentHeader(VP8BitWriter* const bw,
|
||||
const VP8Encoder* const enc) {
|
||||
const VP8SegmentHeader* const hdr = &enc->segment_hdr_;
|
||||
const VP8Proba* const proba = &enc->proba_;
|
||||
const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
|
||||
const VP8EncProba* const proba = &enc->proba_;
|
||||
if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) {
|
||||
// We always 'update' the quant and filter strength values
|
||||
const int update_data = 1;
|
||||
@ -215,7 +215,7 @@ static void PutSegmentHeader(VP8BitWriter* const bw,
|
||||
|
||||
// Filtering parameters header
|
||||
static void PutFilterHeader(VP8BitWriter* const bw,
|
||||
const VP8FilterHeader* const hdr) {
|
||||
const VP8EncFilterHeader* const hdr) {
|
||||
const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
|
||||
VP8PutBitUniform(bw, hdr->simple_);
|
||||
VP8PutBits(bw, hdr->level_, 6);
|
||||
|
@ -154,7 +154,7 @@ const uint8_t
|
||||
};
|
||||
|
||||
void VP8DefaultProbas(VP8Encoder* const enc) {
|
||||
VP8Proba* const probas = &enc->proba_;
|
||||
VP8EncProba* const probas = &enc->proba_;
|
||||
probas->use_skip_proba_ = 0;
|
||||
memset(probas->segments_, 255u, sizeof(probas->segments_));
|
||||
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;
|
||||
for (t = 0; t < NUM_TYPES; ++t) {
|
||||
for (b = 0; b < NUM_BANDS; ++b) {
|
||||
|
@ -15,10 +15,11 @@
|
||||
#define WEBP_ENC_VP8ENCI_H_
|
||||
|
||||
#include <string.h> // for memcpy()
|
||||
#include "../webp/encode.h"
|
||||
#include "../dec/common.h"
|
||||
#include "../dsp/dsp.h"
|
||||
#include "../utils/bit_writer.h"
|
||||
#include "../utils/thread.h"
|
||||
#include "../webp/encode.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -32,32 +33,7 @@ extern "C" {
|
||||
#define ENC_MIN_VERSION 4
|
||||
#define ENC_REV_VERSION 3
|
||||
|
||||
// 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,
|
||||
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
|
||||
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
|
||||
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
|
||||
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 arrays VP8*ModeOffsets[].
|
||||
// * 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|
|
||||
// U_OFF |YYYY|UUVV|
|
||||
// V_OFF |YYYY|....| <- 25% wasted U/V area
|
||||
// Y_OFF_ENC |YYYY|UUVV|
|
||||
// U_OFF_ENC |YYYY|UUVV|
|
||||
// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area
|
||||
// |YYYY|....|
|
||||
// +----+----+
|
||||
// * Prediction area ('yuv_p_', size = PRED_SIZE)
|
||||
// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC)
|
||||
// Intra16 predictions (16x16 block each, two per row):
|
||||
// |I16DC16|I16TM16|
|
||||
// |I16VE16|I16HE16|
|
||||
@ -91,11 +67,12 @@ typedef enum { // Rate-distortion optimization levels
|
||||
// Intra 4x4 predictions (4x4 block each)
|
||||
// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4|
|
||||
// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted
|
||||
#define YUV_SIZE (BPS * 16)
|
||||
#define PRED_SIZE (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds
|
||||
#define Y_OFF (0)
|
||||
#define U_OFF (16)
|
||||
#define V_OFF (16 + 8)
|
||||
#define YUV_SIZE_ENC (BPS * 16)
|
||||
#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds
|
||||
#define Y_OFF_ENC (0)
|
||||
#define U_OFF_ENC (16)
|
||||
#define V_OFF_ENC (16 + 8)
|
||||
|
||||
#define ALIGN_CST 15
|
||||
#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.
|
||||
// must be 0 if there's only 1 segment.
|
||||
int size_; // bit-cost for transmitting the segment map
|
||||
} VP8SegmentHeader;
|
||||
} VP8EncSegmentHeader;
|
||||
|
||||
// Struct collecting all frame-persistent probabilities.
|
||||
typedef struct {
|
||||
@ -176,7 +153,7 @@ typedef struct {
|
||||
int dirty_; // if true, need to call VP8CalculateLevelCosts()
|
||||
int use_skip_proba_; // Note: we always use skip_proba for now.
|
||||
int nb_skip_; // number of skipped blocks
|
||||
} VP8Proba;
|
||||
} VP8EncProba;
|
||||
|
||||
// Filter parameters. Not actually used in the code (we don't perform
|
||||
// the in-loop filtering), but filled from user's config
|
||||
@ -185,7 +162,7 @@ typedef struct {
|
||||
int level_; // base filter level [0..63]
|
||||
int sharpness_; // [0..7]
|
||||
int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16
|
||||
} VP8FilterHeader;
|
||||
} VP8EncFilterHeader;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Informations about the macroblocks.
|
||||
@ -271,9 +248,10 @@ typedef struct {
|
||||
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
|
||||
|
||||
// memory for storing y/u/v_left_ and yuv_in_/out_*
|
||||
uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + ALIGN_CST]; // memory for *_left_
|
||||
uint8_t yuv_mem_[3 * YUV_SIZE + PRED_SIZE + ALIGN_CST]; // memory for yuv_*
|
||||
// memory for storing y/u/v_left_
|
||||
uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + ALIGN_CST];
|
||||
// memory for yuv_*
|
||||
uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + ALIGN_CST];
|
||||
} VP8EncIterator;
|
||||
|
||||
// in iterator.c
|
||||
@ -366,8 +344,8 @@ struct VP8Encoder {
|
||||
WebPPicture* pic_; // input / output picture
|
||||
|
||||
// headers
|
||||
VP8FilterHeader filter_hdr_; // filtering information
|
||||
VP8SegmentHeader segment_hdr_; // segment information
|
||||
VP8EncFilterHeader filter_hdr_; // filtering information
|
||||
VP8EncSegmentHeader segment_hdr_; // segment information
|
||||
|
||||
int profile_; // VP8's profile, deduced from Config.
|
||||
|
||||
@ -403,7 +381,7 @@ struct VP8Encoder {
|
||||
int dq_uv_dc_, dq_uv_ac_;
|
||||
|
||||
// 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_count_; // pixel count for the sse_[] stats
|
||||
int coded_size_;
|
||||
@ -438,7 +416,7 @@ extern const uint8_t
|
||||
// Reset the token probabilities to their initial (default) values
|
||||
void VP8DefaultProbas(VP8Encoder* const enc);
|
||||
// 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)
|
||||
void VP8CodeIntraModes(VP8Encoder* const enc);
|
||||
|
||||
|
@ -38,14 +38,14 @@ int WebPGetEncoderVersion(void) {
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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->update_map_ = (hdr->num_segments_ > 1);
|
||||
hdr->size_ = 0;
|
||||
}
|
||||
|
||||
static void ResetFilterHeader(VP8Encoder* const enc) {
|
||||
VP8FilterHeader* const hdr = &enc->filter_hdr_;
|
||||
VP8EncFilterHeader* const hdr = &enc->filter_hdr_;
|
||||
hdr->simple_ = 1;
|
||||
hdr->level_ = 0;
|
||||
hdr->sharpness_ = 0;
|
||||
@ -131,7 +131,7 @@ static void MapConfigToTools(VP8Encoder* const enc) {
|
||||
// VP8EncIterator: 3360
|
||||
// VP8ModeScore: 872
|
||||
// VP8SegmentInfo: 732
|
||||
// VP8Proba: 18352
|
||||
// VP8EncProba: 18352
|
||||
// LFStats: 2048
|
||||
// Picture size (yuv): 419328
|
||||
|
||||
@ -177,10 +177,10 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
|
||||
" VP8EncIterator: %ld\n"
|
||||
" VP8ModeScore: %ld\n"
|
||||
" VP8SegmentInfo: %ld\n"
|
||||
" VP8Proba: %ld\n"
|
||||
" VP8EncProba: %ld\n"
|
||||
" LFStats: %ld\n",
|
||||
sizeof(VP8EncIterator), sizeof(VP8ModeScore),
|
||||
sizeof(VP8SegmentInfo), sizeof(VP8Proba),
|
||||
sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
|
||||
sizeof(LFStats));
|
||||
printf("Picture size (yuv): %ld\n",
|
||||
mb_w * mb_h * 384 * sizeof(uint8_t));
|
||||
|
Loading…
Reference in New Issue
Block a user