Coverage Report

Created: 2026-09-14 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libde265/libde265/image.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 "image.h"
22
#include "decctx.h"
23
24
#include <atomic>
25
26
#include <stdlib.h>
27
#include <string.h>
28
#include <assert.h>
29
30
#include <limits>
31
32
33
#ifdef HAVE_MALLOC_H
34
#include <malloc.h>
35
#endif
36
37
#ifdef HAVE_SSE4_1
38
// SSE code processes 128bit per iteration and thus might read more data
39
// than is later actually used.
40
133k
#define MEMORY_PADDING  16
41
#else
42
#define MEMORY_PADDING  0
43
#endif
44
45
37.0k
#define STANDARD_ALIGNMENT 16
46
47
#if defined(__MINGW32__)
48
#define ALLOC_ALIGNED(alignment, size)         __mingw_aligned_malloc((size), (alignment))
49
#define FREE_ALIGNED(mem)                      __mingw_aligned_free((mem))
50
#elif defined(_MSC_VER)
51
#define ALLOC_ALIGNED(alignment, size)         _aligned_malloc((size), (alignment))
52
#define FREE_ALIGNED(mem)                      _aligned_free((mem))
53
#elif defined(HAVE_POSIX_MEMALIGN)
54
105k
static inline void *ALLOC_ALIGNED(size_t alignment, size_t size) {
55
105k
    void *mem = nullptr;
56
105k
    if (posix_memalign(&mem, alignment, size) != 0) {
57
0
        return nullptr;
58
0
    }
59
105k
    return mem;
60
105k
};
61
105k
#define FREE_ALIGNED(mem)                      free((mem))
62
#else
63
#define ALLOC_ALIGNED(alignment, size)      memalign((alignment), (size))
64
#define FREE_ALIGNED(mem)                   free((mem))
65
#endif
66
67
105k
#define ALLOC_ALIGNED_16(size)              ALLOC_ALIGNED(16, size)
68
69
LIBDE265_API void* de265_alloc_image_plane(struct de265_image* img, int cIdx,
70
                                           void* inputdata, int inputstride, void *userdata)
71
0
{
72
0
  int alignment = STANDARD_ALIGNMENT;
73
0
  uint32_t stride = (img->get_width(cIdx) + alignment-1) / alignment * alignment;
74
0
  uint32_t height = img->get_height(cIdx);
75
76
  // size computed in size_t: stride*height can exceed UINT32_MAX for large planes
77
0
  uint8_t* p = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(stride) * height + MEMORY_PADDING));
78
79
0
  if (p==nullptr) { return nullptr; }
80
81
0
  img->set_image_plane(cIdx, p, stride, userdata);
82
83
  // copy input data if provided
84
85
0
  if (inputdata != nullptr) {
86
0
    if (inputstride == static_cast<int>(stride)) {
87
0
      memcpy(p, inputdata, static_cast<size_t>(stride) * height);
88
0
    }
89
0
    else {
90
0
      for (uint32_t y=0;y<height;y++) {
91
0
        memcpy(p + static_cast<size_t>(y) * stride,
92
0
               static_cast<char*>(inputdata) + static_cast<size_t>(inputstride) * y,
93
0
               inputstride);
94
0
      }
95
0
    }
96
0
  }
97
98
0
  return p;
99
0
}
100
101
102
LIBDE265_API void de265_free_image_plane(struct de265_image* img, int cIdx)
103
0
{
104
0
  uint8_t* p = img->get_image_plane(cIdx);
105
0
  assert(p);
106
0
  FREE_ALIGNED(p);
107
0
}
108
109
110
static int  de265_image_get_buffer(de265_decoder_context* ctx,
111
                                   de265_image_spec* spec, de265_image* img, void* userdata)
