~ubuntu-branches/ubuntu/wily/libde265/wily

« back to all changes in this revision

Viewing changes to libde265/encoder/analyze.cc

  • Committer: Package Import Robot
  • Author(s): Joachim Bauch
  • Date: 2015-07-16 11:07:46 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20150716110746-76vsv24j3yux7tnu
Tags: 1.0.2-1
* Imported Upstream version 1.0.2
* Added new files to copyright information.
* Only export decoder API and update symbols for new version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * H.265 video codec.
 
3
 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
 
4
 *
 
5
 * Authors: struktur AG, Dirk Farin <farin@struktur.de>
 
6
 *
 
7
 * This file is part of libde265.
 
8
 *
 
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.
 
13
 *
 
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.
 
18
 *
 
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/>.
 
21
 */
 
22
 
 
23
 
 
24
#include "libde265/encoder/analyze.h"
 
25
#include "libde265/encoder/encoder-context.h"
 
26
#include <assert.h>
 
27
#include <limits>
 
28
#include <math.h>
 
29
#include <iostream>
 
30
 
 
31
 
 
32
#define ENCODER_DEVELOPMENT 0
 
33
#define COMPARE_ESTIMATED_RATE_TO_REAL_RATE 0
 
34
 
 
35
 
 
36
static int IntraPredModeCnt[7][35];
 
37
static int MPM_used[7][35];
 
38
 
 
39
static int IntraPredModeCnt_total[35];
 
40
static int MPM_used_total[35];
 
41
 
 
42
void statistics_IntraPredMode(const encoder_context* ectx, int x,int y, const enc_cb* cb)
 
43
{
 
44
  if (cb->split_cu_flag) {
 
45
    for (int i=0;i<4;i++)
 
46
      if (cb->children[i]) {
 
47
        statistics_IntraPredMode(ectx, childX(x,i,cb->log2Size), childY(y,i,cb->log2Size), cb->children[i]);
 
48
      }
 
49
  }
 
50
  else {
 
51
    int cnt;
 
52
    int size = cb->log2Size;
 
53
 
 
54
    if (cb->PartMode == PART_NxN) { cnt=4; size--; } else cnt=1;
 
55
 
 
56
    for (int i=0;i<cnt;i++) {
 
57
      IntraPredModeCnt[size][ cb->intra.pred_mode[i] ]++;
 
58
      IntraPredModeCnt_total[ cb->intra.pred_mode[i] ]++;
 
59
 
 
60
      int xi = childX(x,i,cb->log2Size);
 
61
      int yi = childY(y,i,cb->log2Size);
 
62
 
 
63
      int candModeList[3];
 
64
      fillIntraPredModeCandidates(candModeList,xi,yi, xi>0, yi>0, ectx->img);
 
65
 
 
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]++;
 
72
      }
 
73
    }
 
74
  }
 
75
}
 
76
 
 
77
void statistics_print()
 
78
{
 
79
  for (int i=0;i<35;i++) {
 
80
    printf("%d",i);
 
81
    printf("  %d %d",IntraPredModeCnt_total[i], MPM_used_total[i]);
 
82
 
 
83
    for (int k=2;k<=6;k++) {
 
84
      printf("  %d %d",IntraPredModeCnt[k][i], MPM_used[k][i]);
 
85
    }
 
86
 
 
87
    printf("\n");
 
88
  }
 
89
}
 
90
 
 
91
 
 
92
void print_tb_tree_rates(const enc_tb* tb, int level)
 
93
{
 
94
  for (int i=0;i<level;i++)
 
95
    std::cout << "  ";
 
96
 
 
97
  std::cout << "TB rate=" << tb->rate << " (" << tb->rate_withoutCbfChroma << ")\n";
 
98
  if (tb->split_transform_flag) {
 
99
    for (int i=0;i<4;i++)
 
100
      print_tb_tree_rates(tb->children[i], level+1);
 
101
  }
 
102
}
 
103
 
 
104
 
 
105
void print_cb_tree_rates(const enc_cb* cb, int level)
 
106
{
 
107
  for (int i=0;i<level;i++)
 
108
    std::cout << "  ";
 
109
 
 
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);
 
114
  }
 
115
  else {
 
116
    print_tb_tree_rates(cb->transform_tree, level+1);
 
117
  }
 
118
}
 
119
 
 
120
 
 
121
double encode_image(encoder_context* ectx,
 
122
                    const de265_image* input,
 
123
                    EncodingAlgorithm& algo)
 
