Coverage Report

Created: 2026-10-28 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/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
0
#define MEMORY_PADDING  16
43
#else
44
#define MEMORY_PADDING  0
45
#endif
46
47
0
#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
0
static inline void *ALLOC_ALIGNED(size_t alignment, size_t size) {
57
0
    void *mem = nullptr;
58
0
    if (posix_memalign(&mem, alignment, size) != 0) {
59
0
        return nullptr;
60
0
    }
61
0
    return mem;
62
0
};
63
0
#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
0
#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
0
{
115
0
  const uint32_t rawChromaWidth  = spec->width  / img->SubWidthC;
116
0
  const uint32_t rawChromaHeight = spec->height / img->SubHeightC;
117
118
0
  uint32_t luma_stride   = (spec->width    + spec->alignment-1) / spec->alignment * spec->alignment;
119
0
  uint32_t chroma_stride = (rawChromaWidth + spec->alignment-1) / spec->alignment * spec->alignment;
120
121
0
  assert(img->BitDepth_Y >= 8 && img->BitDepth_Y <= 16);
122
0
  assert(img->BitDepth_C >= 8 && img->BitDepth_C <= 16);
123
124
0
  uint32_t luma_bpl   = luma_stride   * ((img->BitDepth_Y+7)/8);
125
0
  uint32_t chroma_bpl = chroma_stride * ((img->BitDepth_C+7)/8);
126
127
0
  uint32_t luma_height   = spec->height;
128
0
  uint32_t chroma_height = rawChromaHeight;
129
130
0
  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
0
  uint8_t* p[3] = { nullptr,nullptr,nullptr };
138
0
  p[0] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(luma_height) * luma_bpl + MEMORY_PADDING));
139
0
  if (p[0]==nullptr) { alloc_failed=true; }
140
141
0
  if (img->get_chroma_format() != de265_chroma_mono) {
142
0
    p[1] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(chroma_height) * chroma_bpl + MEMORY_PADDING));
143
0
    p[2] = static_cast<uint8_t*>(ALLOC_ALIGNED_16(static_cast<size_t>(chroma_height) * chroma_bpl + MEMORY_PADDING));
144
145
0
    if (p[1]==nullptr || p[2]==nullptr) { alloc_failed=true; }
146
0
  }
147
0
  else {
148
0
    p[1] = nullptr;
149
0
    p[2] = nullptr;
150
0
    chroma_stride = 0;
151
0
  }
152
153
0
  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
0
  img->set_image_plane(0, p[0], luma_stride, nullptr);
163
0
  img->set_image_plane(1, p[1], chroma_stride, nullptr);
164
0
  img->set_image_plane(2, p[2], chroma_stride, nullptr);
165
166
0
  img->fill_image(0,0,0);
167
168
0
  return 1;
169
0
}
170
171
static void de265_image_release_buffer(de265_decoder_context* ctx,
172
                                       de265_image* img, void* userdata)
