Coverage Report

Created: 2026-03-08 06:41

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 <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
#if 0
162
void list_chroma_pred_candidates(enum IntraPredMode chroma_mode[5],
163
                                 enum IntraPredMode luma_mode)
164
{
165
  enum IntraPredMode chroma_cand[5];
166
  chroma_cand[0] = INTRA_PLANAR;
167
  chroma_cand[1] = INTRA_ANGULAR_26;
168
  chroma_cand[2] = INTRA_ANGULAR_10;
169
  chroma_cand[3] = INTRA_DC;
170
  chroma_cand[4] = luma_mode;
171
172
  switch (luma_mode) {
173
  case INTRA_PLANAR:     chroma_cand[0] = INTRA_ANGULAR_34; break;
174
  case INTRA_ANGULAR_26: chroma_cand[1] = INTRA_ANGULAR_34; break;
175
  case INTRA_ANGULAR_10: chroma_cand[2] = INTRA_ANGULAR_34; break;
176
  case INTRA_DC:         chroma_cand[3] = INTRA_ANGULAR_34; break;
177
  default:
178
    // use defaults from above
179
    break;
180
  }
181
}
182
#endif
183
184
185
int get_intra_scan_idx(int log2TrafoSize, enum IntraPredMode intraPredMode, int cIdx,
186
                       const seq_parameter_set* sps)
187
0
{
188
0
  if (log2TrafoSize==2 ||
189
0
      (log2TrafoSize==3 && (cIdx==0 ||
190
0
                            sps->ChromaArrayType==CHROMA_444))) {
191
0
    /**/ if (intraPredMode >=  6 && intraPredMode <= 14) return 2;
192
0
    else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
193
0
    else return 0;
194
0
  }
195
0
  else { return 0; }
196
0
}
197
198
199
int get_intra_scan_idx_luma(int log2TrafoSize, enum IntraPredMode intraPredMode)
200
0
{
201
0
  if (log2TrafoSize==2 || log2TrafoSize==3) {
202
0
    /**/ if (intraPredMode >=  6 && intraPredMode <= 14) return 2;
203
0
    else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
204
0
    else return 0;
205
0
  }
206
0
  else { return 0; }
207
0
}
208
209
int get_intra_scan_idx_chroma(int log2TrafoSize, enum IntraPredMode intraPredMode)
210
0
{
211
0
  if (log2TrafoSize==1 || log2TrafoSize==2) {
212
0
    /**/ if (intraPredMode >=  6 && intraPredMode <= 14) return 2;
213
0
    else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
214
0
    else return 0;
215
0
  }
216
0
  else { return 0; }
217
0
}
218
219
220
enum IntraPredMode lumaPredMode_to_chromaPredMode(enum IntraPredMode luma,
221
                                                  enum IntraChromaPredMode chroma)
222
0
{
223
0
  switch (chroma) {
224
0
  case INTRA_CHROMA_LIKE_LUMA:
225
0
    return luma;
226
227
0
  case INTRA_CHROMA_PLANAR_OR_34:
228
0
    if (luma==INTRA_PLANAR) return INTRA_ANGULAR_34;
229
0
    else                    return INTRA_PLANAR;
230
231
0
  case INTRA_CHROMA_ANGULAR_26_OR_34:
232
0
    if (luma==INTRA_ANGULAR_26) return INTRA_ANGULAR_34;
233
0
    else                        return INTRA_ANGULAR_26;
234
235
0
  case INTRA_CHROMA_ANGULAR_10_OR_34:
236
0
    if (luma==INTRA_ANGULAR_10) return INTRA_ANGULAR_34;
237
0
    else                        return INTRA_ANGULAR_10;
238
239
0
  case INTRA_CHROMA_DC_OR_34:
240
0
    if (luma==INTRA_DC)         return INTRA_ANGULAR_34;
241
0
    else                        return INTRA_DC;
242
0
  }
243
244
245
0
  assert(false);
246
0
  return INTRA_DC;
247
0
}
248
249
250
251
252
// (8.4.4.2.2)
253
template <class pixel_t>
254
void fill_border_samples(de265_image* img,
255
                         int xB,int yB,  // in component specific resolution
256
                         int nT, int cIdx,
257
                         pixel_t* out_border)
258
0
{
259
0
  intra_border_computer<pixel_t> c;
260
0
  c.init(out_border, img, nT, cIdx, xB, yB);
261
0
  c.preproc();
262
0
  c.fill_from_image();
263
0
  c.reference_sample_substitution();
264
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*)
265
266
267
const int intraPredAngle_table[1+34] =
268
  { 0, 0,32,26,21,17,13, 9, 5, 2, 0,-2,-5,-9,-13,-17,-21,-26,
269
    -32,-26,-21,-17,-13,-9,-5,-2,0,2,5,9,13,17,21,26,32 };
