AttributeDecoder.cpp 22.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* The copyright in this software is being made available under the BSD
 * Licence, included below.  This software may be subject to other third
 * party and contributor rights, including patent rights, and no such
 * rights are granted under this licence.
 *
 * Copyright (c) 2017-2018, ISO/IEC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of the ISO/IEC nor the names of its contributors
 *   may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "AttributeDecoder.h"
37

38
#include "DualLutCoder.h"
39
#include "constants.h"
40
#include "entropy.h"
41
#include "io_hls.h"
42
#include "RAHT.h"
43
#include "FixedPoint.h"
44
45
46
47
48
49
50

namespace pcc {

//============================================================================
// An encapsulation of the entropy decoding methods used in attribute coding

struct PCCResidualsDecoder {
51
52
53
54
  EntropyDecoder arithmeticDecoder;
  StaticBitModel binaryModel0;
  AdaptiveBitModel binaryModelDiff[7];
  AdaptiveBitModel binaryModelIsZero[7];
55
  AdaptiveBitModel ctxPredMode[2];
56
57
  AdaptiveBitModel ctxZeroCnt[3];
  AdaptiveBitModel binaryModelIsOne[7];
58
  DualLutCoder<false> symbolCoder[2];
59

60
  void start(const SequenceParameterSet& sps, const char* buf, int buf_len);
61
  void stop();
62
  int decodePredMode(int max);
63
  int decodeZeroCnt(int max);
64
65
66
  uint32_t decodeSymbol(int k1, int k2);
  void decode(uint32_t values[3]);
  uint32_t decode();
67
68
69
70
};

//----------------------------------------------------------------------------

71
void
72
73
PCCResidualsDecoder::start(
  const SequenceParameterSet& sps, const char* buf, int buf_len)
74
{
75
  arithmeticDecoder.setBuffer(buf_len, buf);
76
  arithmeticDecoder.enableBypassStream(sps.cabac_bypass_stream_enabled_flag);
77
  arithmeticDecoder.start();
78
79
80
81
}

//----------------------------------------------------------------------------

82
83
84
void
PCCResidualsDecoder::stop()
{
85
  arithmeticDecoder.stop();
86
87
88
89
}

//----------------------------------------------------------------------------

90
91
int
PCCResidualsDecoder::decodePredMode(int maxMode)
92
{
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  int mode = 0;

  if (maxMode == 0)
    return mode;

  int ctxIdx = 0;
  while (arithmeticDecoder.decode(ctxPredMode[ctxIdx])) {
    ctxIdx = 1;
    mode++;
    if (mode == maxMode)
      break;
  }

  return mode;
107
108
109
110
}

//----------------------------------------------------------------------------

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
int
PCCResidualsDecoder::decodeZeroCnt(int maxMode)
{
  int mode = 0;

  if (maxMode == 0)
    return mode;

  int ctxIdx = 0;
  while (arithmeticDecoder.decode(ctxZeroCnt[ctxIdx])) {
    ctxIdx = (ctxIdx == 0 ? 1 : 2);
    mode++;
    if (mode == maxMode)
      break;
  }
  return mode;
}

//----------------------------------------------------------------------------

131
uint32_t
132
PCCResidualsDecoder::decodeSymbol(int k1, int k2)
133
{
134
  if (arithmeticDecoder.decode(binaryModelIsZero[k1]))
135
    return 0u;
136
137
138

  if (arithmeticDecoder.decode(binaryModelIsOne[k1]))
    return 1u;
139
140

  uint32_t value = symbolCoder[k2].decode(&arithmeticDecoder);
141
  if (value == kAttributeResidualAlphabetSize) {
142
    value +=
143
      arithmeticDecoder.decodeExpGolomb(0, binaryModel0, binaryModelDiff[k1]);
144
  }
145

146
  return value + 2;
147
148
149
150
}

//----------------------------------------------------------------------------

151
152
153
154
155
156
157
158
void
PCCResidualsDecoder::decode(uint32_t value[3])
{
  value[0] = decodeSymbol(0, 0);
  int b0 = value[0] == 0;
  value[1] = decodeSymbol(1 + b0, 1);
  int b1 = value[1] == 0;
  value[2] = decodeSymbol(3 + (b0 << 1) + b1, 1);
159
160
161
162
163

  int d = (value[0] == value[1] && value[0] == value[2]);
  for (int k = 0; k < 3; k++) {
    value[k] += d;
  }
164
165
166
167
}

//----------------------------------------------------------------------------

168
uint32_t
169
PCCResidualsDecoder::decode()
170
{
171
  return decodeSymbol(0, 0) + 1;
172
173
174
175
176
}

//============================================================================
// AttributeDecoder Members

177
void
178
AttributeDecoder::decode(
179
  const SequenceParameterSet& sps,
180
181
  const AttributeDescription& attr_desc,
  const AttributeParameterSet& attr_aps,
182
183
  int geom_num_points,
  int minGeomNodeSizeLog2,
184
185
  const PayloadBuffer& payload,
  PCCPointSet3& pointCloud)
186
{
187
  int abhSize;
188
  AttributeBrickHeader abh = parseAbh(attr_aps, payload, &abhSize);
189
190

  std::vector<Quantizers> quantLayers = deriveQuantizerLayers(attr_aps, abh);
191

192
  PCCResidualsDecoder decoder;
193
  decoder.start(sps, payload.data() + abhSize, payload.size() - abhSize);
194

195
  if (attr_desc.attr_num_dimensions == 1) {
196
197
    switch (attr_aps.attr_encoding) {
    case AttributeEncoding::kRAHTransform:
198
199
      decodeReflectancesRaht(
        attr_desc, attr_aps, quantLayers, decoder, pointCloud);
200
      break;
201

202
    case AttributeEncoding::kPredictingTransform:
203
204
      decodeReflectancesPred(
        attr_desc, attr_aps, quantLayers, decoder, pointCloud);
205
      break;
206

207
    case AttributeEncoding::kLiftingTransform:
208
      decodeReflectancesLift(
209
210
        attr_desc, attr_aps, quantLayers, geom_num_points, minGeomNodeSizeLog2,
        decoder, pointCloud);
211
212
      break;
    }
213
  } else if (attr_desc.attr_num_dimensions == 3) {
214
215
    switch (attr_aps.attr_encoding) {
    case AttributeEncoding::kRAHTransform:
216
      decodeColorsRaht(attr_desc, attr_aps, quantLayers, decoder, pointCloud);
217
218
219
      break;

    case AttributeEncoding::kPredictingTransform:
220
      decodeColorsPred(attr_desc, attr_aps, quantLayers, decoder, pointCloud);
221
222
223
      break;

    case AttributeEncoding::kLiftingTransform:
224
225
226
      decodeColorsLift(
        attr_desc, attr_aps, quantLayers, geom_num_points, minGeomNodeSizeLog2,
        decoder, pointCloud);
227
228
229
      break;
    }
  } else {
230
231
232
    assert(
      attr_desc.attr_num_dimensions == 1
      || attr_desc.attr_num_dimensions == 3);
233
  }
234
235
236
237
238
239

  decoder.stop();
}

//----------------------------------------------------------------------------

240
void
241
AttributeDecoder::computeReflectancePredictionWeights(
242
  const AttributeParameterSet& aps,
243
  const PCCPointSet3& pointCloud,
244
  const std::vector<uint32_t>& indexes,
245
246
247
248
  PCCPredictor& predictor,
  PCCResidualsDecoder& decoder)
{
  predictor.computeWeights();
249
250
  int64_t maxDiff = 0;

251
252
253
  if (predictor.neighborCount > 1) {
    int64_t minValue = 0;
    int64_t maxValue = 0;
254
255
256
    for (int i = 0; i < predictor.neighborCount; ++i) {
      const uint16_t reflectanceNeighbor = pointCloud.getReflectance(
        indexes[predictor.neighbors[i].predictorIndex]);
257
258
259
260
261
262
263
      if (i == 0 || reflectanceNeighbor < minValue) {
        minValue = reflectanceNeighbor;
      }
      if (i == 0 || reflectanceNeighbor > maxValue) {
        maxValue = reflectanceNeighbor;
      }
    }
264
265
266
267
268
    maxDiff = maxValue - minValue;
  }

  if (maxDiff >= aps.adaptive_prediction_threshold) {
    predictor.predMode = decoder.decodePredMode(aps.max_num_direct_predictors);
269
270
271
272
273
  }
}

//----------------------------------------------------------------------------

274
void
275
AttributeDecoder::decodeReflectancesPred(
276
  const AttributeDescription& desc,
277
  const AttributeParameterSet& aps,
278
  const std::vector<Quantizers>& quantLayers,
279
280
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
281
{
282
  const size_t pointCount = pointCloud.getPointCount();
283
284
285
  std::vector<PCCPredictor> predictors;
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
286

287
  buildPredictorsFast(
288
    aps, pointCloud, 0, predictors, numberOfPointsPerLOD, indexesLOD);
289

290
  const int64_t maxReflectance = (1ll << desc.attr_bitdepth) - 1;
291
  int zero_cnt = decoder.decodeZeroCnt(pointCount);
292
  int quantLayer = 0;
293
294
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
295
296
297
298
    if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
      quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
    }
    auto& quant = quantLayers[quantLayer];
299
    auto& predictor = predictors[predictorIndex];
300

301
302
303
304
    computeReflectancePredictionWeights(
      aps, pointCloud, indexesLOD, predictor, decoder);
    const uint32_t pointIndex = indexesLOD[predictorIndex];
    uint16_t& reflectance = pointCloud.getReflectance(pointIndex);
305
306
307
308
309
310
311
    uint32_t attValue0 = 0;
    if (zero_cnt > 0) {
      zero_cnt--;
    } else {
      attValue0 = decoder.decode();
      zero_cnt = decoder.decodeZeroCnt(pointCount);
    }
312
313
    const int64_t quantPredAttValue =
      predictor.predictReflectance(pointCloud, indexesLOD);
314
    const int64_t delta = divExp2RoundHalfUp(
315
      quant[0].scale(UIntToInt(attValue0)), kFixedPointAttributeShift);
316
    const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
317
318
319
320
321
322
323
324
325
    reflectance = uint16_t(
      PCCClip(reconstructedQuantAttValue, int64_t(0), maxReflectance));
  }
}