124
{
 
125
  int stride=input->get_image_stride(0);
 
126
 
 
127
  int w = ectx->sps.pic_width_in_luma_samples;
 
128
  int h = ectx->sps.pic_height_in_luma_samples;
 
129
 
 
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;
 
136
 
 
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();
 
141
 
 
142
#if 1
 
143
  if (1) {
 
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;
 
150
  }
 
151
#endif
 
152
 
 
153
  ectx->active_qp = ectx->pps.pic_init_qp; // TODO take current qp from slice
 
154
 
 
155
 
 
156
  ectx->cabac_ctx_models.init(ectx->shdr->initType, ectx->shdr->SliceQPY);
 
157
  ectx->cabac_encoder.set_context_models(&ectx->cabac_ctx_models);
 
158
 
 
159
 
 
160
  context_model_table modelEstim;
 
161
  CABAC_encoder_estim cabacEstim;
 
162
 
 
163
  modelEstim.init(ectx->shdr->initType, ectx->shdr->SliceQPY);
 
164
  cabacEstim.set_context_models(&modelEstim);
 
165
 
 
166
 
 
167
  int Log2CtbSize = ectx->sps.Log2CtbSizeY;
 
168
 
 
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);
 
172
 
 
173
 
 
174
  // encode CTB by CTB
 
175
 
 
176
  for (int y=0;y<ectx->sps.PicHeightInCtbsY;y++)
 
177
    for (int x=0;x<ectx->sps.PicWidthInCtbsY;x++)
 
178
      {
 
179
        ectx->img->set_SliceAddrRS(x, y, ectx->shdr->SliceAddrRS);
 
180
 
 
181
        int x0 = x<<Log2CtbSize;
 
182
        int y0 = y<<Log2CtbSize;
 
183
 
 
184
        logtrace(LogSlice,"encode CTB at %d %d\n",x0,y0);
 
185
 
 
186
        // make a copy of the context model that we can modify for testing alternatives
 
187
 
 
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
 
192
 
 
193
        disable_logging(LogSymbols);
 
194
        enable_logging(LogSymbols);  // TODO TMP
 
195
 
 
196
        //printf("================================================== ANALYZE\n");
 
197
 
 
198
#if 1
 
199
        /*
 
200
          enc_cb* cb = encode_cb_may_split(ectx, ctxModel,
 
201
          input, x0,y0, Log2CtbSize, 0, qp);
 
202
        */
 
203
 
 
204
        enc_cb* cb = algo.getAlgoCTBQScale()->analyze(ectx,ctxModel, x0,y0);
 
205
#else
 
206
        float minCost = std::numeric_limits<float>::max();
 
207
        int bestQ = 0;
 
208
        int qp = ectx->params.constant_QP;
 
209
 
 
210
        enc_cb* cb;
 
211
        for (int q=1;q<51;q++) {
 
212
          copy_context_model_table(ctxModel, ectx->ctx_model_bitstream);
 
213
 
 
214
          enc_cb* cbq = encode_cb_may_split(ectx, ctxModel,
 
215
                                            input, x0,y0, Log2CtbSize, 0, q);
 
216
 
 
217
          float cost = cbq->distortion + ectx->lambda * cbq->rate;
 
218
          if (cost<minCost) { minCost=cost; bestQ=q; }
 
219
 
 
220
          if (q==qp) { cb=cbq; }
 
221
        }
 
222
 
 
223
        printf("Q %d\n",bestQ);
 
224
        fflush(stdout);
 
225
#endif
 
226
 
 
227
        //print_cb_tree_rates(cb,0);
 
228
 
 
229
        //statistics_IntraPredMode(ectx, x0,y0, cb);
 
230
 
 
231
 
 
232
        // --- write bitstream ---
 
233
 
 
234
        //ectx->switch_CABAC_to_bitstream();
 
235
 
 
236
        enable_logging(LogSymbols);
 
237
 
 
238
        encode_ctb(ectx, &ectx->cabac_encoder, cb, x,y);
 
239
 
 
240
        //printf("================================================== WRITE\n");
 
241
 
 
242
 
 
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();
 
247
 
 
248
          printf("estim: %f  real: %f  diff: %f\n",
 
249
                 cb->rate,
 
250
                 realPost-realPre,
 
251
                 cb->rate - (realPost-realPre));
 
252
        }
 
253
 
 
254
 
 
255
        int last = (y==ectx->sps.PicHeightInCtbsY-1 &&
 
256
                    x==ectx->sps.PicWidthInCtbsY-1);
 
257
        ectx->cabac_encoder.write_CABAC_term_bit(last);
 
258
 
 
259
 
 
260
        delete cb;
 