112
37.0k
{
113
37.0k
  const uint32_t rawChromaWidth  = spec->width  / img->SubWidthC;
114
37.0k
  const uint32_t rawChromaHeight = spec->height / img->SubHeightC;
115
116
37.0k
  uint32_t luma_stride   = (spec->width    + spec->alignment-1) / spec->alignment * spec->alignment;
117
37.0k
  uint32_t chroma_stride = (rawChromaWidth + spec->alignment-1) / spec->alignment * spec->alignment;
118
119
37.0k
  assert(img->BitDepth_Y >= 8 && img->BitDepth_Y <= 16);
120
37.0k
  assert(img->BitDepth_C >= 8 && img->BitDepth_C <= 16);
121
122
37.0k
  uint32_t luma_bpl   = luma_stride   * ((img->BitDepth_Y+7)/8);
123
37.0k
  uint32_t chroma_bpl = chroma_stride * ((img->BitDepth_C+7)/8);
124
125
37.0k
  uint32_t luma_height   = spec->height;
126
37.0k
  uint32_t chroma_height = rawChromaHeight;
127
128
37.0k
  bool alloc_failed = false;
129
130
  // Compute the plane sizes in size_t. Each operand fits in uint32_t, but the
131
  // height * bytes-per-line product can exceed UINT32_MAX for large frames, so
132
  // the multiplication must be done in 64 bits. Computing it in 32 bits wraps
133
  // the allocation size to a small value while fill_image() later writes the
134
  // real (size_t) size -> heap buffer overflow (GHSA-vv8h-932h-7r86).
135
37.0k
  uint8_t* p[3] = { nullptr,nullptr,nullptr };
136
37.0k
  p[0] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(luma_height) * luma_bpl + MEMORY_PADDING));
137
37.0k
  if (p[0]==nullptr) { alloc_failed=true; }
138
139
37.0k
  if (img->get_chroma_format() != de265_chroma_mono) {
140
34.3k
    p[1] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(chroma_height) * chroma_bpl + MEMORY_PADDING));
141
34.3k
    p[2] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(chroma_height) * chroma_bpl + MEMORY_PADDING));
142
143
34.3k
    if (p[1]==nullptr || p[2]==nullptr) { alloc_failed=true; }
144
34.3k
  }
145
2.66k
  else {
146
2.66k
    p[1] = nullptr;
147
2.66k
    p[2] = nullptr;
148
2.66k
    chroma_stride = 0;
149
2.66k
  }
150
151
37.0k
  if (alloc_failed) {
152
0
    for (int i=0;i<3;i++)
153
0
      if (p[i]) {
154
0
        FREE_ALIGNED(p[i]);
155
0
      }
156
157
0
    return 0;
158
0
  }
159
160
37.0k
  img->set_image_plane(0, p[0], luma_stride, nullptr);
161
37.0k
  img->set_image_plane(1, p[1], chroma_stride, nullptr);
162
37.0k
  img->set_image_plane(2, p[2], chroma_stride, nullptr);
163
164
37.0k
  img->fill_image(0,0,0);
165
166
37.0k
  return 1;
167
37.0k
}
168
169
static void de265_image_release_buffer(de265_decoder_context* ctx,
170
                                       de265_image* img, void* userdata)
171
37.0k
{
172
148k
  for (int i=0;i<3;i++) {
173
111k
    uint8_t* p = img->get_image_plane(i);
174
111k
    if (p) {
175
105k
      FREE_ALIGNED(p);
176
105k
    }
177
111k
  }
178
37.0k
}
179
180
181
de265_image_allocation de265_image::default_image_allocation = {
182
  de265_image_get_buffer,
183
  de265_image_release_buffer
184
};
185
186
187
void de265_image::set_image_plane(int cIdx, uint8_t* mem, ptrdiff_t stride, void *userdata)
188
111k
{
189
111k
  pixels[cIdx] = mem;
190
111k
  plane_user_data[cIdx] = userdata;
191
192
111k
  if (cIdx==0) { this->stride        = stride; }
193
74.0k
  else         { this->chroma_stride = stride; }
194
111k
}
195
196
197
39.9k
de265_image::de265_image() = default;
198
199
200
de265_error de265_image::alloc_image(int w,int h, enum de265_chroma c,
201
                                     std::shared_ptr<const seq_parameter_set> sps, bool allocMetadata,
202
                                     decoder_context* dctx,
203
                                     //encoder_context* ectx,
204
                                     de265_PTS pts, void* user_data,
205
                                     bool useCustomAllocFunc)