//----------------------------------------------------------------------------

void
AttributeDecoder::computeColorPredictionWeights(
326
  const AttributeParameterSet& aps,
327
  const PCCPointSet3& pointCloud,
328
  const std::vector<uint32_t>& indexes,
329
330
331
332
  PCCPredictor& predictor,
  PCCResidualsDecoder& decoder)
{
  predictor.computeWeights();
333
334
  int64_t maxDiff = 0;

335
336
337
  if (predictor.neighborCount > 1) {
    int64_t minValue[3] = {0, 0, 0};
    int64_t maxValue[3] = {0, 0, 0};
338
    for (int i = 0; i < predictor.neighborCount; ++i) {
339
      const Vec3<uint8_t> colorNeighbor =
340
        pointCloud.getColor(indexes[predictor.neighbors[i].predictorIndex]);
341
342
343
344
345
346
347
348
349
      for (size_t k = 0; k < 3; ++k) {
        if (i == 0 || colorNeighbor[k] < minValue[k]) {
          minValue[k] = colorNeighbor[k];
        }
        if (i == 0 || colorNeighbor[k] > maxValue[k]) {
          maxValue[k] = colorNeighbor[k];
        }
      }
    }
350
    maxDiff = (std::max)(
351
352
      maxValue[2] - minValue[2],
      (std::max)(maxValue[0] - minValue[0], maxValue[1] - minValue[1]));
353
354
355
356
  }

  if (maxDiff >= aps.adaptive_prediction_threshold) {
    predictor.predMode = decoder.decodePredMode(aps.max_num_direct_predictors);
357
358
359
360
361
  }
}

