Coverage Report

Created: 2022-08-24 06:11

/src/libde265/libde265/intrapred.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * H.265 video codec.
3
 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
4
 *
5
 * This file is part of libde265.
6
 *
7
 * libde265 is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libde265 is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libde265.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "intrapred.h"
22
#include "transform.h"
23
#include "util.h"
24
#include <assert.h>
25
26
27
#include <sys/types.h>
28
#include <string.h>
29
30
31
32
void fillIntraPredModeCandidates(enum IntraPredMode candModeList[3],
33
                                 enum IntraPredMode candIntraPredModeA,
34
                                 enum IntraPredMode candIntraPredModeB)
35
0
{
36
  // build candidate list
37
38
0
  if (candIntraPredModeA == candIntraPredModeB) {
39
0
    if (candIntraPredModeA < 2) {
40
0
      candModeList[0] = INTRA_PLANAR;
41
0
      candModeList[1] = INTRA_DC;
42
0
      candModeList[2] = INTRA_ANGULAR_26;
43
0
    }
44
0
    else {
45
0
      candModeList[0] = candIntraPredModeA;
46
0
      candModeList[1] = (enum IntraPredMode)(2 + ((candIntraPredModeA-2 -1 +32) % 32));
47
0
      candModeList[2] = (enum IntraPredMode)(2 + ((candIntraPredModeA-2 +1    ) % 32));
48
0
    }
49
0
  }
50
0
  else {
51
0
    candModeList[0] = candIntraPredModeA;
52
0
    candModeList[1] = candIntraPredModeB;
53
54
0
    if (candIntraPredModeA != INTRA_PLANAR &&
55
0
        candIntraPredModeB != INTRA_PLANAR) {
56
0
      candModeList[2] = INTRA_PLANAR;
57
0
    }
58
0
    else if (candIntraPredModeA != INTRA_DC &&
59
0
             candIntraPredModeB != INTRA_DC) {
60
0
      candModeList[2] = INTRA_DC;
61
0
    }
62
0
    else {
63
0
      candModeList[2] = INTRA_ANGULAR_26;
64
0
    }
65
0
  }
66
67
  /*
68
    printf("candModeList: %d %d %d\n",
69
    candModeList[0],
70
    candModeList[1],
71
    candModeList[2]
72
    );
73
  */
74
0
}
75
76
77
void fillIntraPredModeCandidates(enum IntraPredMode candModeList[3], int x,int y, int PUidx,
78
                                 bool availableA, // left
79
                                 bool availableB, // top
80
                                 const de265_image* img)
81
0
{
82
0
  const seq_parameter_set* sps = &img->get_sps();
83
84
  // block on left side
85
86
0
  enum IntraPredMode candIntraPredModeA, candIntraPredModeB;
87
0
  if (availableA==false) {
88
0
    candIntraPredModeA=INTRA_DC;
89
0
  }
90
0
  else if (img->get_pred_mode(x-1,y) != MODE_INTRA ||
91
0
           img->get_pcm_flag (x-1,y)) {
92
0
    candIntraPredModeA=INTRA_DC;
93
0
 }
94
0
  else {
95
0
    candIntraPredModeA = img->get_IntraPredMode_atIndex(PUidx-1);
96
0
  }
97
98
  // block above
99
100
0
  if (availableB==false) {
101
0
    candIntraPredModeB=INTRA_DC;
102
0
  }
103
0
  else if (img->get_pred_mode(x,y-1) != MODE_INTRA ||
104
0
           img->get_pcm_flag (x,y-1)) {
105
0
    candIntraPredModeB=INTRA_DC;
106
0
  }
107
0
  else if (y-1 < ((y >> sps->Log2CtbSizeY) << sps->Log2CtbSizeY)) {
108
0
    candIntraPredModeB=INTRA_DC;
109
0
  }
110
0
  else {
111
0
    candIntraPredModeB = img->get_IntraPredMode_atIndex(PUidx-sps->PicWidthInMinPUs);
112
0
  }
113
114
115
0
  logtrace(LogSlice,"%d;%d candA:%d / candB:%d\n", x,y,
116
0
           availableA ? candIntraPredModeA : -999,
117
0
           availableB ? candIntraPredModeB : -999);
118
119
120
0
  fillIntraPredModeCandidates(candModeList,
121
0
                              candIntraPredModeA,
122
0
                              candIntraPredModeB);
123
0
}
124
125
126
int find_intra_pred_mode(enum IntraPredMode mode,
127
                         enum IntraPredMode candModeList[3])