173
0
{
174
0
  for (int i=0;i<3;i++) {
175
0
    uint8_t* p = img->get_image_plane(i);
176
0
    if (p) {
177
0
      FREE_ALIGNED(p);
178
0
    }
179
0
  }
180
0
}
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
0
{
191
0
  pixels[cIdx] = mem;
192
0
  plane_user_data[cIdx] = userdata;
193
194
0
  if (cIdx==0) { this->stride        = stride; }
195
0
  else         { this->chroma_stride = stride; }
196
0
}
197
198
199
0
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
0
{
209
  //if (allocMetadata) { assert(sps); }
210
0
  if (allocMetadata) { assert(sps); }
211
212
0
  if (sps) { this->sps = sps; }
213
214
0
  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
0
  static std::atomic<uint32_t> s_next_image_ID(0);
219
0
  ID = s_next_image_ID++;
220
0
  removed_at_picture_id = std::numeric_limits<uint32_t>::max();
221
222
0
  decctx = dctx;
223
  //encctx = ectx;
224
225
  // --- allocate image buffer ---
226
227
0
  chroma_format= c;
228
229
0
  width = w;
230
0
  height = h;
231
0
  chroma_width = w;
232
0
  chroma_height= h;
233
234
0
  this->user_data = user_data;
235
0
  this->pts = pts;
236
237
0
  de265_image_spec spec;
238
239
0
  uint8_t WinUnitX, WinUnitY;
240
241
0
  switch (chroma_format) {
242
0
    case de265_chroma_mono: WinUnitX=1; WinUnitY=1; break;
243
0
    case de265_chroma_420:  WinUnitX=2; WinUnitY=2; break;
244
0
    case de265_chroma_422:  WinUnitX=2; WinUnitY=1; break;
245
0
    case de265_chroma_444:  WinUnitX=1; WinUnitY=1; break;
246
0
    default:
247
0
      assert(0);
248
0
      WinUnitX = WinUnitY = 0;
249
0
  }
250
251
0
  switch (chroma_format) {
252
0
  case de265_chroma_420:
253
0
    spec.format = de265_image_format_YUV420P8;
254
0
    chroma_width  = (chroma_width +1)/2;
255
0
    chroma_height = (chroma_height+1)/2;
256
0
    SubWidthC  = 2;
257
0
    SubHeightC = 2;
258
0
    break;
259
260
0
  case de265_chroma_422:
261
0
    spec.format = de265_image_format_YUV422P8;
262
0
    chroma_width = (chroma_width+1)/2;
263
0
    SubWidthC  = 2;
264
0
    SubHeightC = 1;
265
0
    break;
266
267
0
  case de265_chroma_444:
268
0
    spec.format = de265_image_format_YUV444P8;
269
0
    SubWidthC  = 1;
270
0
    SubHeightC = 1;
271
0
    break;
272
273
0
  case de265_chroma_mono:
274
0
    spec.format = de265_image_format_mono8;
275
0
    chroma_width = 0;
276
0
    chroma_height= 0;
277
0
    SubWidthC  = 1;
278
0
    SubHeightC = 1;
279
0
    break;
280
281
0
  default:
282
0
    assert(false);
283
0
    break;
284
0
  }
285
286
0
  if (chroma_format != de265_chroma_mono && sps) {
287
0
    assert(sps->SubWidthC  == SubWidthC);
288
0
    assert(sps->SubHeightC == SubHeightC);
289
0
  }
290
291
0
  spec.width  = w;
292
0
  spec.height = h;
293
0
  spec.alignment = STANDARD_ALIGNMENT;
294
295
296
  // conformance window cropping
297
298
0
  int left   = sps ? sps->conf_win_left_offset : 0;
299
0
  int right  = sps ? sps->conf_win_right_offset : 0;
300
0
  int top    = sps ? sps->conf_win_top_offset : 0;
301
0
  int bottom = sps ? sps->conf_win_bottom_offset : 0;
302
303
0
  if ((left+right)*WinUnitX >= width) {
304
0
    return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
305
0
  }
306
307
0
  if ((top+bottom)*WinUnitY >= height) {
308
0
    return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
309
0
  }
310
311
0
  width_confwin = width - (left+right)*WinUnitX;
312
0
  height_confwin= height- (top+bottom)*WinUnitY;
313
0
  chroma_width_confwin = chroma_width -left-right;
314
0
  chroma_height_confwin= chroma_height-top-bottom;
315
316
0
  spec.crop_left  = left *WinUnitX;
317
0
  spec.crop_right = right*WinUnitX;
318
0
  spec.crop_top   = top   *WinUnitY;
319
0
  spec.crop_bottom= bottom*WinUnitY;
320
321
0
  spec.visible_width = width_confwin;
322
0
  spec.visible_height= height_confwin;
323
324
325
0
  BitDepth_Y = (sps==nullptr) ? 8 : sps->BitDepth_Y;
326
0
  BitDepth_C = (sps==nullptr) ? 8 : sps->BitDepth_C;
327
328
0
  bpp_shift[0] = (BitDepth_Y <= 8) ? 0 : 1;
329
0
  bpp_shift[1] = (BitDepth_C <= 8) ? 0 : 1;
330
0
  bpp_shift[2] = bpp_shift[1];
331
332
333
  // allocate memory and set conformance window pointers
334
335
0
  void* alloc_userdata = nullptr;
336
0
  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
0
  else*/ if (decctx && useCustomAllocFunc) {
354
0
    image_allocation_functions = decctx->param_image_allocation_functions;
355
0
  }
356
0
  else {
357
0
    image_allocation_functions = de265_image::default_image_allocation;
358
0
  }
359
360
0
  bool mem_alloc_success = true;
361
362
0
  if (image_allocation_functions.get_buffer != nullptr) {
363
0
    mem_alloc_success = image_allocation_functions.get_buffer(decctx, &spec, this,
364
0
                                                              alloc_userdata);
365
366
    // check for memory shortage
367
368
0
    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
0
    pixels_confwin[0] = static_cast<uint8_t*>(get_image_plane_at_pos_any_depth(0, left*WinUnitX, top*WinUnitY));
377
378
0
    if (chroma_format != de265_chroma_mono) {
379
0
      pixels_confwin[1] = static_cast<uint8_t*>(get_image_plane_at_pos_any_depth(1, left, top));
380
0
      pixels_confwin[2] = static_cast<uint8_t*>(get_image_plane_at_pos_any_depth(2, left, top));
381
0
    }
382
0
    else {
383
0
      pixels_confwin[1] = nullptr;
384
0
      pixels_confwin[2] = nullptr;
385
0
    }
386
0
  }
387
388
  //alloc_functions = *allocfunc;
389
  //alloc_userdata  = userdata;
390
391
  // --- allocate decoding info arrays ---
392
393
0
  if (allocMetadata) {
394
    // intra pred mode
395
396
0
    mem_alloc_success &= intraPredMode.alloc(sps->PicWidthInMinPUs, sps->PicHeightInMinPUs,
397
0
                                             sps->Log2MinPUSize);
398
399
0
    mem_alloc_success &= intraPredModeC.alloc(sps->PicWidthInMinPUs, sps->PicHeightInMinPUs,
400
0
                                              sps->Log2MinPUSize);
401
402
    // cb info
403
404
0
    mem_alloc_success &= cb_info.alloc(sps->PicWidthInMinCbsY, sps->PicHeightInMinCbsY,
405
0
                                       sps->Log2MinCbSizeY);
406
407
    // pb info
408
409
0
    int puWidth  = sps->PicWidthInMinCbsY  << (sps->Log2MinCbSizeY -2);
410
0
    int puHeight = sps->PicHeightInMinCbsY << (sps->Log2MinCbSizeY -2);
411
412
0
    mem_alloc_success &= pb_info.alloc(puWidth,puHeight, 2);
413
414
415
    // tu info
416
417
0
    mem_alloc_success &= tu_info.alloc(sps->PicWidthInTbsY, sps->PicHeightInTbsY,
418
0
                                       sps->Log2MinTrafoSize);
419
420
    // deblk info
421
422
0
    int deblk_w = (sps->pic_width_in_luma_samples +3)/4;
423
0
    int deblk_h = (sps->pic_height_in_luma_samples+3)/4;
424
425
0
    mem_alloc_success &= deblk_info.alloc(deblk_w, deblk_h, 2);
426
427
    // CTB info
428
429
0
    if (ctb_info.width_in_units  != sps->PicWidthInCtbsY  ||
430
0
        ctb_info.height_in_units != sps->PicHeightInCtbsY ||
431
0
        ctb_info.log2unitSize    != sps->Log2CtbSizeY)
432
0
      {
433
0
        delete[] ctb_progress;
434
435
0
        mem_alloc_success &= ctb_info.alloc(sps->PicWidthInCtbsY, sps->PicHeightInCtbsY,
436
0
                                            sps->Log2CtbSizeY);
437
438
0
        ctb_progress = new de265_progress_lock[ ctb_info.data_size ];
439
0
      }
440
441
442
    // check for memory shortage
443
444
0
    if (!mem_alloc_success)
445
0
      {
446
0
        return DE265_ERROR_OUT_OF_MEMORY;
447
0
      }
448
0
  }
449
450
0
  return DE265_OK;
451
0
}
452
453
454
de265_image::~de265_image()
455
0
{
456
0
  release();
457
458
  // free progress locks
459
460
0
  if (ctb_progress) {
461
0
    delete[] ctb_progress;
462
0
  }
463
0
}
464
465
466
void de265_image::release()
467
0
{
468
  // free image memory
469
470
0
  if (pixels[0])
471
0
    {
472
      /*
473
      if (encoder_image_release_func != nullptr) {
474
        encoder_image_release_func(encctx, this,
475
                                   encctx->param_image_allocation_userdata);
476
      }
477
0
      else*/ {
478
0
        image_allocation_functions.release_buffer(decctx, this,
479
0
                                                  decctx ?
480
0
                                                  decctx->param_image_allocation_userdata :
481
0
                                                  nullptr);
482
0
      }
483
484
0
      for (int i=0;i<3;i++)
485
0
        {
486
0
          pixels[i] = nullptr;
487
0
          pixels_confwin[i] = nullptr;
488
0
        }
489
0
    }
490
491
  // free slices
492
493
0
  for (size_t i=0;i<slices.size();i++) {
494
0
    delete slices[i];
495
0
  }
496
0
  slices.clear();
497
0
}
498
499
500
void de265_image::fill_plane(int channel, int value)
501
0
{
502
0
  int bytes_per_pixel = get_bytes_per_pixel(channel);
503
0
  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
0
  const size_t plane_bytes =
508
0
      (channel == 0 ? static_cast<size_t>(stride) * height
509
0
                    : static_cast<size_t>(chroma_stride) * chroma_height)
510
0
      * bytes_per_pixel;
511
512
0
  if (bytes_per_pixel == 1) {
513
0
    memset(pixels[channel], value, plane_bytes + MEMORY_PADDING);
514
0
  }
515
0
  else if ((value >> 8) == (value & 0xFF)) {
516
0
    assert(bytes_per_pixel == 2);
517
518
    // if we fill the same byte value to all bytes, we can still use memset()
519
0
    memset(pixels[channel], value & 0xFF, plane_bytes + MEMORY_PADDING);
520
0
  }
521
0
  else {
522
0
    assert(bytes_per_pixel == 2);
523
0
    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
0
    const ptrdiff_t row_width  = (channel==0 ? stride        : chroma_stride);
529
0
    const int       nRows      = (channel==0 ? height        : chroma_height);
530
531
    // copy value into first row
532
0
    for (ptrdiff_t x = 0; x < row_width; x++) {
533
0
      *reinterpret_cast<uint16_t*>(&pixels[channel][2 * x]) = v;
534
0
    }
535
536
    // copy first row into remaining rows
537
0
    for (int y = 1; y < nRows; y++) {
538
0
      memcpy(pixels[channel] + y * row_width * 2, pixels[channel], row_width * 2);
539
0
    }
540
541
0
#if MEMORY_PADDING > 0
542
0
    memset(pixels[channel] + plane_bytes, 0, MEMORY_PADDING);
543
0
#endif
544
0
  }
545
0
}
546
547
548
void de265_image::fill_image(int y,int cb,int cr)
549
0
{
550
0
  if (pixels[0]) {
551
0
    fill_plane(0, y);
552
0
  }
553
554
0
  if (pixels[1]) {
555
0
    fill_plane(1, cb);
556
0
  }
557
558
0
  if (pixels[2]) {
559
0
    fill_plane(2, cr);
560
0
  }
561
0
}
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
0
{
587
0
  if (end > src->height) end=src->height;
588
589
0
  assert(first % 2 == 0);
590
0
  assert(end   % 2 == 0);
591
592
0
  int luma_bpp   = (sps->BitDepth_Y+7)/8;
593
0
  int chroma_bpp = (sps->BitDepth_C+7)/8;
594
595
0
  if (src->stride == stride) {
596
0
    memcpy(pixels[0]      + first*stride * luma_bpp,
597
0
           src->pixels[0] + first*src->stride * luma_bpp,
598
0
           (end-first)*stride * luma_bpp);
599
0
  }
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
0
  int first_chroma = first / src->SubHeightC;
609
0
  int end_chroma   = end   / src->SubHeightC;
610
611
0
  if (src->chroma_format != de265_chroma_mono) {
612
0
    if (src->chroma_stride == chroma_stride) {
613
0
      memcpy(pixels[1]      + first_chroma*chroma_stride * chroma_bpp,
614
0
             src->pixels[1] + first_chroma*chroma_stride * chroma_bpp,
615
0
             (end_chroma-first_chroma) * chroma_stride * chroma_bpp);
616
0
      memcpy(pixels[2]      + first_chroma*chroma_stride * chroma_bpp,
617
0
             src->pixels[2] + first_chroma*chroma_stride * chroma_bpp,
618
0
             (end_chroma-first_chroma) * chroma_stride * chroma_bpp);
619
0
    }
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
0
  }
631
0
}
632
633
634
void de265_image::exchange_pixel_data_with(de265_image& b)
635
0
{
636
0
  for (int i=0;i<3;i++) {
637
0
    std::swap(pixels[i], b.pixels[i]);
638
0
    std::swap(pixels_confwin[i], b.pixels_confwin[i]);
639
0
    std::swap(plane_user_data[i], b.plane_user_data[i]);
640
0
  }
641
642
0
  std::swap(stride, b.stride);
643
0
  std::swap(chroma_stride, b.chroma_stride);
644
0
  std::swap(image_allocation_functions, b.image_allocation_functions);
645
0
}
646
647
648
void de265_image::thread_start(int nThreads)
649
0
{
650
0
  std::unique_lock<std::mutex> lock(mutex);
651
652
  //printf("nThreads before: %d %d\n",nThreadsQueued, nThreadsTotal);
653
654
0
  nThreadsQueued += nThreads;
655
0
  nThreadsTotal += nThreads;
656
657
  //printf("nThreads after: %d %d\n",nThreadsQueued, nThreadsTotal);
658
0
}
659
660
void de265_image::thread_run(const thread_task* task)
661
0
{
662
0
  std::unique_lock<std::mutex> lock(mutex);
663
664
  //printf("run thread %s\n", task->name().c_str());
665
666
0
  nThreadsQueued--;
667
0
  nThreadsRunning++;
668
0
}
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
0
{
688
  //printf("finish thread %s\n", task->name().c_str());
689
690
0
  std::unique_lock<std::mutex> lock(mutex);
691
692
0
  nThreadsRunning--;
693
0
  nThreadsFinished++;
694
0
  assert(nThreadsRunning >= 0);
695
696
0
  if (nThreadsFinished==nThreadsTotal) {
697
0
    finished_cond.notify_all();
698
0
  }
699
0
}
700
701
void de265_image::wait_for_progress(thread_task* task, int ctbx,int ctby, int progress)
702
0
{
703
0
  const int ctbW = sps->PicWidthInCtbsY;
704
705
0
  wait_for_progress(task, ctbx + ctbW*ctby, progress);
706
0
}
707
708
void de265_image::wait_for_progress(thread_task* task, int ctbAddrRS, int progress)
709
0
{
710
0
  if (task==nullptr) { return; }
711
712
0
  de265_progress_lock* progresslock = &ctb_progress[ctbAddrRS];
713
0
  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
0
}
729
730
731
void de265_image::wait_for_completion()
732
0
{
733
0
  std::unique_lock<std::mutex> lock(mutex);
734
735
0
  while (nThreadsFinished!=nThreadsTotal) {
736
0
    finished_cond.wait(lock);
737
0
  }
738
0
}
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
0
{
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
0
  cb_info.clear();
753
0
  intraPredMode.clear();
754
  //tu_info.clear();  // done on the fly
755
0
  ctb_info.clear();
756
0
  deblk_info.clear();
757
758
  // --- reset CTB progresses ---
759
760
0
  for (int i=0;i<ctb_info.data_size;i++) {
761
0
    ctb_progress[i].reset(CTB_PROGRESS_NONE);
762
0
  }
763
0
}
764
765
766
void de265_image::set_mv_info(int x,int y, int nPbW,int nPbH, const PBMotion& mv)
767
0
{
768
0
  int log2PuSize = 2;
769
770
0
  int xPu = x >> log2PuSize;
771
0
  int yPu = y >> log2PuSize;
772
0
  int wPu = nPbW >> log2PuSize;
773
0
  int hPu = nPbH >> log2PuSize;
774
775
0
  int stride = pb_info.width_in_units;
776
777
0
  for (int pby=0;pby<hPu;pby++)
778
0
    for (int pbx=0;pbx<wPu;pbx++)
779
0
      {
780
0
        pb_info[ xPu+pbx + (yPu+pby)*stride ] = mv;
781
0
      }
782
0
}
783
784
785
bool de265_image::available_zscan(int xCurr,int yCurr, int xN,int yN) const
786
0
{
787
0
  if (xN<0 || yN<0) return false;
788
0
  if (xN>=sps->pic_width_in_luma_samples ||
789
0
      yN>=sps->pic_height_in_luma_samples) return false;
790
791
0
  int minBlockAddrN = pps->scan->MinTbAddrZS[ (xN>>sps->Log2MinTrafoSize) +
792
0
                                        (yN>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ];
793
0
  int minBlockAddrCurr = pps->scan->MinTbAddrZS[ (xCurr>>sps->Log2MinTrafoSize) +
794
0
                                           (yCurr>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ];
795
796
0
  if (minBlockAddrN > minBlockAddrCurr) return false;
797
798
0
  int xCurrCtb = xCurr >> sps->Log2CtbSizeY;
799
0
  int yCurrCtb = yCurr >> sps->Log2CtbSizeY;
800
0
  int xNCtb = xN >> sps->Log2CtbSizeY;
801
0
  int yNCtb = yN >> sps->Log2CtbSizeY;
802
803
0
  if (get_SliceAddrRS(xCurrCtb,yCurrCtb) !=
804
0
      get_SliceAddrRS(xNCtb,   yNCtb)) {
805
0
    return false;
806
0
  }
807
808
0
  if (pps->scan->TileIdRS[xCurrCtb + yCurrCtb*sps->PicWidthInCtbsY] !=
809
0
      pps->scan->TileIdRS[xNCtb    + yNCtb   *sps->PicWidthInCtbsY]) {
810
0
    return false;
811
0
  }
812
813
0
  return true;
814
0
}
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
0
{
820
0
  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
0
  int sameCb = (xC <= xN && xN < xC+nCbS &&
823
0
                yC <= yN && yN < yC+nCbS);
824
825
0
  bool availableN;
826
827
0
  if (!sameCb) {
828
0
    availableN = available_zscan(xP,yP,xN,yN);
829
0
  }
830
0
  else {
831
0
    availableN = !(nPbW<<1 == nCbS && nPbH<<1 == nCbS &&  // NxN
832
0
                   partIdx==1 &&
833
0
                   yN >= yC+nPbH && xN < xC+nPbW);  // xN/yN inside partIdx 2
834
0
  }
835
836
0
  if (availableN && get_pred_mode(xN,yN) == MODE_INTRA) {
837
0
    availableN = false;
838
0
  }
839
840
0
  return availableN;
841
0
}