261
 
 
262
        //ectx->free_all_pools();
 
263
      }
 
264
 
 
265
 
 
266
  //statistics_print();
 
267
 
 
268
 
 
269
  delete ectx->prediction;
 
270
 
 
271
 
 
272
  // frame PSNR
 
273
 
 
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()));
 
277
  return psnr;
 
278
}
 
279
 
 
280
 
 
281
 
 
282
void EncodingAlgorithm_Custom::setParams(encoder_params& params)
 
283
{
 
284
  // build algorithm tree
 
285
 
 
286
  mAlgo_CTB_QScale_Constant.setChildAlgo(&mAlgo_CB_Split_BruteForce);
 
287
  mAlgo_CB_Split_BruteForce.setChildAlgo(&mAlgo_CB_Skip_BruteForce);
 
288
 
 
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);
 
292
 
 
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;
 
297
    break;
 
298
  case ALGO_CB_IntraPartMode_Fixed:
 
299
    algo_CB_IntraPartMode = &mAlgo_CB_IntraPartMode_Fixed;
 
300
    break;
 
301
  }
 
302
 
 
303
  mAlgo_CB_IntraInter_BruteForce.setIntraChildAlgo(algo_CB_IntraPartMode);
 
304
  mAlgo_CB_IntraInter_BruteForce.setInterChildAlgo(&mAlgo_CB_InterPartMode_Fixed);
 
305
 
 
306
  mAlgo_CB_MergeIndex_Fixed.setChildAlgo(&mAlgo_TB_Split_BruteForce);
 
307
 
 
308
  Algo_PB_MV* pbAlgo = NULL;
 
309
  switch (params.mAlgo_MEMode()) {
 
310
  case MEMode_Test:
 
311
    pbAlgo = &mAlgo_PB_MV_Test;
 
312
    break;
 
313
  case MEMode_Search:
 
314
    pbAlgo = &mAlgo_PB_MV_Search;
 
315
    break;
 
316
  }
 
317
 
 
318
  mAlgo_CB_InterPartMode_Fixed.setChildAlgo(pbAlgo);
 
319
  pbAlgo->setChildAlgo(&mAlgo_TB_Split_BruteForce);
 
320
 
 
321
 
 
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;
 
326
    break;
 
327
  case ALGO_TB_IntraPredMode_FastBrute:
 
328
    algo_TB_IntraPredMode = &mAlgo_TB_IntraPredMode_FastBrute;
 
329
    break;
 
330
  case ALGO_TB_IntraPredMode_MinResidual:
 
331
    algo_TB_IntraPredMode = &mAlgo_TB_IntraPredMode_MinResidual;
 
332
    break;
 
333
  }
 
334
 
 
335
  algo_CB_IntraPartMode->setChildAlgo(algo_TB_IntraPredMode);
 
336
 
 
337
  mAlgo_TB_Split_BruteForce.setAlgo_TB_IntraPredMode(algo_TB_IntraPredMode);
 
338
  //mAlgo_TB_Split_BruteForce.setParams(params.TB_Split_BruteForce);
 
339
 
 
340
  algo_TB_IntraPredMode->setChildAlgo(&mAlgo_TB_Split_BruteForce);
 
341
 
 
342
 
 
343
  // ===== set algorithm parameters ======
 
344
 
 
345
  //mAlgo_CB_IntraPartMode_Fixed.setParams(params.CB_IntraPartMode_Fixed);
 
346
 
 
347
  //mAlgo_TB_IntraPredMode_FastBrute.setParams(params.TB_IntraPredMode_FastBrute);
 
348
  //mAlgo_TB_IntraPredMode_MinResidual.setParams(params.TB_IntraPredMode_MinResidual);
 
349
 
 
350
 
 
351
  //mAlgo_CTB_QScale_Constant.setParams(params.CTB_QScale_Constant);
 
352
 
 
353
 
 
354
  algo_TB_IntraPredMode->enableIntraPredModeSubset( params.mAlgo_TB_IntraPredMode_Subset() );
 
355
}
 
356
 
 
357
 
 
358
void Logging::print_logging(const encoder_context* ectx, const char* id, const char* filename)
 
359
{
 
360
#if 000
 
361
  if (strcmp(id,logging_tb_split.name())==0) {
 
362
    logging_tb_split.print(ectx,filename);
 
363
  }
 
364
#endif
 
365
}
 
366
 
 
367
 
 
368
void en265_print_logging(const encoder_context* ectx, const char* id, const char* filename)
 
369
{
 
370
  Logging::print_logging(ectx,id,filename);
 
371
}