128
0
{
129
  // check whether the mode is in the candidate list
130
131
0
  for (int i=0;i<3;i++) {
132
0
    if (candModeList[i] == mode) {
133
0
      return i;
134
0
    }
135
0
  }
136
137
  // sort candModeList
138
139
0
  if (candModeList[0] > candModeList[1]) {
140
0
    std::swap(candModeList[0],candModeList[1]);
141
0
  }
142
0
  if (candModeList[0] > candModeList[2]) {
143
0
    std::swap(candModeList[0],candModeList[2]);
144
0
  }
145
0
  if (candModeList[1] > candModeList[2]) {
146
0
    std::swap(candModeList[1],candModeList[2]);
147
0
  }
148
149
  // skip modes already in the candidate list
150
151
0
  int intraMode = mode;
152
153
0
  for (int i=2;i>=0;i--) {
154
0
    if (intraMode >= candModeList[i]) { intraMode--; }
155
0
  }
156
157
0
  return -intraMode-1;
158
0
}
159
160
161
void list_chroma_pred_candidates(enum IntraPredMode chroma_mode[5],
162
                                 enum IntraPredMode luma_mode)
163
0
{
164
0
  enum IntraPredMode chroma_cand[5];
165
0
  chroma_cand[0] = INTRA_PLANAR;
166
0
  chroma_cand[1] = INTRA_ANGULAR_26;
167
0
  chroma_cand[2] = INTRA_ANGULAR_10;
168
0
  chroma_cand[3] = INTRA_DC;
169
0
  chroma_cand[4] = luma_mode;
170
171
0
  switch (luma_mode) {
172
0
  case INTRA_PLANAR:     chroma_cand[0] = INTRA_ANGULAR_34; break;
173
0
  case INTRA_ANGULAR_26: chroma_cand[1] = INTRA_ANGULAR_34; break;
174
0
  case INTRA_ANGULAR_10: chroma_cand[2] = INTRA_ANGULAR_34; break;
175
0
  case INTRA_DC:         chroma_cand[3] = INTRA_ANGULAR_34; break;
176
0
  default:
177
    // use defaults from above
178
0
    break;
179
0
  }
180
0
}
181
182
183
int get_intra_scan_idx(int log2TrafoSize, enum IntraPredMode intraPredMode, int cIdx,
184
                       const seq_parameter_set* sps)
185
0
{
186
0
  if (log2TrafoSize==2 ||
187
0
      (log2TrafoSize==3 && (cIdx==0 ||
188
0
                            sps->ChromaArrayType==CHROMA_444))) {
189
0
    /**/ if (intraPredMode >=  6 && intraPredMode <= 14) return 2;
190
0
    else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
191
0
    else return 0;
192
0
  }
193
0
  else { return 0; }
194
0
}
195
196
197
int get_intra_scan_idx_luma(int log2TrafoSize, enum IntraPredMode intraPredMode)
198
0
{
199
0
  if (log2TrafoSize==2 || log2TrafoSize==3) {
200
0
    /**/ if (intraPredMode >=  6 && intraPredMode <= 14) return 2;
201
0
    else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
202
0
    else return 0;
203
0
  }
204
0
  else { return 0; }
205
0
}
206
207
int get_intra_scan_idx_chroma(int log2TrafoSize, enum IntraPredMode intraPredMode)
208
0
{
209
0
  if (log2TrafoSize==1 || log2TrafoSize==2) {
210
0
    /**/ if (intraPredMode >=  6 && intraPredMode <= 14) return 2;
211
0
    else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
212
0
    else return 0;
213
0
  }
214
0
  else { return 0; }
215
0
}
216
217
218
enum IntraPredMode lumaPredMode_to_chromaPredMode(enum IntraPredMode luma,
219
                                                  enum IntraChromaPredMode chroma)
