3
* Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
5
* Authors: struktur AG, Dirk Farin <farin@struktur.de>
7
* This file is part of libde265.
9
* libde265 is free software: you can redistribute it and/or modify
10
* it under the terms of the GNU Lesser General Public License as
11
* published by the Free Software Foundation, either version 3 of
12
* the License, or (at your option) any later version.
14
* libde265 is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU Lesser General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public License
20
* along with libde265. If not, see <http://www.gnu.org/licenses/>.
24
#include "libde265/encoder/analyze.h"
25
#include "libde265/encoder/encoder-context.h"
32
#define ENCODER_DEVELOPMENT 0
33
#define COMPARE_ESTIMATED_RATE_TO_REAL_RATE 0
36
static int IntraPredModeCnt[7][35];
37
static int MPM_used[7][35];
39
static int IntraPredModeCnt_total[35];
40
static int MPM_used_total[35];
42
void statistics_IntraPredMode(const encoder_context* ectx, int x,int y, const enc_cb* cb)
44
if (cb->split_cu_flag) {
46
if (cb->children[i]) {
47
statistics_IntraPredMode(ectx, childX(x,i,cb->log2Size), childY(y,i,cb->log2Size), cb->children[i]);
52
int size = cb->log2Size;
54
if (cb->PartMode == PART_NxN) { cnt=4; size--; } else cnt=1;
56
for (int i=0;i<cnt;i++) {
57
IntraPredModeCnt[size][ cb->intra.pred_mode[i] ]++;
58
IntraPredModeCnt_total[ cb->intra.pred_mode[i] ]++;
60
int xi = childX(x,i,cb->log2Size);
61
int yi = childY(y,i,cb->log2Size);
64
fillIntraPredModeCandidates(candModeList,xi,yi, xi>0, yi>0, ectx->img);
66
int predmode = cb->intra.pred_mode[i];
67
if (candModeList[0]==predmode ||
68
candModeList[1]==predmode ||
69
candModeList[2]==predmode) {
70
MPM_used[size][predmode]++;
71
MPM_used_total[predmode]++;
77
void statistics_print()
79
for (int i=0;i<35;i++) {
81
printf(" %d %d",IntraPredModeCnt_total[i], MPM_used_total[i]);
83
for (int k=2;k<=6;k++) {
84
printf(" %d %d",IntraPredModeCnt[k][i], MPM_used[k][i]);
92
void print_tb_tree_rates(const enc_tb* tb, int level)
94
for (int i=0;i<level;i++)
97
std::cout << "TB rate=" << tb->rate << " (" << tb->rate_withoutCbfChroma << ")\n";
98
if (tb->split_transform_flag) {
100
print_tb_tree_rates(tb->children[i], level+1);
105
void print_cb_tree_rates(const enc_cb* cb, int level)
107
for (int i=0;i<level;i++)
110
std::cout << "CB rate=" << cb->rate << "\n";
111
if (cb->split_cu_flag) {
112
for (int i=0;i<4;i++)
113
print_cb_tree_rates(cb->children[i], level+1);
116
print_tb_tree_rates(cb->transform_tree, level+1);
121
double encode_image(encoder_context* ectx,
122
const de265_image* input,
123
EncodingAlgorithm& algo)
125
int stride=input->get_image_stride(0);
127
int w = ectx->sps.pic_width_in_luma_samples;
128
int h = ectx->sps.pic_height_in_luma_samples;
130
// --- create reconstruction image ---
131
ectx->img = new de265_image;
132
ectx->img->vps = ectx->vps;
133
ectx->img->sps = ectx->sps;
134
ectx->img->pps = ectx->pps;
135
ectx->img->PicOrderCntVal = input->PicOrderCntVal;
137
ectx->img->alloc_image(w,h, de265_chroma_420, &ectx->sps, true,
138
NULL /* no decctx */, ectx, 0,NULL,false);
139
//ectx->img->alloc_encoder_data(&ectx->sps);
140
ectx->img->clear_metadata();
144
ectx->prediction = new de265_image;
145
ectx->prediction->alloc_image(w,h, de265_chroma_420, &ectx->sps, false /* no metadata */,
146
NULL /* no decctx */, NULL /* no encctx */, 0,NULL,false);
147
ectx->prediction->vps = ectx->vps;
148
ectx->prediction->sps = ectx->sps;
149
ectx->prediction->pps = ectx->pps;
153
ectx->active_qp = ectx->pps.pic_init_qp; // TODO take current qp from slice
156
ectx->cabac_ctx_models.init(ectx->shdr->initType, ectx->shdr->SliceQPY);
157
ectx->cabac_encoder.set_context_models(&ectx->cabac_ctx_models);
160
context_model_table modelEstim;
161
CABAC_encoder_estim cabacEstim;
163
modelEstim.init(ectx->shdr->initType, ectx->shdr->SliceQPY);
164
cabacEstim.set_context_models(&modelEstim);
167
int Log2CtbSize = ectx->sps.Log2CtbSizeY;
169
uint8_t* luma_plane = ectx->img->get_image_plane(0);
170
uint8_t* cb_plane = ectx->img->get_image_plane(1);
171
uint8_t* cr_plane = ectx->img->get_image_plane(2);
176
for (int y=0;y<ectx->sps.PicHeightInCtbsY;y++)
177
for (int x=0;x<ectx->sps.PicWidthInCtbsY;x++)
179
ectx->img->set_SliceAddrRS(x, y, ectx->shdr->SliceAddrRS);
181
int x0 = x<<Log2CtbSize;
182
int y0 = y<<Log2CtbSize;
184
logtrace(LogSlice,"encode CTB at %d %d\n",x0,y0);
186
// make a copy of the context model that we can modify for testing alternatives
188
context_model_table ctxModel;
189
//copy_context_model_table(ctxModel, ectx->ctx_model_bitstream);
190
ctxModel = ectx->cabac_ctx_models.copy();
191
ctxModel = modelEstim.copy(); // TODO TMP
193
disable_logging(LogSymbols);
194
enable_logging(LogSymbols); // TODO TMP
196
//printf("================================================== ANALYZE\n");
200
enc_cb* cb = encode_cb_may_split(ectx, ctxModel,
201
input, x0,y0, Log2CtbSize, 0, qp);
204
enc_cb* cb = algo.getAlgoCTBQScale()->analyze(ectx,ctxModel, x0,y0);
206
float minCost = std::numeric_limits<float>::max();
208
int qp = ectx->params.constant_QP;
211
for (int q=1;q<51;q++) {
212
copy_context_model_table(ctxModel, ectx->ctx_model_bitstream);
214
enc_cb* cbq = encode_cb_may_split(ectx, ctxModel,
215
input, x0,y0, Log2CtbSize, 0, q);
217
float cost = cbq->distortion + ectx->lambda * cbq->rate;
218
if (cost<minCost) { minCost=cost; bestQ=q; }
220
if (q==qp) { cb=cbq; }
223
printf("Q %d\n",bestQ);
227
//print_cb_tree_rates(cb,0);
229
//statistics_IntraPredMode(ectx, x0,y0, cb);
232
// --- write bitstream ---
234
//ectx->switch_CABAC_to_bitstream();
236
enable_logging(LogSymbols);
238
encode_ctb(ectx, &ectx->cabac_encoder, cb, x,y);
240
//printf("================================================== WRITE\n");
243
if (COMPARE_ESTIMATED_RATE_TO_REAL_RATE) {
244
float realPre = cabacEstim.getRDBits();
245
encode_ctb(ectx, &cabacEstim, cb, x,y);
246
float realPost = cabacEstim.getRDBits();
248
printf("estim: %f real: %f diff: %f\n",
251
cb->rate - (realPost-realPre));
255
int last = (y==ectx->sps.PicHeightInCtbsY-1 &&
256
x==ectx->sps.PicWidthInCtbsY-1);
257
ectx->cabac_encoder.write_CABAC_term_bit(last);
262
//ectx->free_all_pools();
266
//statistics_print();
269
delete ectx->prediction;
274
double psnr = PSNR(MSE(input->get_image_plane(0), input->get_image_stride(0),
275
luma_plane, ectx->img->get_image_stride(0),
276
input->get_width(), input->get_height()));
282
void EncodingAlgorithm_Custom::setParams(encoder_params& params)
284
// build algorithm tree
286
mAlgo_CTB_QScale_Constant.setChildAlgo(&mAlgo_CB_Split_BruteForce);
287
mAlgo_CB_Split_BruteForce.setChildAlgo(&mAlgo_CB_Skip_BruteForce);
289
mAlgo_CB_Skip_BruteForce.setSkipAlgo(&mAlgo_CB_MergeIndex_Fixed);
290
mAlgo_CB_Skip_BruteForce.setNonSkipAlgo(&mAlgo_CB_IntraInter_BruteForce);
291
//&mAlgo_CB_InterPartMode_Fixed);
293
Algo_CB_IntraPartMode* algo_CB_IntraPartMode = NULL;
294
switch (params.mAlgo_CB_IntraPartMode()) {
295
case ALGO_CB_IntraPartMode_BruteForce:
296
algo_CB_IntraPartMode = &mAlgo_CB_IntraPartMode_BruteForce;
298
case ALGO_CB_IntraPartMode_Fixed:
299
algo_CB_IntraPartMode = &mAlgo_CB_IntraPartMode_Fixed;
303
mAlgo_CB_IntraInter_BruteForce.setIntraChildAlgo(algo_CB_IntraPartMode);
304
mAlgo_CB_IntraInter_BruteForce.setInterChildAlgo(&mAlgo_CB_InterPartMode_Fixed);
306
mAlgo_CB_MergeIndex_Fixed.setChildAlgo(&mAlgo_TB_Split_BruteForce);
308
Algo_PB_MV* pbAlgo = NULL;
309
switch (params.mAlgo_MEMode()) {
311
pbAlgo = &mAlgo_PB_MV_Test;
314
pbAlgo = &mAlgo_PB_MV_Search;
318
mAlgo_CB_InterPartMode_Fixed.setChildAlgo(pbAlgo);
319
pbAlgo->setChildAlgo(&mAlgo_TB_Split_BruteForce);
322
Algo_TB_IntraPredMode_ModeSubset* algo_TB_IntraPredMode = NULL;
323
switch (params.mAlgo_TB_IntraPredMode()) {
324
case ALGO_TB_IntraPredMode_BruteForce:
325
algo_TB_IntraPredMode = &mAlgo_TB_IntraPredMode_BruteForce;
327
case ALGO_TB_IntraPredMode_FastBrute:
328
algo_TB_IntraPredMode = &mAlgo_TB_IntraPredMode_FastBrute;
330
case ALGO_TB_IntraPredMode_MinResidual:
331
algo_TB_IntraPredMode = &mAlgo_TB_IntraPredMode_MinResidual;
335
algo_CB_IntraPartMode->setChildAlgo(algo_TB_IntraPredMode);
337
mAlgo_TB_Split_BruteForce.setAlgo_TB_IntraPredMode(algo_TB_IntraPredMode);
338
//mAlgo_TB_Split_BruteForce.setParams(params.TB_Split_BruteForce);
340
algo_TB_IntraPredMode->setChildAlgo(&mAlgo_TB_Split_BruteForce);
343
// ===== set algorithm parameters ======
345
//mAlgo_CB_IntraPartMode_Fixed.setParams(params.CB_IntraPartMode_Fixed);
347
//mAlgo_TB_IntraPredMode_FastBrute.setParams(params.TB_IntraPredMode_FastBrute);
348
//mAlgo_TB_IntraPredMode_MinResidual.setParams(params.TB_IntraPredMode_MinResidual);
351
//mAlgo_CTB_QScale_Constant.setParams(params.CTB_QScale_Constant);
354
algo_TB_IntraPredMode->enableIntraPredModeSubset( params.mAlgo_TB_IntraPredMode_Subset() );
358
void Logging::print_logging(const encoder_context* ectx, const char* id, const char* filename)
361
if (strcmp(id,logging_tb_split.name())==0) {
362
logging_tb_split.print(ectx,filename);
368
void en265_print_logging(const encoder_context* ectx, const char* id, const char* filename)
370
Logging::print_logging(ectx,id,filename);