Coverage Report

Created: 2026-06-15 06:25

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