220
0
{
221
0
  switch (chroma) {
222
0
  case INTRA_CHROMA_LIKE_LUMA:
223
0
    return luma;
224
225
0
  case INTRA_CHROMA_PLANAR_OR_34:
226
0
    if (luma==INTRA_PLANAR) return INTRA_ANGULAR_34;
227
0
    else                    return INTRA_PLANAR;
228
229
0
  case INTRA_CHROMA_ANGULAR_26_OR_34:
230
0
    if (luma==INTRA_ANGULAR_26) return INTRA_ANGULAR_34;
231
0
    else                        return INTRA_ANGULAR_26;
232
233
0
  case INTRA_CHROMA_ANGULAR_10_OR_34:
234
0
    if (luma==INTRA_ANGULAR_10) return INTRA_ANGULAR_34;
235
0
    else                        return INTRA_ANGULAR_10;
236
237
0
  case INTRA_CHROMA_DC_OR_34:
238
0
    if (luma==INTRA_DC)         return INTRA_ANGULAR_34;
239
0
    else                        return INTRA_DC;
240
0
  }
241
242
243
0
  assert(false);
244
0
  return INTRA_DC;
245
0
}
246
247
248
249
250
// (8.4.4.2.2)
251
template <class pixel_t>
252
void fill_border_samples(de265_image* img,
253
                         int xB,int yB,  // in component specific resolution
254
                         int nT, int cIdx,
255
                         pixel_t* out_border)
256
0
{
257
0
  intra_border_computer<pixel_t> c;
258
0
  c.init(out_border, img, nT, cIdx, xB, yB);
259
0
  c.preproc();
260
0
  c.fill_from_image();
261
0
  c.reference_sample_substitution();
262
0
}
Unexecuted instantiation: void fill_border_samples<unsigned short>(de265_image*, int, int, int, int, unsigned short*)
Unexecuted instantiation: void fill_border_samples<unsigned char>(de265_image*, int, int, int, int, unsigned char*)
263
264
265
const int intraPredAngle_table[1+34] =
266
  { 0, 0,32,26,21,17,13, 9, 5, 2, 0,-2,-5,-9,-13,-17,-21,-26,
267
    -32,-26,-21,-17,-13,-9,-5,-2,0,2,5,9,13,17,21,26,32 };
268
269
const int invAngle_table[25-10] =
270
  { -4096,-1638,-910,-630,-482,-390,-315,-256,
271
    -315,-390,-482,-630,-910,-1638,-4096 };
272
273
274
template <class pixel_t>
275
void decode_intra_prediction_internal(de265_image* img,
276
                                      int xB0,int yB0,
277
                                      enum IntraPredMode intraPredMode,
278
                                      pixel_t* dst, int dstStride,
279
                                      int nT, int cIdx)