270
271
const int invAngle_table[25-10] =
272
  { -4096,-1638,-910,-630,-482,-390,-315,-256,
273
    -315,-390,-482,-630,-910,-1638,-4096 };
274
275
276
template <class pixel_t>
277
void decode_intra_prediction_internal(de265_image* img,
278
                                      int xB0,int yB0,
279
                                      enum IntraPredMode intraPredMode,
280
                                      pixel_t* dst, int dstStride,
281
                                      int nT, int cIdx)
282
0
{
283
0
  pixel_t  border_pixels_mem[4*MAX_INTRA_PRED_BLOCK_SIZE+1];
284
0
  pixel_t* border_pixels = &border_pixels_mem[2*MAX_INTRA_PRED_BLOCK_SIZE];
285
286
0
  fill_border_samples(img, xB0,yB0, nT, cIdx, border_pixels);
287
288
0
  if (img->get_sps().range_extension.intra_smoothing_disabled_flag == 0 &&
289
0
      (cIdx==0 || img->get_sps().ChromaArrayType==CHROMA_444))
290
0
    {
291
0
      intra_prediction_sample_filtering(img->get_sps(), border_pixels, nT, cIdx, intraPredMode);
292
0
    }
293
294
295
0
  switch (intraPredMode) {
296
0
  case INTRA_PLANAR:
297
0
    intra_prediction_planar(dst,dstStride, nT,cIdx, border_pixels);
298
0
    break;
299
0
  case INTRA_DC:
300
0
    intra_prediction_DC(dst,dstStride, nT,cIdx, border_pixels);
301
0
    break;
302
0
  default:
303
0
    {
304
0
      int bit_depth = img->get_bit_depth(cIdx);
305
0
      bool disableIntraBoundaryFilter =
306
0
        (img->get_sps().range_extension.implicit_rdpcm_enabled_flag &&
307
0
         img->get_cu_transquant_bypass(xB0,yB0));
308
309
0
      intra_prediction_angular(dst,dstStride, bit_depth,disableIntraBoundaryFilter,
310
0
                               xB0,yB0,intraPredMode,nT,cIdx, border_pixels);
311
0
    }
312
0
    break;
313
0
  }
314
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)
315
316
317
// (8.4.4.2.1)
318
void decode_intra_prediction(de265_image* img,
319
                             int xB0,int yB0,
320
                             enum IntraPredMode intraPredMode,
321
                             int nT, int cIdx)
322
0
{
323
0
  logtrace(LogIntraPred,"decode_intra_prediction xy0:%d/%d mode=%d nT=%d, cIdx=%d\n",
324
0
           xB0,yB0, intraPredMode, nT,cIdx);
325
  /*
326
    printf("decode_intra_prediction xy0:%d/%d mode=%d nT=%d, cIdx=%d\n",
327
    xB0,yB0, intraPredMode, nT,cIdx);
328
  */
329
330
0
  if (img->high_bit_depth(cIdx)) {
331
0
    decode_intra_prediction_internal<uint16_t>(img,xB0,yB0, intraPredMode,
332
0
                                               img->get_image_plane_at_pos_NEW<uint16_t>(cIdx,xB0,yB0),
333
0
                                               img->get_image_stride(cIdx),
334
0
                                               nT,cIdx);
335
0
  }
336
0
  else {
337
0
    decode_intra_prediction_internal<uint8_t>(img,xB0,yB0, intraPredMode,
338
0
                                              img->get_image_plane_at_pos_NEW<uint8_t>(cIdx,xB0,yB0),
339
0
                                              img->get_image_stride(cIdx),
340
0
                                              nT,cIdx);
341
0
  }
342
0
}
343
344
345
// TODO: remove this
346
template <> void decode_intra_prediction<uint8_t>(de265_image* img,
347
                                                  int xB0,int yB0,
348
                                                  enum IntraPredMode intraPredMode,
349
                                                  uint8_t* dst, int nT, int cIdx)
350
0
{
351
0
    decode_intra_prediction_internal<uint8_t>(img,xB0,yB0, intraPredMode,
352
0
                                              dst,nT,
353
0
                                              nT,cIdx);
354
0
}
355
356
357
// TODO: remove this
358
template <> void decode_intra_prediction<uint16_t>(de265_image* img,
359
                                                   int xB0,int yB0,
360
                                                   enum IntraPredMode intraPredMode,
361
                                                   uint16_t* dst, int nT, int cIdx)
362
0
{
363
0
  decode_intra_prediction_internal<uint16_t>(img,xB0,yB0, intraPredMode,
364
0
                                             dst,nT,
365
0
                                             nT,cIdx);
366
0
}