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

« back to all changes in this revision

Viewing changes to libde265/encoder/algo/pb-mv.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/algo/pb-mv.h"
 
25
#include "libde265/encoder/algo/coding-options.h"
 
26
#include "libde265/encoder/encoder-context.h"
 
27
#include <assert.h>
 
28
#include <limits>
 
29
#include <math.h>
 
30
 
 
31
 
 
32
 
 
33
enc_cb* Algo_PB_MV_Test::analyze(encoder_context* ectx,
 
34
                                 context_model_table& ctxModel,
 
35
                                 enc_cb* cb,
 
36
                                 int PBidx, int x,int y,int w,int h)
 
37
{
 
38
  enum MVTestMode testMode = mParams.testMode();
 
39
 
 
40
 
 
41
  MotionVector mvp[2];
 
42
 
 
43
  fill_luma_motion_vector_predictors(ectx, ectx->shdr, ectx->img,
 
44
                                     cb->x,cb->y,1<<cb->log2Size, x,y,w,h,
 
45
                                     0, // l
 
46
                                     0, 0, // int refIdx, int partIdx,
 
47
                                     mvp);
 
48
 
 
49
  //printf("%d/%d: [%d;%d] [%d;%d]\n",cb->x,cb->y, mvp[0].x,mvp[0].y, mvp[1].x,mvp[1].y);
 
50
 
 
51
 
 
52
  motion_spec&     spec = cb->inter.pb[PBidx].spec;
 
53
  MotionVectorSpec& vec = cb->inter.pb[PBidx].motion;
 
54
 
 
55
  spec.merge_flag = 0;
 
56
  spec.merge_idx  = 0;
 
57
 
 
58
  spec.inter_pred_idc = PRED_L0;
 
59
  spec.refIdx[0] = vec.refIdx[0] = 0;
 
60
  spec.mvp_l0_flag = 0;
 
61
 
 
62
  int value = mParams.range();
 
63
 
 
64
  switch (testMode) {
 
65
  case MVTestMode_Zero:
 
66
    spec.mvd[0][0]=0;
 
67
    spec.mvd[0][1]=0;
 
68
    break;
 
69
 
 
70
  case MVTestMode_Random:
 
71
    spec.mvd[0][0] = (rand() % (2*value+1)) - value;
 
72
    spec.mvd[0][1] = (rand() % (2*value+1)) - value;
 
73
    break;
 
74
 
 
75
  case MVTestMode_Horizontal:
 
76
    spec.mvd[0][0]=value;
 
77
    spec.mvd[0][1]=0;
 
78
    break;
 
79
 
 
80
  case MVTestMode_Vertical:
 
81
    spec.mvd[0][0]=0;
 
82
    spec.mvd[0][1]=value;
 
83
    break;
 
84
  }
 
85
 
 
86
  spec.mvd[0][0] -= mvp[0].x;
 
87
  spec.mvd[0][1] -= mvp[0].y;
 
88
 
 
89
  vec.mv[0].x = mvp[0].x + spec.mvd[0][0];
 
90
  vec.mv[0].y = mvp[0].y + spec.mvd[0][1];
 
91
  vec.predFlag[0] = 1;
 
92
  vec.predFlag[1] = 0;
 
93
 
 
94
  ectx->img->set_mv_info(x,y,w,h, vec);
 
95
 
 
96
  generate_inter_prediction_samples(ectx, ectx->shdr, ectx->prediction,
 
97
                                    cb->x,cb->y, // int xC,int yC,
 
98
                                    0,0,         // int xB,int yB,
 
99
                                    1<<cb->log2Size, // int nCS,
 
100
                                    1<<cb->log2Size,
 
101
                                    1<<cb->log2Size, // int nPbW,int nPbH,
 
102
                                    &vec);
 
103
 
 
104
  // TODO estimate rate for sending MV
 
105
 
 
106
  int IntraSplitFlag = 0;
 
107
  int MaxTrafoDepth = ectx->sps.max_transform_hierarchy_depth_inter;
 
108
 
 
109
  mCodeResidual=true;
 
110
  if (mCodeResidual) {
 
111
    assert(mTBSplitAlgo);
 
112
    cb->transform_tree = mTBSplitAlgo->analyze(ectx,ctxModel, ectx->imgdata->input, NULL, cb,
 
113
                                               cb->x,cb->y,cb->x,cb->y, cb->log2Size,0,
 
114
                                               0, MaxTrafoDepth, IntraSplitFlag);
 
115
 
 
116
    cb->inter.rqt_root_cbf = ! cb->transform_tree->isZeroBlock();
 
117
 
 
118
    cb->distortion = cb->transform_tree->distortion;
 
119
    cb->rate       = cb->transform_tree->rate;
 
120
  }
 
121
  else {
 
122
    const de265_image* input = ectx->imgdata->input;
 
123
    de265_image* img   = ectx->prediction;
 
124
    int x0 = cb->x;
 
125
    int y0 = cb->y;
 
126
    int tbSize = 1<<cb->log2Size;
 
127
 
 
128
    cb->distortion = compute_distortion_ssd(input, img, x0,y0, cb->log2Size, 0);
 
129
    cb->rate = 5; // fake (MV)
 
130
 
 
131
    cb->inter.rqt_root_cbf = 0;
 
132
  }
 
133
 
 
134
  return cb;
 
135
}
 