//----------------------------------------------------------------------------

362
void
363
AttributeDecoder::decodeColorsPred(
364
  const AttributeDescription& desc,
365
  const AttributeParameterSet& aps,
366
  const std::vector<Quantizers>& quantLayers,
367
368
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
369
{
370
  const size_t pointCount = pointCloud.getPointCount();
371
372
373
  std::vector<PCCPredictor> predictors;
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
374

375
  buildPredictorsFast(
376
    aps, pointCloud, 0, predictors, numberOfPointsPerLOD, indexesLOD);
377

378
  uint32_t values[3];
379
  int zero_cnt = decoder.decodeZeroCnt(pointCount);
380
  int quantLayer = 0;
381
382
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
383
384
385
386
    if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
      quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
    }
    auto& quant = quantLayers[quantLayer];
387
    auto& predictor = predictors[predictorIndex];
388

389
390
    computeColorPredictionWeights(
      aps, pointCloud, indexesLOD, predictor, decoder);
391
392
393
394
395
396
397
    if (zero_cnt > 0) {
      values[0] = values[1] = values[2] = 0;
      zero_cnt--;
    } else {
      decoder.decode(values);
      zero_cnt = decoder.decodeZeroCnt(pointCount);
    }
398
    const uint32_t pointIndex = indexesLOD[predictorIndex];
399
400
    Vec3<uint8_t>& color = pointCloud.getColor(pointIndex);
    const Vec3<uint8_t> predictedColor =
401
      predictor.predictColor(pointCloud, indexesLOD);
402

403
    int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
404
405
406
407
408
409
    for (int k = 0; k < 3; ++k) {
      const auto& q = quant[std::min(k, 1)];
      const int64_t residual = divExp2RoundHalfUp(
        q.scale(UIntToInt(values[k])), kFixedPointAttributeShift);
      const int64_t recon = predictedColor[k] + residual;
      color[k] = uint8_t(PCCClip(recon, int64_t(0), clipMax));
410
411
412
413
    }
  }
}