206
37.0k
{
207
  //if (allocMetadata) { assert(sps); }
208
37.0k
  if (allocMetadata) { assert(sps); }
209
210
37.0k
  if (sps) { this->sps = sps; }
211
212
37.0k
  release(); /* TODO: review code for efficient allocation when arrays are already
213
                allocated to the requested size. Without the release, the old image-data
214
                will not be freed. */
215
216
37.0k
  static std::atomic<uint32_t> s_next_image_ID(0);
217
37.0k
  ID = s_next_image_ID++;
218
37.0k
  removed_at_picture_id = std::numeric_limits<uint32_t>::max();
219
220
37.0k
  decctx = dctx;
221
  //encctx = ectx;
222
223
  // --- allocate image buffer ---
224
225
37.0k
  chroma_format= c;
226
227
37.0k
  width = w;
228
37.0k
  height = h;
229
37.0k
  chroma_width = w;
230
37.0k
  chroma_height= h;
231
232
37.0k
  this->user_data = user_data;
233
37.0k
  this->pts = pts;
234
235
37.0k
  de265_image_spec spec;
236
237
37.0k
  uint8_t WinUnitX, WinUnitY;
238
239
37.0k
  switch (chroma_format) {
240
2.66k
    case de265_chroma_mono: WinUnitX=1; WinUnitY=1; break;
241
12.1k
    case de265_chroma_420:  WinUnitX=2; WinUnitY=2; break;
242
1.59k
    case de265_chroma_422:  WinUnitX=2; WinUnitY=1; break;
243
20.6k
    case de265_chroma_444:  WinUnitX=1; WinUnitY=1; break;
244
0
    default:
245
0
      assert(0);
246
0
      WinUnitX = WinUnitY = 0;
247
37.0k
  }
248
249
37.0k
  switch (chroma_format) {
250
12.1k
  case de265_chroma_420:
251
12.1k
    spec.format = de265_image_format_YUV420P8;
252
12.1k
    chroma_width  = (chroma_width +1)/2;
253
12.1k
    chroma_height = (chroma_height+1)/2;
254
12.1k
    SubWidthC  = 2;
255
12.1k
    SubHeightC = 2;
256
12.1k
    break;
257
258
1.59k
  case de265_chroma_422:
259
1.59k
    spec.format = de265_image_format_YUV422P8;
260
1.59k
    chroma_width = (chroma_width+1)/2;
261
1.59k
    SubWidthC  = 2;
262
1.59k
    SubHeightC = 1;
263
1.59k
    break;
264
265
20.6k
  case de265_chroma_444:
266
20.6k
    spec.format = de265_image_format_YUV444P8;
267
20.6k
    SubWidthC  = 1;
268
20.6k
    SubHeightC = 1;
269
20.6k
    break;
270
271
2.66k
  case de265_chroma_mono:
272
2.66k
    spec.format = de265_image_format_mono8;
273
2.66k
    chroma_width = 0;
274
2.66k
    chroma_height= 0;
275
2.66k
    SubWidthC  = 1;
276
2.66k
    SubHeightC = 1;
277
2.66k
    break;
278
279
0
  default:
280
0
    assert(false);
281
0
    break;
282
37.0k
  }
283
284
37.0k
  if (chroma_format != de265_chroma_mono && sps) {
285
34.3k
    assert(sps->SubWidthC  == SubWidthC);
286
34.3k
    assert(sps->SubHeightC == SubHeightC);
287
34.3k
  }
288
289
37.0k
  spec.width  = w;
290
37.0k
  spec.height = h;
291
37.0k
  spec.alignment = STANDARD_ALIGNMENT;
292
293
294
  // conformance window cropping
295
296
37.0k
  int left   = sps ? sps->conf_win_left_offset : 0;
297
37.0k
  int right  = sps ? sps->conf_win_right_offset : 0;
298
37.0k
  int top    = sps ? sps->conf_win_top_offset : 0;
299
37.0k
  int bottom = sps ? sps->conf_win_bottom_offset : 0;
300
301
37.0k
  if ((left+right)*WinUnitX >= width) {
302
0
    return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
303
0
  }
304
305
37.0k
  if ((top+bottom)*WinUnitY >= height) {
306
0
    return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
307
0
  }
308
309
37.0k
  width_confwin = width - (left+right)*WinUnitX;
310
37.0k
  height_confwin= height- (top+bottom)*WinUnitY;
311
37.0k
  chroma_width_confwin = chroma_width -left-right;
312
37.0k
  chroma_height_confwin= chroma_height-top-bottom;
313
314
37.0k
  spec.crop_left  = left *WinUnitX;
315
37.0k
  spec.crop_right = right*WinUnitX;
316
37.0k
  spec.crop_top   = top   *WinUnitY;
317
37.0k
  spec.crop_bottom= bottom*WinUnitY;
318
319
37.0k
  spec.visible_width = width_confwin;
320
37.0k
  spec.visible_height= height_confwin;
321
322
323
37.0k
  BitDepth_Y = (sps==nullptr) ? 8 : sps->BitDepth_Y;
324
37.0k
  BitDepth_C = (sps==nullptr) ? 8 : sps->BitDepth_C;
325
326
37.0k
  bpp_shift[0] = (BitDepth_Y <= 8) ? 0 : 1;
327
37.0k
  bpp_shift[1] = (BitDepth_C <= 8) ? 0 : 1;
328
37.0k
  bpp_shift[2] = bpp_shift[1];
329
330
331
  // allocate memory and set conformance window pointers
332
333
37.0k
  void* alloc_userdata = nullptr;
334
37.0k
  if (decctx) alloc_userdata = decctx->param_image_allocation_userdata;
335
  // if (encctx) alloc_userdata = encctx->param_image_allocation_userdata; // actually not needed
336
337
  /*
338
  if (encctx && useCustomAllocFunc) {
339
    encoder_image_release_func = encctx->release_func;
340
341
    // if we do not provide a release function, use our own
342
343
    if (encoder_image_release_func == nullptr) {
344
      image_allocation_functions = de265_image::default_image_allocation;
345
    }
346
    else {
347
      image_allocation_functions.get_buffer     = nullptr;
348
      image_allocation_functions.release_buffer = nullptr;
349
    }
350
  }
351
37.0k
  else*/ if (decctx && useCustomAllocFunc) {
352
14.5k
    image_allocation_functions = decctx->param_image_allocation_functions;
353
14.5k
  }
354
22.5k
  else {
355
22.5k
    image_allocation_functions = de265_image::default_image_allocation;
356
22.5k
  }
357
358
37.0k
  bool mem_alloc_success = true;
359
360
37.0k
  if (image_allocation_functions.get_buffer != nullptr) {
361
37.0k
    mem_alloc_success = image_allocation_functions.get_buffer(decctx, &spec, this,
362
37.0k
                                                              alloc_userdata);
363
364
37.0k
    pixels_confwin[0] = pixels[0] + left*WinUnitX + top*WinUnitY*stride;
365
366
37.0k
    if (chroma_format != de265_chroma_mono) {
367
34.3k
      pixels_confwin[1] = pixels[1] + left + top*chroma_stride;
368
34.3k
      pixels_confwin[2] = pixels[2] + left + top*chroma_stride;
369
34.3k
    }
370
2.65k
    else {
371
2.65k
      pixels_confwin[1] = nullptr;
372
2.65k
      pixels_confwin[2] = nullptr;
373
2.65k
    }
374
375
    // check for memory shortage
376
377
37.0k
    if (!mem_alloc_success)
378
0
      {
379
0
        return DE265_ERROR_OUT_OF_MEMORY;
380
0
      }
381
37.0k
  }
382
383
  //alloc_functions = *allocfunc;
384
  //alloc_userdata  = userdata;
385
386
  // --- allocate decoding info arrays ---
387
388
37.0k
  if (allocMetadata) {
389
    // intra pred mode
390
391
25.1k
    mem_alloc_success &= intraPredMode.alloc(sps->PicWidthInMinPUs, sps->PicHeightInMinPUs,
392
25.1k
                                             sps->Log2MinPUSize);
393
394
25.1k
    mem_alloc_success &= intraPredModeC.alloc(sps->PicWidthInMinPUs, sps->PicHeightInMinPUs,
395
25.1k
                                              sps->Log2MinPUSize);
396
397
    // cb info
398
399
25.1k
    mem_alloc_success &= cb_info.alloc(sps->PicWidthInMinCbsY, sps->PicHeightInMinCbsY,
400
25.1k
                                       sps->Log2MinCbSizeY);
401
402
    // pb info
403
404
25.1k
    int puWidth  = sps->PicWidthInMinCbsY  << (sps->Log2MinCbSizeY -2);
405
25.1k
    int puHeight = sps->PicHeightInMinCbsY << (sps->Log2MinCbSizeY -2);
406
407
25.1k
    mem_alloc_success &= pb_info.alloc(puWidth,puHeight, 2);
408
409
410
    // tu info
411
412
25.1k
    mem_alloc_success &= tu_info.alloc(sps->PicWidthInTbsY, sps->PicHeightInTbsY,
413
25.1k
                                       sps->Log2MinTrafoSize);
414
415
    // deblk info
416
417
25.1k
    int deblk_w = (sps->pic_width_in_luma_samples +3)/4;
418
25.1k
    int deblk_h = (sps->pic_height_in_luma_samples+3)/4;
419
420
25.1k
    mem_alloc_success &= deblk_info.alloc(deblk_w, deblk_h, 2);
421
422
    // CTB info
423
424
25.1k
    if (ctb_info.width_in_units  != sps->PicWidthInCtbsY  ||
425
51
        ctb_info.height_in_units != sps->PicHeightInCtbsY ||
426
51
        ctb_info.log2unitSize    != sps->Log2CtbSizeY)
427
25.0k
      {
428
25.0k
        delete[] ctb_progress;
429
430
25.0k
        mem_alloc_success &= ctb_info.alloc(sps->PicWidthInCtbsY, sps->PicHeightInCtbsY,
431
25.0k
                                            sps->Log2CtbSizeY);
432
433
25.0k
        ctb_progress = new de265_progress_lock[ ctb_info.data_size ];
434
25.0k
      }
435
436
437
    // check for memory shortage
438
439
25.1k
    if (!mem_alloc_success)
440
0
      {
441
0
        return DE265_ERROR_OUT_OF_MEMORY;
442
0
      }
443
25.1k
  }
444
445
37.0k
  return DE265_OK;
446
37.0k
}
447
448
449
de265_image::~de265_image()
450
39.9k
{
451
39.9k
  release();
452
453
  // free progress locks
454
455
39.9k
  if (ctb_progress) {
456
25.0k
    delete[] ctb_progress;
457
25.0k
  }
458
39.9k
}
459
460
461
void de265_image::release()
462
77.0k
{
463
  // free image memory
464
465
77.0k
  if (pixels[0])
466
37.0k
    {
467
      /*
468
      if (encoder_image_release_func != nullptr) {
469
        encoder_image_release_func(encctx, this,
470
                                   encctx->param_image_allocation_userdata);
471
      }
472
37.0k
      else*/ {
473
37.0k
        image_allocation_functions.release_buffer(decctx, this,
474
37.0k
                                                  decctx ?
475
37.0k
                                                  decctx->param_image_allocation_userdata :
476
37.0k
                                                  nullptr);
477
37.0k
      }
478
479
148k
      for (int i=0;i<3;i++)
480
111k
        {
481
111k
          pixels[i] = nullptr;
482
111k
          pixels_confwin[i] = nullptr;
483
111k
        }
484
37.0k
    }
485
486
  // free slices
487
488
92.6k
  for (size_t i=0;i<slices.size();i++) {
489
15.5k
    delete slices[i];
490
15.5k
  }
491
77.0k
  slices.clear();
492
77.0k
}
493
494
495
void de265_image::fill_plane(int channel, int value)
496
133k
{
497
133k
  int bytes_per_pixel = get_bytes_per_pixel(channel);
498
133k
  assert(value >= 0); // needed for the shift operation in the check below
499
500
  // Each plane is allocated with MEMORY_PADDING trailing bytes for safe SSE overread; the
501
  // memsets below cover that padding too so it never contains uninitialized heap data.
502
133k
  const size_t plane_bytes =
503
133k
      (channel == 0 ? static_cast<size_t>(stride) * height
504
133k
                    : static_cast<size_t>(chroma_stride) * chroma_height)
505
133k
      * bytes_per_pixel;
506
507
133k
  if (bytes_per_pixel == 1) {
508
77.9k
    memset(pixels[channel], value, plane_bytes + MEMORY_PADDING);
509
77.9k
  }
510
55.5k
  else if ((value >> 8) == (value & 0xFF)) {
511
42.1k
    assert(bytes_per_pixel == 2);
512
513
    // if we fill the same byte value to all bytes, we can still use memset()
514
42.1k
    memset(pixels[channel], 0, plane_bytes + MEMORY_PADDING);
515
42.1k
  }
516
13.3k
  else {
517
13.3k
    assert(bytes_per_pixel == 2);
518
13.3k
    uint16_t v = value;
519
520
13.3k
    if (channel==0) {
521
      // copy value into first row
522
2.71M
      for (int x = 0; x < width; x++) {
523
2.70M
        *reinterpret_cast<uint16_t*>(&pixels[channel][2 * x]) = v;
524
2.70M
      }
525
526
      // copy first row into remaining rows
527
641k
      for (int y = 1; y < height; y++) {
528
636k
        memcpy(pixels[channel] + y * stride * 2, pixels[channel], chroma_width * 2);
529
636k
      }
530
5.49k
    }
531
7.85k
    else {
532
      // copy value into first row
533
1.72M
      for (int x = 0; x < chroma_width; x++) {
534
1.71M
        *reinterpret_cast<uint16_t*>(&pixels[channel][2 * x]) = v;
535
1.71M
      }
536
537
      // copy first row into remaining rows
538
1.00M
      for (int y = 1; y < chroma_height; y++) {
539
999k
        memcpy(pixels[channel] + y * chroma_stride * 2, pixels[channel], chroma_width * 2);
540
999k
      }
541
7.85k
    }
542
543
13.3k
#if MEMORY_PADDING > 0
544
13.3k
    memset(pixels[channel] + plane_bytes, 0, MEMORY_PADDING);
545
13.3k
#endif
546
13.3k
  }
547
133k
}
548
549
550
void de265_image::fill_image(int y,int cb,int cr)
551
47.1k
{
552
47.1k
  if (pixels[0]) {
553
47.1k
    fill_plane(0, y);
554
47.1k
  }
555
556
47.1k
  if (pixels[1]) {
557
43.1k
    fill_plane(1, cb);
558
43.1k
  }
559
560
47.1k
  if (pixels[2]) {
561
43.1k
    fill_plane(2, cr);
562
43.1k
  }
563
47.1k
}
564
565
566
de265_error de265_image::copy_image(const de265_image* src)
567
0
{
568
  /* TODO: actually, since we allocate the image only for internal purpose, we
569
     do not have to call the external allocation routines for this. However, then
570
     we have to track for each image how to release it again.
571
     Another option would be to safe the copied data not in an de265_image at all.
572
  */
573
574
0
  de265_error err = alloc_image(src->width, src->height, src->chroma_format, src->sps, false,
575
0
                                src->decctx, /*src->encctx,*/ src->pts, src->user_data, false);
576
0
  if (err != DE265_OK) {
577
0
    return err;
578
0
  }
579
580
0
  copy_lines_from(src, 0, src->height);
581
582
0
  return err;
583
0
}
584
585
586
// end = last line + 1
587
void de265_image::copy_lines_from(const de265_image* src, int first, int end)
588
56.8k
{
589
56.8k
  if (end > src->height) end=src->height;
590
591
56.8k
  assert(first % 2 == 0);
592
56.8k
  assert(end   % 2 == 0);
593
594
56.8k
  int luma_bpp   = (sps->BitDepth_Y+7)/8;
595
56.8k
  int chroma_bpp = (sps->BitDepth_C+7)/8;
596
597
56.8k
  if (src->stride == stride) {
598
56.8k
    memcpy(pixels[0]      + first*stride * luma_bpp,
599
56.8k
           src->pixels[0] + first*src->stride * luma_bpp,
600
56.8k
           (end-first)*stride * luma_bpp);
601
56.8k
  }
602
0
  else {
603
0
    for (int yp=first;yp<end;yp++) {
604
0
      memcpy(pixels[0]+yp*stride * luma_bpp,
605
0
             src->pixels[0]+yp*src->stride * luma_bpp,
606
0
             src->width * luma_bpp);
607
0
    }
608
0
  }
609
610
56.8k
  int first_chroma = first / src->SubHeightC;
611
56.8k
  int end_chroma   = end   / src->SubHeightC;
612
613
56.8k
  if (src->chroma_format != de265_chroma_mono) {
614
50.3k
    if (src->chroma_stride == chroma_stride) {
615
50.3k
      memcpy(pixels[1]      + first_chroma*chroma_stride * chroma_bpp,
616
50.3k
             src->pixels[1] + first_chroma*chroma_stride * chroma_bpp,
617
50.3k
             (end_chroma-first_chroma) * chroma_stride * chroma_bpp);
618
50.3k
      memcpy(pixels[2]      + first_chroma*chroma_stride * chroma_bpp,
619
50.3k
             src->pixels[2] + first_chroma*chroma_stride * chroma_bpp,
620
50.3k
             (end_chroma-first_chroma) * chroma_stride * chroma_bpp);
621
50.3k
    }
622
0
    else {
623
0
      for (int y=first_chroma;y<end_chroma;y++) {
624
0
        memcpy(pixels[1]+y*chroma_stride * chroma_bpp,
625
0
               src->pixels[1]+y*src->chroma_stride * chroma_bpp,
626
0
               src->chroma_width * chroma_bpp);
627
0
        memcpy(pixels[2]+y*chroma_stride * chroma_bpp,
628
0
               src->pixels[2]+y*src->chroma_stride * chroma_bpp,
629
0
               src->chroma_width * chroma_bpp);
630
0
      }
631
0
    }
632
50.3k
  }
633
56.8k
}
634
635
636
void de265_image::exchange_pixel_data_with(de265_image& b)
637
11.9k
{
638
47.7k
  for (int i=0;i<3;i++) {
639
35.8k
    std::swap(pixels[i], b.pixels[i]);
640
35.8k
    std::swap(pixels_confwin[i], b.pixels_confwin[i]);
641
35.8k
    std::swap(plane_user_data[i], b.plane_user_data[i]);
642
35.8k
  }
643
644
11.9k
  std::swap(stride, b.stride);
645
11.9k
  std::swap(chroma_stride, b.chroma_stride);
646
11.9k
  std::swap(image_allocation_functions, b.image_allocation_functions);
647
11.9k
}
648
649
650
void de265_image::thread_start(int nThreads)
651
40.1k
{
652
40.1k
  std::unique_lock<std::mutex> lock(mutex);
653
654
  //printf("nThreads before: %d %d\n",nThreadsQueued, nThreadsTotal);
655
656
40.1k
  nThreadsQueued += nThreads;
657
40.1k
  nThreadsTotal += nThreads;
658
659
  //printf("nThreads after: %d %d\n",nThreadsQueued, nThreadsTotal);
660
40.1k
}
661
662
void de265_image::thread_run(const thread_task* task)
663
217k
{
664
217k
  std::unique_lock<std::mutex> lock(mutex);
665
666
  //printf("run thread %s\n", task->name().c_str());
667
668
217k
  nThreadsQueued--;
669
217k
  nThreadsRunning++;
670
217k
}
671
672
void de265_image::thread_blocks()
673
0
{
674
0
  std::unique_lock<std::mutex> lock(mutex);
675
676
0
  nThreadsRunning--;
677
0
  nThreadsBlocked++;
678
0
}
679
680
void de265_image::thread_unblocks()
681
0
{
682
0
  std::unique_lock<std::mutex> lock(mutex);
683
684
0
  nThreadsBlocked--;
685
0
  nThreadsRunning++;
686
0
}
687
688
void de265_image::thread_finishes(const thread_task* task)
689
217k
{
690
  //printf("finish thread %s\n", task->name().c_str());
691
692
217k
  std::unique_lock<std::mutex> lock(mutex);
693
694
217k
  nThreadsRunning--;
695
217k
  nThreadsFinished++;
696
217k
  assert(nThreadsRunning >= 0);
697
698
217k
  if (nThreadsFinished==nThreadsTotal) {
699
20.0k
    finished_cond.notify_all();
700
20.0k
  }
701
217k
}
702
703
void de265_image::wait_for_progress(thread_task* task, int ctbx,int ctby, int progress)
704
504k
{
705
504k
  const int ctbW = sps->PicWidthInCtbsY;
706
707
504k
  wait_for_progress(task, ctbx + ctbW*ctby, progress);
708
504k
}
709
710
void de265_image::wait_for_progress(thread_task* task, int ctbAddrRS, int progress)
711
504k
{
712
504k
  if (task==nullptr) { return; }
713
714
504k
  de265_progress_lock* progresslock = &ctb_progress[ctbAddrRS];
715
504k
  if (progresslock->get_progress() < progress) {
716
0
    thread_blocks();
717
718
0
    assert(task!=nullptr);
719
0
    task->state = thread_task::Blocked;
720
721
    /* TODO: check whether we are the first blocked task in the list.
722
       If we are, we have to conceal input errors.
723
       Simplest concealment: do not block.
724
    */
725
726
0
    progresslock->wait_for_progress(progress);
727
0
    task->state = thread_task::Running;
728
0
    thread_unblocks();
729
0
  }
730
504k
}
731
732
733
void de265_image::wait_for_completion()
734
31.9k
{
735
31.9k
  std::unique_lock<std::mutex> lock(mutex);
736
737
51.9k
  while (nThreadsFinished!=nThreadsTotal) {
738
19.9k
    finished_cond.wait(lock);
739
19.9k
  }
740
31.9k
}
741
742
bool de265_image::debug_is_completed() const
743
0
{
744
0
  return nThreadsFinished==nThreadsTotal;
745
0
}
746
747
748
749
void de265_image::clear_metadata()
750
15.0k
{
751
  // TODO: maybe we could avoid the memset by ensuring that all data is written to
752
  // during decoding (especially log2CbSize), but it is unlikely to be faster than the memset.
753
754
15.0k
  cb_info.clear();
755
15.0k
  intraPredMode.clear();
756
  //tu_info.clear();  // done on the fly
757
15.0k
  ctb_info.clear();
758
15.0k
  deblk_info.clear();
759
760
  // --- reset CTB progresses ---
761
762
989k
  for (int i=0;i<ctb_info.data_size;i++) {
763
974k
    ctb_progress[i].reset(CTB_PROGRESS_NONE);
764
974k
  }
765
15.0k
}
766
767
768
void de265_image::set_mv_info(int x,int y, int nPbW,int nPbH, const PBMotion& mv)
769
1.69M
{
770
1.69M
  int log2PuSize = 2;
771
772
1.69M
  int xPu = x >> log2PuSize;
773
1.69M
  int yPu = y >> log2PuSize;
774
1.69M
  int wPu = nPbW >> log2PuSize;
775
1.69M
  int hPu = nPbH >> log2PuSize;
776
777
1.69M
  int stride = pb_info.width_in_units;
778
779
5.48M
  for (int pby=0;pby<hPu;pby++)
780
17.0M
    for (int pbx=0;pbx<wPu;pbx++)
781
13.2M
      {
782
13.2M
        pb_info[ xPu+pbx + (yPu+pby)*stride ] = mv;
783
13.2M
      }
784
1.69M
}
785
786
787
bool de265_image::available_zscan(int xCurr,int yCurr, int xN,int yN) const
788
33.9M
{
789
33.9M
  if (xN<0 || yN<0) return false;
790
29.8M
  if (xN>=sps->pic_width_in_luma_samples ||
791
29.8M
      yN>=sps->pic_height_in_luma_samples) return false;
792
793
29.6M
  int minBlockAddrN = pps->scan->MinTbAddrZS[ (xN>>sps->Log2MinTrafoSize) +
794
29.6M
                                        (yN>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ];
795
29.6M
  int minBlockAddrCurr = pps->scan->MinTbAddrZS[ (xCurr>>sps->Log2MinTrafoSize) +
796
29.6M
                                           (yCurr>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ];
797
798
29.6M
  if (minBlockAddrN > minBlockAddrCurr) return false;
799
800
28.6M
  int xCurrCtb = xCurr >> sps->Log2CtbSizeY;
801
28.6M
  int yCurrCtb = yCurr >> sps->Log2CtbSizeY;
802
28.6M
  int xNCtb = xN >> sps->Log2CtbSizeY;
803
28.6M
  int yNCtb = yN >> sps->Log2CtbSizeY;
804
805
28.6M
  if (get_SliceAddrRS(xCurrCtb,yCurrCtb) !=
806
28.6M
      get_SliceAddrRS(xNCtb,   yNCtb)) {
807
15.5k
    return false;
808
15.5k
  }
809
810
28.6M
  if (pps->scan->TileIdRS[xCurrCtb + yCurrCtb*sps->PicWidthInCtbsY] !=
811
28.6M
      pps->scan->TileIdRS[xNCtb    + yNCtb   *sps->PicWidthInCtbsY]) {
812
41.5k
    return false;
813
41.5k
  }
814
815
28.6M
  return true;
816
28.6M
}
817
818
819
bool de265_image::available_pred_blk(int xC,int yC, int nCbS, int xP, int yP,
820
                                     int nPbW, int nPbH, int partIdx, int xN,int yN) const
821
6.11M
{
822
6.11M
  logtrace(LogMotion,"C:%d;%d P:%d;%d N:%d;%d size=%d;%d\n",xC,yC,xP,yP,xN,yN,nPbW,nPbH);
823
824
6.11M
  int sameCb = (xC <= xN && xN < xC+nCbS &&
825
1.76M
                yC <= yN && yN < yC+nCbS);
826
827
6.11M
  bool availableN;
828
829
6.11M
  if (!sameCb) {
830
5.81M
    availableN = available_zscan(xP,yP,xN,yN);
831
5.81M
  }
832
292k
  else {
833
292k
    availableN = !(nPbW<<1 == nCbS && nPbH<<1 == nCbS &&  // NxN
834
21.4k
                   partIdx==1 &&
835
6.56k
                   yN >= yC+nPbH && xN < xC+nPbW);  // xN/yN inside partIdx 2
836
292k
  }
837
838
6.11M
  if (availableN && get_pred_mode(xN,yN) == MODE_INTRA) {
839
155k
    availableN = false;
840
155k
  }
841
842
6.11M
  return availableN;
843
6.11M
}