136
 
 
137
 
 
138
 
 
139
 
 
140
int sad(const uint8_t* p1,int stride1,
 
141
        const uint8_t* p2,int stride2,
 
142
        int w,int h)
 
143
{
 
144
  int cost=0;
 
145
 
 
146
  for (int y=0;y<h;y++) {
 
147
    for (int x=0;x<w;x++) {
 
148
      cost += abs_value(*p1 - *p2);
 
149
      p1++;
 
150
      p2++;
 
151
    }
 
152
 
 
153
    p1 += stride1-w;
 
154
    p2 += stride2-w;
 
155
  }
 
156
 
 
157
  return cost;
 
158
}
 
159
 
 
160
 
 
161
enc_cb* Algo_PB_MV_Search::analyze(encoder_context* ectx,
 
162
                                   context_model_table& ctxModel,
 
163
                                   enc_cb* cb,
 
164
                                   int PBidx, int x,int y,int pbW,int pbH)
 
165
{
 
166
  enum MVSearchAlgo searchAlgo = mParams.mvSearchAlgo();
 
167
 
 
168
 
 
169
  MotionVector mvp[2];
 
170
 
 
171
  fill_luma_motion_vector_predictors(ectx, ectx->shdr, ectx->img,
 
172
                                     cb->x,cb->y,1<<cb->log2Size, x,y,pbW,pbH,
 
173
                                     0, // l
 
174
                                     0, 0, // int refIdx, int partIdx,
 
175
                                     mvp);
 
176
 
 
177
  motion_spec&     spec = cb->inter.pb[PBidx].spec;
 
178
  MotionVectorSpec& vec = cb->inter.pb[PBidx].motion;
 
179
 
 
180
  spec.merge_flag = 0;
 
181
  spec.merge_idx  = 0;
 
182
 
 
183
  spec.inter_pred_idc = PRED_L0;
 
184
  spec.refIdx[0] = vec.refIdx[0] = 0;
 
185
  spec.mvp_l0_flag = 0;
 
186
 
 
187
  int hrange = mParams.hrange();
 
188
  int vrange = mParams.vrange();
 
189
 
 
190
  // previous frame (TODO)
 
191
  const de265_image* refimg   = ectx->get_image(ectx->imgdata->frame_number -1);
 
192
  const de265_image* inputimg = ectx->imgdata->input;
 
193
 
 
194
  int w = refimg->get_width();
 
195
  int h = refimg->get_height();
 
196
 
 
197
  int mincost = 0x7fffffff;
 
198
 
 
199
  double lambda = 10.0;
 
200
 
 
201
  double *bits_h = new double[2*hrange+1];
 
202
  double *bits_v = new double[2*vrange+1];
 
203
 
 
204
  for (int i=-hrange;i<=hrange;i++) {
 
205
    int diff = (i - mvp[0].x);
 
206
    int b;
 
207
 
 
208
    if (diff==0) { b=0; }
 
209
    else if (diff==1 || diff==-1) { b=2; }
 
210
    else { b=abs_value(b+2); }
 
211
 
 
212
    bits_h[i+hrange]=b;
 
213
  }
 
214
 
 
215
  for (int i=-vrange;i<=vrange;i++) {
 
216
    int diff = (i - mvp[0].y);
 
217
    int b;
 
218
 
 
219
    if (diff==0) { b=0; }
 
220
    else if (diff==1 || diff==-1) { b=2; }
 
221
    else { b=abs_value(b+2); }
 
222
 
 
223
    bits_v[i+vrange]=b;
 
224
  }
 
225
 
 
226
  for (int my = y-vrange; my<=y+vrange; my++)
 
227
    for (int mx = x-hrange; mx<=x+hrange; mx++)
 
228
      {
 
229
        if (mx<0 || mx+pbW>w || my<0 || my+pbH>h) continue;
 
230
 
 
231
        int cost = sad(refimg->get_image_plane_at_pos(0,mx,my),
 
232
                       refimg->get_image_stride(0),
 
233
                       inputimg->get_image_plane_at_pos(0,x,y),
 
234
                       inputimg->get_image_stride(0),
 
235
                       pbW,pbH);
 
236
 
 
237
        int bits = bits_h[mx-x+hrange] + bits_v[my-y+vrange];
 
238
 
 
239
        cost += lambda * bits;
 
240
 
 
241
        //printf("%d %d : %d\n",mx,my,cost);
 
242
 
 
243
        if (cost<mincost) {
 
244
          mincost=cost;
 
245
 
 
246
          spec.mvd[0][0]=(mx-x)<<2;
 
247
          spec.mvd[0][1]=(my-y)<<2;
 
248
        }
 
249
      }
 
250
 
 
251
  spec.mvd[0][0] -= mvp[0].x;
 
252
  spec.mvd[0][1] -= mvp[0].y;
 
253
 
 
254
  vec.mv[0].x = mvp[0].x + spec.mvd[0][0];
 
255
  vec.mv[0].y = mvp[0].y + spec.mvd[0][1];
 
256
  vec.predFlag[0] = 1;
 
257
  vec.predFlag[1] = 0;
 
258
 
 
259
  ectx->img->set_mv_info(x,y,pbW,pbH, vec);
 
260
 
 
261
  generate_inter_prediction_samples(ectx, ectx->shdr, ectx->prediction,
 
262
                                    cb->x,cb->y, // int xC,int yC,
 
263
                                    0,0,         // int xB,int yB,
 
264
                                    1<<cb->log2Size, // int nCS,
 
265
                                    1<<cb->log2Size,
 
266
                                    1<<cb->log2Size, // int nPbW,int nPbH,
 
267
                                    &vec);
 
268
 
 
269
  // --- create residual ---
 
270
 
 
271
 
 
272
 
 
273
  // TODO estimate rate for sending MV
 
274
 
 
275
  int IntraSplitFlag = 0;
 
276
  int MaxTrafoDepth = ectx->sps.max_transform_hierarchy_depth_inter;
 
277
 
 
278
  mCodeResidual=true;
 
279
  if (mCodeResidual) {
 
280
    cb->transform_tree = mTBSplitAlgo->analyze(ectx,ctxModel, ectx->imgdata->input, NULL, cb,
 
281
                                               cb->x,cb->y,cb->x,cb->y, cb->log2Size,0,
 
282
                                               0, MaxTrafoDepth, IntraSplitFlag);
 
283
 
 
284
    cb->inter.rqt_root_cbf = ! cb->transform_tree->isZeroBlock();
 
285
 
 
286
    cb->distortion = cb->transform_tree->distortion;
 
287
    cb->rate       = cb->transform_tree->rate;
 
288
  }
 
289
  else {
 
290
    const de265_image* input = ectx->imgdata->input;
 
291
    de265_image* img   = ectx->img;
 
292
    int x0 = cb->x;
 
293
    int y0 = cb->y;
 
294
    int tbSize = 1<<cb->log2Size;
 
295
 
 
296
    cb->distortion = compute_distortion_ssd(input, img, x0,y0, cb->log2Size, 0);
 
297
    cb->rate = 5; // fake (MV)
 
298
 
 
299
    cb->inter.rqt_root_cbf = 0;
 
300
  }
 
301
 
 
302
  delete[] bits_h;
 
303
  delete[] bits_v;
 
304
 
 
305
  return cb;
 
306
}