414
415
//----------------------------------------------------------------------------

416
417
void
AttributeDecoder::decodeReflectancesRaht(
418
  const AttributeDescription& desc,
419
  const AttributeParameterSet& aps,
420
  const std::vector<Quantizers>& quantLayers,
421
422
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
423
{
424
425
426
  const int voxelCount = int(pointCloud.getPointCount());
  std::vector<MortonCodeWithIndex> packedVoxel(voxelCount);
  for (int n = 0; n < voxelCount; n++) {
427
    packedVoxel[n].mortonCode = mortonAddr(pointCloud[n], 0);
428
429
430
431
    packedVoxel[n].index = n;
  }
  sort(packedVoxel.begin(), packedVoxel.end());

432
  // Morton codes
433
  int64_t* mortonCode = new int64_t[voxelCount];
434
435
436
437
438
  for (int n = 0; n < voxelCount; n++) {
    mortonCode[n] = packedVoxel[n].mortonCode;
  }

  // Entropy decode
439
  const int attribCount = 1;
David Flynn's avatar
David Flynn committed
440
  int* coefficients = new int[attribCount * voxelCount];
441
  int zero_cnt = decoder.decodeZeroCnt(voxelCount);
442
  for (int n = 0; n < voxelCount; ++n) {
443
444
445
446
447
448
449
    uint32_t value = 0;
    if (zero_cnt > 0) {
      zero_cnt--;
    } else {
      value = decoder.decode();
      zero_cnt = decoder.decodeZeroCnt(voxelCount);
    }
David Flynn's avatar
David Flynn committed
450
    coefficients[n] = UIntToInt(value);
451
452
  }

David Flynn's avatar
David Flynn committed
453
  int* attributes = new int[attribCount * voxelCount];
454
455

  regionAdaptiveHierarchicalInverseTransform(
456
    aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
457
    attribCount, voxelCount, coefficients);
458

459
460
  const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
  const int64_t minReflectance = 0;
461
  for (int n = 0; n < voxelCount; n++) {
David Flynn's avatar
David Flynn committed
462
    int64_t val = attributes[attribCount * n];
463
464
465
    const uint16_t reflectance =
      (uint16_t)PCCClip(val, minReflectance, maxReflectance);
    pointCloud.setReflectance(packedVoxel[n].index, reflectance);
466
467
468
469
470
  }

  // De-allocate arrays.
  delete[] mortonCode;
  delete[] attributes;
David Flynn's avatar
David Flynn committed
471
  delete[] coefficients;
472
473
474
475
}

//----------------------------------------------------------------------------

476
477
void
AttributeDecoder::decodeColorsRaht(
478
  const AttributeDescription& desc,
479
  const AttributeParameterSet& aps,
480
  const std::vector<Quantizers>& quantLayers,
481
482
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
483
{
484
485
486
  const int voxelCount = int(pointCloud.getPointCount());
  std::vector<MortonCodeWithIndex> packedVoxel(voxelCount);
  for (int n = 0; n < voxelCount; n++) {
487
    packedVoxel[n].mortonCode = mortonAddr(pointCloud[n], 0);
488
489
490
491
    packedVoxel[n].index = n;
  }
  sort(packedVoxel.begin(), packedVoxel.end());

492
  // Morton codes
493
  int64_t* mortonCode = new int64_t[voxelCount];
494
495
496
497
498
499
  for (int n = 0; n < voxelCount; n++) {
    mortonCode[n] = packedVoxel[n].mortonCode;
  }

  // Entropy decode
  const int attribCount = 3;
500
  int zero_cnt = decoder.decodeZeroCnt(voxelCount);
David Flynn's avatar
David Flynn committed
501
  int* coefficients = new int[attribCount * voxelCount];
502

503
  for (int n = 0; n < voxelCount; ++n) {
504
505
506
507
508
509
510
511
    uint32_t values[3];
    if (zero_cnt > 0) {
      values[0] = values[1] = values[2] = 0;
      zero_cnt--;
    } else {
      decoder.decode(values);
      zero_cnt = decoder.decodeZeroCnt(voxelCount);
    }
512
    for (int d = 0; d < attribCount; ++d) {
David Flynn's avatar
David Flynn committed
513
      coefficients[voxelCount * d + n] = UIntToInt(values[d]);
514
515
516
    }
  }

David Flynn's avatar
David Flynn committed
517
  int* attributes = new int[attribCount * voxelCount];
518

519
  regionAdaptiveHierarchicalInverseTransform(
520
    aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
521
    attribCount, voxelCount, coefficients);
522

523
  const int clipMax = (1 << desc.attr_bitdepth) - 1;
524
  for (int n = 0; n < voxelCount; n++) {
David Flynn's avatar
David Flynn committed
525
526
527
    const int r = attributes[attribCount * n];
    const int g = attributes[attribCount * n + 1];
    const int b = attributes[attribCount * n + 2];
528
    Vec3<uint8_t> color;
529
530
531
    color[0] = uint8_t(PCCClip(r, 0, clipMax));
    color[1] = uint8_t(PCCClip(g, 0, clipMax));
    color[2] = uint8_t(PCCClip(b, 0, clipMax));
532
533
534
535
536
537
    pointCloud.setColor(packedVoxel[n].index, color);
  }

  // De-allocate arrays.
  delete[] mortonCode;
  delete[] attributes;
David Flynn's avatar
David Flynn committed
538
  delete[] coefficients;
539
540
}

541
542
543
544
//----------------------------------------------------------------------------

void
AttributeDecoder::decodeColorsLift(
545
  const AttributeDescription& desc,
546
  const AttributeParameterSet& aps,
547
  const std::vector<Quantizers>& quantLayers,
548
549
  int geom_num_points,
  int minGeomNodeSizeLog2,
550
551
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
552
553
{
  const size_t pointCount = pointCloud.getPointCount();
554
  std::vector<PCCPredictor> predictors;
555
556
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
557

558
559
560
  if (minGeomNodeSizeLog2 > 0)
    assert(aps.scalable_lifting_enabled_flag);

561
  buildPredictorsFast(
562
563
    aps, pointCloud, minGeomNodeSizeLog2, predictors, numberOfPointsPerLOD,
    indexesLOD);
564

565
566
567
568
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    predictors[predictorIndex].computeWeights();
  }
569
  std::vector<uint64_t> weights;
570
571
572
573
574
575
576
577
  if (!aps.scalable_lifting_enabled_flag) {
    PCCComputeQuantizationWeights(predictors, weights);
  } else {
    computeQuantizationWeightsScalable(
      predictors, numberOfPointsPerLOD, geom_num_points, minGeomNodeSizeLog2,
      weights);
  }

578
  const size_t lodCount = numberOfPointsPerLOD.size();
579
  std::vector<Vec3<int64_t>> colors;
580
  colors.resize(pointCount);
581

582
583
584
585
586
  // NB: when partially decoding, the truncated unary limit for zero_run
  // must be the original value.  geom_num_points may be the case.  However,
  // the encoder does lie sometimes, and there are actually more points.
  int zeroCntLimit = std::max(geom_num_points, int(pointCount));

587
  // decompress
588
589
  int zero_cnt = decoder.decodeZeroCnt(zeroCntLimit);
  std::cout << zero_cnt << '\n';
590
  int quantLayer = 0;
591
592
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
593
594
595
596
597
    if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
      quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
    }
    auto& quant = quantLayers[quantLayer];

598
    uint32_t values[3];
599
600
601
602
603
    if (zero_cnt > 0) {
      values[0] = values[1] = values[2] = 0;
      zero_cnt--;
    } else {
      decoder.decode(values);
604
605
      zero_cnt = decoder.decodeZeroCnt(zeroCntLimit);
  std::cout << zero_cnt << '\n';
606
    }
607

608
    const int64_t quantWeight = weights[predictorIndex];
609
    auto& color = colors[predictorIndex];
610
    const int64_t delta = UIntToInt(values[0]);
611
    const int64_t reconstructedDelta = quant[0].scale(delta);
612
613
    color[0] = reconstructedDelta / quantWeight;
    for (size_t d = 1; d < 3; ++d) {
614
      const int64_t delta = UIntToInt(values[d]);
615
      const int64_t reconstructedDelta = quant[1].scale(delta);
616
617
618
619
620
621
622
623
624
625
626
      color[d] = reconstructedDelta / quantWeight;
    }
  }

  // reconstruct
  for (size_t lodIndex = 1; lodIndex < lodCount; ++lodIndex) {
    const size_t startIndex = numberOfPointsPerLOD[lodIndex - 1];
    const size_t endIndex = numberOfPointsPerLOD[lodIndex];
    PCCLiftUpdate(predictors, weights, startIndex, endIndex, false, colors);
    PCCLiftPredict(predictors, startIndex, endIndex, false, colors);
  }
627

628
  const int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
629
  for (size_t f = 0; f < pointCount; ++f) {
630
631
    const auto color0 =
      divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift);
632
    Vec3<uint8_t> color;
633
    for (size_t d = 0; d < 3; ++d) {
634
      color[d] = uint8_t(PCCClip(color0[d], int64_t(0), clipMax));
635
    }
636
    pointCloud.setColor(indexesLOD[f], color);
637
638
639
640
641
642
643
  }
}