280
0
{
281
0
  pixel_t  border_pixels_mem[4*MAX_INTRA_PRED_BLOCK_SIZE+1];
282
0
  pixel_t* border_pixels = &border_pixels_mem[2*MAX_INTRA_PRED_BLOCK_SIZE];
283
284
0
  fill_border_samples(img, xB0,yB0, nT, cIdx, border_pixels);
285
286
0
  if (img->get_sps().range_extension.intra_smoothing_disabled_flag == 0 &&
287
0
      (cIdx==0 || img->get_sps().ChromaArrayType==CHROMA_444))
288
0
    {
289
0
      intra_prediction_sample_filtering(img->get_sps(), border_pixels, nT, cIdx, intraPredMode);
290
0
    }
291
292
293
0
  switch (intraPredMode) {
294
0
  case INTRA_PLANAR:
295
0
    intra_prediction_planar(dst,dstStride, nT,cIdx, border_pixels);
296
0
    break;
297
0
  case INTRA_DC:
298
0
    intra_prediction_DC(dst,dstStride, nT,cIdx, border_pixels);
299
0
    break;
300
0
  default:
301
0
    {
302
0
      int bit_depth = img->get_bit_depth(cIdx);
303
0
      bool disableIntraBoundaryFilter =
304
0
        (img->get_sps().range_extension.implicit_rdpcm_enabled_flag &&
305
0
         img->get_cu_transquant_bypass(xB0,yB0));
306
307
0
      intra_prediction_angular(dst,dstStride, bit_depth,disableIntraBoundaryFilter,
308
0
                               xB0,yB0,intraPredMode,nT,cIdx, border_pixels);
309
0
    }
310
0
    break;
311
0
  }
312
0
}
Unexecuted instantiation: void decode_intra_prediction_internal<unsigned short>(de265_image*, int, int, IntraPredMode, unsigned short*, int, int, int)
Unexecuted instantiation: void decode_intra_prediction_internal<unsigned char>(de265_image*, int, int, IntraPredMode, unsigned char*, int, int, int)
313
314
315
// (8.4.4.2.1)
316
void decode_intra_prediction(de265_image* img,
317
                             int xB0,int yB0,
318
                             enum IntraPredMode intraPredMode,
319
                             int nT, int cIdx)
320
0
{
321
0
  logtrace(LogIntraPred,"decode_intra_prediction xy0:%d/%d mode=%d nT=%d, cIdx=%d\n",
322
0
           xB0,yB0, intraPredMode, nT,cIdx);
323
  /*
324
    printf("decode_intra_prediction xy0:%d/%d mode=%d nT=%d, cIdx=%d\n",
325
    xB0,yB0, intraPredMode, nT,cIdx);
326
  */
327
328
0
  if (img->high_bit_depth(cIdx)) {
329
0
    decode_intra_prediction_internal<uint16_t>(img,xB0,yB0, intraPredMode,
330
0
                                               img->get_image_plane_at_pos_NEW<uint16_t>(cIdx,xB0,yB0),
331
0
                                               img->get_image_stride(cIdx),
332
0
                                               nT,cIdx);
333
0
  }
334
0
  else {
335
0
    decode_intra_prediction_internal<uint8_t>(img,xB0,yB0, intraPredMode,
336
0
                                              img->get_image_plane_at_pos_NEW<uint8_t>(cIdx,xB0,yB0),
337
0
                                              img->get_image_stride(cIdx),
338
0
                                              nT,cIdx);
339
0
  }
340
0
}
341
342
343
// TODO: remove this
344
template <> void decode_intra_prediction<uint8_t>(de265_image* img,
345
                                                  int xB0,int yB0,
346
                                                  enum IntraPredMode intraPredMode,
347
                                                  uint8_t* dst, int nT, int cIdx)
348
0
{
349
0
    decode_intra_prediction_internal<uint8_t>(img,xB0,yB0, intraPredMode,
350
0
                                              dst,nT,
351
0
                                              nT,cIdx);
352
0
}
353
354
355
// TODO: remove this
356
template <> void decode_intra_prediction<uint16_t>(de265_image* img,
357
                                                   int xB0,int yB0,
358
                                                   enum IntraPredMode intraPredMode,
359
                                                   uint16_t* dst, int nT, int cIdx)
360
0
{
361
0
  decode_intra_prediction_internal<uint16_t>(img,xB0,yB0, intraPredMode,
362
0
                                             dst,nT,
363
0
                                             nT,cIdx);
364
0
}