Coverage Report

Created: 2026-11-12 07:35

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