//----------------------------------------------------------------------------

void
AttributeDecoder::decodeReflectancesLift(
644
  const AttributeDescription& desc,
645
  const AttributeParameterSet& aps,
646
  const std::vector<Quantizers>& quantLayers,
647
648
  int geom_num_points,
  int minGeomNodeSizeLog2,
649
650
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
651
{
652
  const size_t pointCount = pointCloud.getPointCount();
653
  std::vector<PCCPredictor> predictors;
654
655
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
656

657
658
659
  if (minGeomNodeSizeLog2 > 0)
    assert(aps.scalable_lifting_enabled_flag);

660
  buildPredictorsFast(
661
662
    aps, pointCloud, minGeomNodeSizeLog2, predictors, numberOfPointsPerLOD,
    indexesLOD);
663

664
665
666
667
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    predictors[predictorIndex].computeWeights();
  }
668

669
  std::vector<uint64_t> weights;
670
671
672
673
674
675
676
677
  if (!aps.scalable_lifting_enabled_flag) {
    PCCComputeQuantizationWeights(predictors, weights);
  } else {
    computeQuantizationWeightsScalable(
      predictors, numberOfPointsPerLOD, geom_num_points, minGeomNodeSizeLog2,
      weights);
  }

678
  const size_t lodCount = numberOfPointsPerLOD.size();
679
  std::vector<int64_t> reflectances;
680
  reflectances.resize(pointCount);
681

682
683
684
685
686
  // NB: when partially decoding, the truncated unary limit for zero_run
  // must be the original value.  geom_num_points may be the case.  However,
  // the encoder does lie sometimes, and there are actually more points.
  int zeroCntLimit = std::max(geom_num_points, int(pointCount));

687
  // decompress
688
  int zero_cnt = decoder.decodeZeroCnt(zeroCntLimit);
689
  int quantLayer = 0;
690
691
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
692
693
694
695
696
    if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
      quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
    }
    auto& quant = quantLayers[quantLayer];

697
698
699
700
701
    int64_t detail = 0;
    if (zero_cnt > 0) {
      zero_cnt--;
    } else {
      detail = decoder.decode();
702
      zero_cnt = decoder.decodeZeroCnt(zeroCntLimit);
703
    }
704
    const int64_t quantWeight = weights[predictorIndex];
705
    auto& reflectance = reflectances[predictorIndex];
706
    const int64_t delta = UIntToInt(detail);
707
    const int64_t reconstructedDelta = quant[0].scale(delta);
708
709
710
711
712
713
714
715
716
717
718
    reflectance = reconstructedDelta / quantWeight;
  }

  // reconstruct
  for (size_t lodIndex = 1; lodIndex < lodCount; ++lodIndex) {
    const size_t startIndex = numberOfPointsPerLOD[lodIndex - 1];
    const size_t endIndex = numberOfPointsPerLOD[lodIndex];
    PCCLiftUpdate(
      predictors, weights, startIndex, endIndex, false, reflectances);
    PCCLiftPredict(predictors, startIndex, endIndex, false, reflectances);
  }
719
  const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
720
  for (size_t f = 0; f < pointCount; ++f) {
721
722
    const auto refl =
      divExp2RoundHalfInf(reflectances[f], kFixedPointAttributeShift);
723
    pointCloud.setReflectance(
724
      indexesLOD[f], uint16_t(PCCClip(refl, int64_t(0), maxReflectance)));
725
726
727
  }
}

728
729
//============================================================================

730
} /* namespace pcc */