• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "logging/rtc_event_log/encoder/delta_encoding.h"
12 
13 #include <algorithm>
14 #include <limits>
15 #include <memory>
16 #include <utility>
17 
18 #include "absl/memory/memory.h"
19 #include "logging/rtc_event_log/encoder/var_int.h"
20 #include "rtc_base/bit_buffer.h"
21 #include "rtc_base/checks.h"
22 #include "rtc_base/constructor_magic.h"
23 #include "rtc_base/logging.h"
24 #include "rtc_base/numerics/safe_conversions.h"
25 
26 namespace webrtc {
27 namespace {
28 
29 // TODO(eladalon): Only build the decoder in tools and unit tests.
30 
31 bool g_force_unsigned_for_testing = false;
32 bool g_force_signed_for_testing = false;
33 
BitsToBytes(size_t bits)34 size_t BitsToBytes(size_t bits) {
35   return (bits / 8) + (bits % 8 > 0 ? 1 : 0);
36 }
37 
38 // TODO(eladalon): Replace by something more efficient.
UnsignedBitWidth(uint64_t input,bool zero_val_as_zero_width=false)39 uint64_t UnsignedBitWidth(uint64_t input, bool zero_val_as_zero_width = false) {
40   if (zero_val_as_zero_width && input == 0) {
41     return 0;
42   }
43 
44   uint64_t width = 0;
45   do {  // input == 0 -> width == 1
46     width += 1;
47     input >>= 1;
48   } while (input != 0);
49   return width;
50 }
51 
SignedBitWidth(uint64_t max_pos_magnitude,uint64_t max_neg_magnitude)52 uint64_t SignedBitWidth(uint64_t max_pos_magnitude,
53                         uint64_t max_neg_magnitude) {
54   const uint64_t bitwidth_pos = UnsignedBitWidth(max_pos_magnitude, true);
55   const uint64_t bitwidth_neg =
56       (max_neg_magnitude > 0) ? UnsignedBitWidth(max_neg_magnitude - 1, true)
57                               : 0;
58   return 1 + std::max(bitwidth_pos, bitwidth_neg);
59 }
60 
61 // Return the maximum integer of a given bit width.
62 // Examples:
63 // MaxUnsignedValueOfBitWidth(1) = 0x01
64 // MaxUnsignedValueOfBitWidth(6) = 0x3f
65 // MaxUnsignedValueOfBitWidth(8) = 0xff
66 // MaxUnsignedValueOfBitWidth(32) = 0xffffffff
MaxUnsignedValueOfBitWidth(uint64_t bit_width)67 uint64_t MaxUnsignedValueOfBitWidth(uint64_t bit_width) {
68   RTC_DCHECK_GE(bit_width, 1);
69   RTC_DCHECK_LE(bit_width, 64);
70   return (bit_width == 64) ? std::numeric_limits<uint64_t>::max()
71                            : ((static_cast<uint64_t>(1) << bit_width) - 1);
72 }
73 
74 // Computes the delta between |previous| and |current|, under the assumption
75 // that wrap-around occurs after |width| is exceeded.
UnsignedDelta(uint64_t previous,uint64_t current,uint64_t bit_mask)76 uint64_t UnsignedDelta(uint64_t previous, uint64_t current, uint64_t bit_mask) {
77   return (current - previous) & bit_mask;
78 }
79 
80 // Determines the encoding type (e.g. fixed-size encoding).
81 // Given an encoding type, may also distinguish between some variants of it
82 // (e.g. which fields of the fixed-size encoding are explicitly mentioned by
83 // the header, and which are implicitly assumed to hold certain default values).
84 enum class EncodingType {
85   kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt = 0,
86   kFixedSizeSignedDeltasEarlyWrapAndOptSupported = 1,
87   kReserved1 = 2,
88   kReserved2 = 3,
89   kNumberOfEncodingTypes  // Keep last
90 };
91 
92 // The width of each field in the encoding header. Note that this is the
93 // width in case the field exists; not all fields occur in all encoding types.
94 constexpr size_t kBitsInHeaderForEncodingType = 2;
95 constexpr size_t kBitsInHeaderForDeltaWidthBits = 6;
96 constexpr size_t kBitsInHeaderForSignedDeltas = 1;
97 constexpr size_t kBitsInHeaderForValuesOptional = 1;
98 constexpr size_t kBitsInHeaderForValueWidthBits = 6;
99 
100 static_assert(static_cast<size_t>(EncodingType::kNumberOfEncodingTypes) <=
101                   1 << kBitsInHeaderForEncodingType,
102               "Not all encoding types fit.");
103 
104 // Default values for when the encoding header does not specify explicitly.
105 constexpr bool kDefaultSignedDeltas = false;
106 constexpr bool kDefaultValuesOptional = false;
107 constexpr uint64_t kDefaultValueWidthBits = 64;
108 
109 // Wrap BitBufferWriter and extend its functionality by (1) keeping track of
110 // the number of bits written and (2) owning its buffer.
111 class BitWriter final {
112  public:
BitWriter(size_t byte_count)113   explicit BitWriter(size_t byte_count)
114       : buffer_(byte_count, '\0'),
115         bit_writer_(reinterpret_cast<uint8_t*>(&buffer_[0]), buffer_.size()),
116         written_bits_(0),
117         valid_(true) {
118     RTC_DCHECK_GT(byte_count, 0);
119   }
120 
WriteBits(uint64_t val,size_t bit_count)121   void WriteBits(uint64_t val, size_t bit_count) {
122     RTC_DCHECK(valid_);
123     const bool success = bit_writer_.WriteBits(val, bit_count);
124     RTC_DCHECK(success);
125     written_bits_ += bit_count;
126   }
127 
WriteBits(const std::string & input)128   void WriteBits(const std::string& input) {
129     RTC_DCHECK(valid_);
130     for (std::string::value_type c : input) {
131       WriteBits(c, 8 * sizeof(std::string::value_type));
132     }
133   }
134 
135   // Returns everything that was written so far.
136   // Nothing more may be written after this is called.
GetString()137   std::string GetString() {
138     RTC_DCHECK(valid_);
139     valid_ = false;
140 
141     buffer_.resize(BitsToBytes(written_bits_));
142     written_bits_ = 0;
143 
144     std::string result;
145     std::swap(buffer_, result);
146     return result;
147   }
148 
149  private:
150   std::string buffer_;
151   rtc::BitBufferWriter bit_writer_;
152   // Note: Counting bits instead of bytes wraps around earlier than it has to,
153   // which means the maximum length is lower than it could be. We don't expect
154   // to go anywhere near the limit, though, so this is good enough.
155   size_t written_bits_;
156   bool valid_;
157 
158   RTC_DISALLOW_COPY_AND_ASSIGN(BitWriter);
159 };
160 
161 // Parameters for fixed-size delta-encoding/decoding.
162 // These are tailored for the sequence which will be encoded (e.g. widths).
163 class FixedLengthEncodingParameters final {
164  public:
ValidParameters(uint64_t delta_width_bits,bool signed_deltas,bool values_optional,uint64_t value_width_bits)165   static bool ValidParameters(uint64_t delta_width_bits,
166                               bool signed_deltas,
167                               bool values_optional,
168                               uint64_t value_width_bits) {
169     return (1 <= delta_width_bits && delta_width_bits <= 64 &&
170             1 <= value_width_bits && value_width_bits <= 64 &&
171             delta_width_bits <= value_width_bits);
172   }
173 
FixedLengthEncodingParameters(uint64_t delta_width_bits,bool signed_deltas,bool values_optional,uint64_t value_width_bits)174   FixedLengthEncodingParameters(uint64_t delta_width_bits,
175                                 bool signed_deltas,
176                                 bool values_optional,
177                                 uint64_t value_width_bits)
178       : delta_width_bits_(delta_width_bits),
179         signed_deltas_(signed_deltas),
180         values_optional_(values_optional),
181         value_width_bits_(value_width_bits),
182         delta_mask_(MaxUnsignedValueOfBitWidth(delta_width_bits_)),
183         value_mask_(MaxUnsignedValueOfBitWidth(value_width_bits_)) {
184     RTC_DCHECK(ValidParameters(delta_width_bits, signed_deltas, values_optional,
185                                value_width_bits));
186   }
187 
188   // Number of bits necessary to hold the widest(*) of the deltas between the
189   // values in the sequence.
190   // (*) - Widest might not be the largest, if signed deltas are used.
delta_width_bits() const191   uint64_t delta_width_bits() const { return delta_width_bits_; }
192 
193   // Whether deltas are signed.
signed_deltas() const194   bool signed_deltas() const { return signed_deltas_; }
195 
196   // Whether the values of the sequence are optional. That is, it may be
197   // that some of them do not have a value (not even a sentinel value indicating
198   // invalidity).
values_optional() const199   bool values_optional() const { return values_optional_; }
200 
201   // Number of bits necessary to hold the largest value in the sequence.
value_width_bits() const202   uint64_t value_width_bits() const { return value_width_bits_; }
203 
204   // Masks where only the bits relevant to the deltas/values are turned on.
delta_mask() const205   uint64_t delta_mask() const { return delta_mask_; }
value_mask() const206   uint64_t value_mask() const { return value_mask_; }
207 
SetSignedDeltas(bool signed_deltas)208   void SetSignedDeltas(bool signed_deltas) { signed_deltas_ = signed_deltas; }
SetDeltaWidthBits(uint64_t delta_width_bits)209   void SetDeltaWidthBits(uint64_t delta_width_bits) {
210     delta_width_bits_ = delta_width_bits;
211     delta_mask_ = MaxUnsignedValueOfBitWidth(delta_width_bits);
212   }
213 
214  private:
215   uint64_t delta_width_bits_;  // Normally const, but mutable in tests.
216   bool signed_deltas_;         // Normally const, but mutable in tests.
217   const bool values_optional_;
218   const uint64_t value_width_bits_;
219 
220   uint64_t delta_mask_;  // Normally const, but mutable in tests.
221   const uint64_t value_mask_;
222 };
223 
224 // Performs delta-encoding of a single (non-empty) sequence of values, using
225 // an encoding where all deltas are encoded using the same number of bits.
226 // (With the exception of optional elements; those are encoded as a bit vector
227 // with one bit per element, plus a fixed number of bits for every element that
228 // has a value.)
229 class FixedLengthDeltaEncoder final {
230  public:
231   // See webrtc::EncodeDeltas() for general details.
232   // This function return a bit pattern that would allow the decoder to
233   // determine whether it was produced by FixedLengthDeltaEncoder, and can
234   // therefore be decoded by FixedLengthDeltaDecoder, or whether it was produced
235   // by a different encoder.
236   static std::string EncodeDeltas(
237       absl::optional<uint64_t> base,
238       const std::vector<absl::optional<uint64_t>>& values);
239 
240  private:
241   // Calculate min/max values of unsigned/signed deltas, given the bit width
242   // of all the values in the series.
243   static void CalculateMinAndMaxDeltas(
244       absl::optional<uint64_t> base,
245       const std::vector<absl::optional<uint64_t>>& values,
246       uint64_t bit_width,
247       uint64_t* max_unsigned_delta,
248       uint64_t* max_pos_signed_delta,
249       uint64_t* min_neg_signed_delta);
250 
251   // No effect outside of unit tests.
252   // In unit tests, may lead to forcing signed/unsigned deltas, etc.
253   static void ConsiderTestOverrides(FixedLengthEncodingParameters* params,
254                                     uint64_t delta_width_bits_signed,
255                                     uint64_t delta_width_bits_unsigned);
256 
257   // FixedLengthDeltaEncoder objects are to be created by EncodeDeltas() and
258   // released by it before it returns. They're mostly a convenient way to
259   // avoid having to pass a lot of state between different functions.
260   // Therefore, it was deemed acceptable to let them have a reference to
261   // |values|, whose lifetime must exceed the lifetime of |this|.
262   FixedLengthDeltaEncoder(const FixedLengthEncodingParameters& params,
263                           absl::optional<uint64_t> base,
264                           const std::vector<absl::optional<uint64_t>>& values,
265                           size_t existent_values_count);
266 
267   // Perform delta-encoding using the parameters given to the ctor on the
268   // sequence of values given to the ctor.
269   std::string Encode();
270 
271   // Exact lengths.
272   size_t OutputLengthBytes(size_t existent_values_count) const;
273   size_t HeaderLengthBits() const;
274   size_t EncodedDeltasLengthBits(size_t existent_values_count) const;
275 
276   // Encode the compression parameters into the stream.
277   void EncodeHeader();
278 
279   // Encode a given delta into the stream.
280   void EncodeDelta(uint64_t previous, uint64_t current);
281   void EncodeUnsignedDelta(uint64_t previous, uint64_t current);
282   void EncodeSignedDelta(uint64_t previous, uint64_t current);
283 
284   // The parameters according to which encoding will be done (width of
285   // fields, whether signed deltas should be used, etc.)
286   const FixedLengthEncodingParameters params_;
287 
288   // The encoding scheme assumes that at least one value is transmitted OOB,
289   // so that the first value can be encoded as a delta from that OOB value,
290   // which is |base_|.
291   const absl::optional<uint64_t> base_;
292 
293   // The values to be encoded.
294   // Note: This is a non-owning reference. See comment above ctor for details.
295   const std::vector<absl::optional<uint64_t>>& values_;
296 
297   // Buffer into which encoded values will be written.
298   // This is created dynmically as a way to enforce that the rest of the
299   // ctor has finished running when this is constructed, so that the lower
300   // bound on the buffer size would be guaranteed correct.
301   std::unique_ptr<BitWriter> writer_;
302 
303   RTC_DISALLOW_COPY_AND_ASSIGN(FixedLengthDeltaEncoder);
304 };
305 
306 // TODO(eladalon): Reduce the number of passes.
EncodeDeltas(absl::optional<uint64_t> base,const std::vector<absl::optional<uint64_t>> & values)307 std::string FixedLengthDeltaEncoder::EncodeDeltas(
308     absl::optional<uint64_t> base,
309     const std::vector<absl::optional<uint64_t>>& values) {
310   RTC_DCHECK(!values.empty());
311 
312   // As a special case, if all of the elements are identical to the base,
313   // (including, for optional fields, about their existence/non-existence),
314   // the empty string is used to signal that.
315   if (std::all_of(
316           values.cbegin(), values.cend(),
317           [base](absl::optional<uint64_t> val) { return val == base; })) {
318     return std::string();
319   }
320 
321   bool non_decreasing = true;
322   uint64_t max_value_including_base = base.value_or(0u);
323   size_t existent_values_count = 0;
324   {
325     uint64_t previous = base.value_or(0u);
326     for (size_t i = 0; i < values.size(); ++i) {
327       if (!values[i].has_value()) {
328         continue;
329       }
330       ++existent_values_count;
331       non_decreasing &= (previous <= values[i].value());
332       max_value_including_base =
333           std::max(max_value_including_base, values[i].value());
334       previous = values[i].value();
335     }
336   }
337 
338   // If the sequence is non-decreasing, it may be assumed to have width = 64;
339   // there's no reason to encode the actual max width in the encoding header.
340   const uint64_t value_width_bits =
341       non_decreasing ? 64 : UnsignedBitWidth(max_value_including_base);
342 
343   uint64_t max_unsigned_delta;
344   uint64_t max_pos_signed_delta;
345   uint64_t min_neg_signed_delta;
346   CalculateMinAndMaxDeltas(base, values, value_width_bits, &max_unsigned_delta,
347                            &max_pos_signed_delta, &min_neg_signed_delta);
348 
349   const uint64_t delta_width_bits_unsigned =
350       UnsignedBitWidth(max_unsigned_delta);
351   const uint64_t delta_width_bits_signed =
352       SignedBitWidth(max_pos_signed_delta, min_neg_signed_delta);
353 
354   // Note: Preference for unsigned if the two have the same width (efficiency).
355   const bool signed_deltas =
356       delta_width_bits_signed < delta_width_bits_unsigned;
357   const uint64_t delta_width_bits =
358       signed_deltas ? delta_width_bits_signed : delta_width_bits_unsigned;
359 
360   const bool values_optional =
361       !base.has_value() || (existent_values_count < values.size());
362 
363   FixedLengthEncodingParameters params(delta_width_bits, signed_deltas,
364                                        values_optional, value_width_bits);
365 
366   // No effect in production.
367   ConsiderTestOverrides(&params, delta_width_bits_signed,
368                         delta_width_bits_unsigned);
369 
370   FixedLengthDeltaEncoder encoder(params, base, values, existent_values_count);
371   return encoder.Encode();
372 }
373 
CalculateMinAndMaxDeltas(absl::optional<uint64_t> base,const std::vector<absl::optional<uint64_t>> & values,uint64_t bit_width,uint64_t * max_unsigned_delta_out,uint64_t * max_pos_signed_delta_out,uint64_t * min_neg_signed_delta_out)374 void FixedLengthDeltaEncoder::CalculateMinAndMaxDeltas(
375     absl::optional<uint64_t> base,
376     const std::vector<absl::optional<uint64_t>>& values,
377     uint64_t bit_width,
378     uint64_t* max_unsigned_delta_out,
379     uint64_t* max_pos_signed_delta_out,
380     uint64_t* min_neg_signed_delta_out) {
381   RTC_DCHECK(!values.empty());
382   RTC_DCHECK(max_unsigned_delta_out);
383   RTC_DCHECK(max_pos_signed_delta_out);
384   RTC_DCHECK(min_neg_signed_delta_out);
385 
386   const uint64_t bit_mask = MaxUnsignedValueOfBitWidth(bit_width);
387 
388   uint64_t max_unsigned_delta = 0;
389   uint64_t max_pos_signed_delta = 0;
390   uint64_t min_neg_signed_delta = 0;
391 
392   absl::optional<uint64_t> prev = base;
393   for (size_t i = 0; i < values.size(); ++i) {
394     if (!values[i].has_value()) {
395       continue;
396     }
397 
398     if (!prev.has_value()) {
399       // If the base is non-existent, the first existent value is encoded as
400       // a varint, rather than as a delta.
401       RTC_DCHECK(!base.has_value());
402       prev = values[i];
403       continue;
404     }
405 
406     const uint64_t current = values[i].value();
407 
408     const uint64_t forward_delta = UnsignedDelta(*prev, current, bit_mask);
409     const uint64_t backward_delta = UnsignedDelta(current, *prev, bit_mask);
410 
411     max_unsigned_delta = std::max(max_unsigned_delta, forward_delta);
412 
413     if (forward_delta < backward_delta) {
414       max_pos_signed_delta = std::max(max_pos_signed_delta, forward_delta);
415     } else {
416       min_neg_signed_delta = std::max(min_neg_signed_delta, backward_delta);
417     }
418 
419     prev = current;
420   }
421 
422   *max_unsigned_delta_out = max_unsigned_delta;
423   *max_pos_signed_delta_out = max_pos_signed_delta;
424   *min_neg_signed_delta_out = min_neg_signed_delta;
425 }
426 
ConsiderTestOverrides(FixedLengthEncodingParameters * params,uint64_t delta_width_bits_signed,uint64_t delta_width_bits_unsigned)427 void FixedLengthDeltaEncoder::ConsiderTestOverrides(
428     FixedLengthEncodingParameters* params,
429     uint64_t delta_width_bits_signed,
430     uint64_t delta_width_bits_unsigned) {
431   if (g_force_unsigned_for_testing) {
432     params->SetDeltaWidthBits(delta_width_bits_unsigned);
433     params->SetSignedDeltas(false);
434   } else if (g_force_signed_for_testing) {
435     params->SetDeltaWidthBits(delta_width_bits_signed);
436     params->SetSignedDeltas(true);
437   } else {
438     // Unchanged.
439   }
440 }
441 
FixedLengthDeltaEncoder(const FixedLengthEncodingParameters & params,absl::optional<uint64_t> base,const std::vector<absl::optional<uint64_t>> & values,size_t existent_values_count)442 FixedLengthDeltaEncoder::FixedLengthDeltaEncoder(
443     const FixedLengthEncodingParameters& params,
444     absl::optional<uint64_t> base,
445     const std::vector<absl::optional<uint64_t>>& values,
446     size_t existent_values_count)
447     : params_(params), base_(base), values_(values) {
448   RTC_DCHECK(!values_.empty());
449   writer_ =
450       std::make_unique<BitWriter>(OutputLengthBytes(existent_values_count));
451 }
452 
Encode()453 std::string FixedLengthDeltaEncoder::Encode() {
454   EncodeHeader();
455 
456   if (params_.values_optional()) {
457     // Encode which values exist and which don't.
458     for (absl::optional<uint64_t> value : values_) {
459       writer_->WriteBits(value.has_value() ? 1u : 0u, 1);
460     }
461   }
462 
463   absl::optional<uint64_t> previous = base_;
464   for (absl::optional<uint64_t> value : values_) {
465     if (!value.has_value()) {
466       RTC_DCHECK(params_.values_optional());
467       continue;
468     }
469 
470     if (!previous.has_value()) {
471       // If the base is non-existent, the first existent value is encoded as
472       // a varint, rather than as a delta.
473       RTC_DCHECK(!base_.has_value());
474       writer_->WriteBits(EncodeVarInt(value.value()));
475     } else {
476       EncodeDelta(previous.value(), value.value());
477     }
478 
479     previous = value;
480   }
481 
482   return writer_->GetString();
483 }
484 
OutputLengthBytes(size_t existent_values_count) const485 size_t FixedLengthDeltaEncoder::OutputLengthBytes(
486     size_t existent_values_count) const {
487   return BitsToBytes(HeaderLengthBits() +
488                      EncodedDeltasLengthBits(existent_values_count));
489 }
490 
HeaderLengthBits() const491 size_t FixedLengthDeltaEncoder::HeaderLengthBits() const {
492   if (params_.signed_deltas() == kDefaultSignedDeltas &&
493       params_.values_optional() == kDefaultValuesOptional &&
494       params_.value_width_bits() == kDefaultValueWidthBits) {
495     return kBitsInHeaderForEncodingType + kBitsInHeaderForDeltaWidthBits;
496   } else {
497     return kBitsInHeaderForEncodingType + kBitsInHeaderForDeltaWidthBits +
498            kBitsInHeaderForSignedDeltas + kBitsInHeaderForValuesOptional +
499            kBitsInHeaderForValueWidthBits;
500   }
501 }
502 
EncodedDeltasLengthBits(size_t existent_values_count) const503 size_t FixedLengthDeltaEncoder::EncodedDeltasLengthBits(
504     size_t existent_values_count) const {
505   if (!params_.values_optional()) {
506     return values_.size() * params_.delta_width_bits();
507   } else {
508     RTC_DCHECK_EQ(std::count_if(values_.begin(), values_.end(),
509                                 [](absl::optional<uint64_t> val) {
510                                   return val.has_value();
511                                 }),
512                   existent_values_count);
513     // One bit for each delta, to indicate if the value exists, and delta_width
514     // for each existent value, to indicate the delta itself.
515     // If base_ is non-existent, the first value (if any) is encoded as a varint
516     // rather than as a delta.
517     const size_t existence_bitmap_size_bits = 1 * values_.size();
518     const bool first_value_is_varint =
519         !base_.has_value() && existent_values_count >= 1;
520     const size_t first_value_varint_size_bits = 8 * kMaxVarIntLengthBytes;
521     const size_t deltas_count = existent_values_count - first_value_is_varint;
522     const size_t deltas_size_bits = deltas_count * params_.delta_width_bits();
523     return existence_bitmap_size_bits + first_value_varint_size_bits +
524            deltas_size_bits;
525   }
526 }
527 
EncodeHeader()528 void FixedLengthDeltaEncoder::EncodeHeader() {
529   RTC_DCHECK(writer_);
530 
531   const EncodingType encoding_type =
532       (params_.value_width_bits() == kDefaultValueWidthBits &&
533        params_.signed_deltas() == kDefaultSignedDeltas &&
534        params_.values_optional() == kDefaultValuesOptional)
535           ? EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt
536           : EncodingType::kFixedSizeSignedDeltasEarlyWrapAndOptSupported;
537 
538   writer_->WriteBits(static_cast<uint64_t>(encoding_type),
539                      kBitsInHeaderForEncodingType);
540 
541   // Note: Since it's meaningless for a field to be of width 0, when it comes
542   // to fields that relate widths, we encode  width 1 as 0, width 2 as 1,
543 
544   writer_->WriteBits(params_.delta_width_bits() - 1,
545                      kBitsInHeaderForDeltaWidthBits);
546 
547   if (encoding_type == EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt) {
548     return;
549   }
550 
551   writer_->WriteBits(static_cast<uint64_t>(params_.signed_deltas()),
552                      kBitsInHeaderForSignedDeltas);
553   writer_->WriteBits(static_cast<uint64_t>(params_.values_optional()),
554                      kBitsInHeaderForValuesOptional);
555   writer_->WriteBits(params_.value_width_bits() - 1,
556                      kBitsInHeaderForValueWidthBits);
557 }
558 
EncodeDelta(uint64_t previous,uint64_t current)559 void FixedLengthDeltaEncoder::EncodeDelta(uint64_t previous, uint64_t current) {
560   if (params_.signed_deltas()) {
561     EncodeSignedDelta(previous, current);
562   } else {
563     EncodeUnsignedDelta(previous, current);
564   }
565 }
566 
EncodeUnsignedDelta(uint64_t previous,uint64_t current)567 void FixedLengthDeltaEncoder::EncodeUnsignedDelta(uint64_t previous,
568                                                   uint64_t current) {
569   RTC_DCHECK(writer_);
570   const uint64_t delta = UnsignedDelta(previous, current, params_.value_mask());
571   writer_->WriteBits(delta, params_.delta_width_bits());
572 }
573 
EncodeSignedDelta(uint64_t previous,uint64_t current)574 void FixedLengthDeltaEncoder::EncodeSignedDelta(uint64_t previous,
575                                                 uint64_t current) {
576   RTC_DCHECK(writer_);
577 
578   const uint64_t forward_delta =
579       UnsignedDelta(previous, current, params_.value_mask());
580   const uint64_t backward_delta =
581       UnsignedDelta(current, previous, params_.value_mask());
582 
583   uint64_t delta;
584   if (forward_delta <= backward_delta) {
585     delta = forward_delta;
586   } else {
587     // Compute the unsigned representation of a negative delta.
588     // This is the two's complement representation of this negative value,
589     // when deltas are of width params_.delta_mask().
590     RTC_DCHECK_GE(params_.delta_mask(), backward_delta);
591     RTC_DCHECK_LT(params_.delta_mask() - backward_delta, params_.delta_mask());
592     delta = params_.delta_mask() - backward_delta + 1;
593     RTC_DCHECK_LE(delta, params_.delta_mask());
594   }
595 
596   writer_->WriteBits(delta, params_.delta_width_bits());
597 }
598 
599 // Perform decoding of a a delta-encoded stream, extracting the original
600 // sequence of values.
601 class FixedLengthDeltaDecoder final {
602  public:
603   // Checks whether FixedLengthDeltaDecoder is a suitable decoder for this
604   // bitstream. Note that this does NOT imply that stream is valid, and will
605   // be decoded successfully. It DOES imply that all other decoder classes
606   // will fail to decode this input, though.
607   static bool IsSuitableDecoderFor(const std::string& input);
608 
609   // Assuming that |input| is the result of fixed-size delta-encoding
610   // that took place with the same value to |base| and over |num_of_deltas|
611   // original values, this will return the sequence of original values.
612   // If an error occurs (can happen if |input| is corrupt), an empty
613   // vector will be returned.
614   static std::vector<absl::optional<uint64_t>> DecodeDeltas(
615       const std::string& input,
616       absl::optional<uint64_t> base,
617       size_t num_of_deltas);
618 
619  private:
620   // Reads the encoding header in |input| and returns a FixedLengthDeltaDecoder
621   // with the corresponding configuration, that can be used to decode the
622   // values in |input|.
623   // If the encoding header is corrupt (contains an illegal configuration),
624   // nullptr will be returned.
625   // When a valid FixedLengthDeltaDecoder is returned, this does not mean that
626   // the entire stream is free of error. Rather, only the encoding header is
627   // examined and guaranteed.
628   static std::unique_ptr<FixedLengthDeltaDecoder> Create(
629       const std::string& input,
630       absl::optional<uint64_t> base,
631       size_t num_of_deltas);
632 
633   // FixedLengthDeltaDecoder objects are to be created by DecodeDeltas() and
634   // released by it before it returns. They're mostly a convenient way to
635   // avoid having to pass a lot of state between different functions.
636   // Therefore, it was deemed acceptable that |reader| does not own the buffer
637   // it reads, meaning the lifetime of |this| must not exceed the lifetime
638   // of |reader|'s underlying buffer.
639   FixedLengthDeltaDecoder(std::unique_ptr<rtc::BitBuffer> reader,
640                           const FixedLengthEncodingParameters& params,
641                           absl::optional<uint64_t> base,
642                           size_t num_of_deltas);
643 
644   // Perform the decoding using the parameters given to the ctor.
645   std::vector<absl::optional<uint64_t>> Decode();
646 
647   // Decode a varint and write it to |output|. Return value indicates success
648   // or failure. In case of failure, no guarantees are made about the contents
649   // of |output| or the results of additional reads.
650   bool ParseVarInt(uint64_t* output);
651 
652   // Attempt to parse a delta from the input reader.
653   // Returns true/false for success/failure.
654   // Writes the delta into |delta| if successful.
655   bool ParseDelta(uint64_t* delta);
656 
657   // Add |delta| to |base| to produce the next value in a sequence.
658   // The delta is applied as signed/unsigned depending on the parameters
659   // given to the ctor. Wrap-around is taken into account according to the
660   // values' width, as specified by the aforementioned encoding parameters.
661   uint64_t ApplyDelta(uint64_t base, uint64_t delta) const;
662 
663   // Helpers for ApplyDelta().
664   uint64_t ApplyUnsignedDelta(uint64_t base, uint64_t delta) const;
665   uint64_t ApplySignedDelta(uint64_t base, uint64_t delta) const;
666 
667   // Reader of the input stream to be decoded. Does not own that buffer.
668   // See comment above ctor for details.
669   const std::unique_ptr<rtc::BitBuffer> reader_;
670 
671   // The parameters according to which encoding will be done (width of
672   // fields, whether signed deltas should be used, etc.)
673   const FixedLengthEncodingParameters params_;
674 
675   // The encoding scheme assumes that at least one value is transmitted OOB,
676   // so that the first value can be encoded as a delta from that OOB value,
677   // which is |base_|.
678   const absl::optional<uint64_t> base_;
679 
680   // The number of values to be known to be decoded.
681   const size_t num_of_deltas_;
682 
683   RTC_DISALLOW_COPY_AND_ASSIGN(FixedLengthDeltaDecoder);
684 };
685 
IsSuitableDecoderFor(const std::string & input)686 bool FixedLengthDeltaDecoder::IsSuitableDecoderFor(const std::string& input) {
687   if (input.length() < kBitsInHeaderForEncodingType) {
688     return false;
689   }
690 
691   rtc::BitBuffer reader(reinterpret_cast<const uint8_t*>(&input[0]),
692                         kBitsInHeaderForEncodingType);
693 
694   uint32_t encoding_type_bits;
695   const bool result =
696       reader.ReadBits(&encoding_type_bits, kBitsInHeaderForEncodingType);
697   RTC_DCHECK(result);
698 
699   const auto encoding_type = static_cast<EncodingType>(encoding_type_bits);
700   return encoding_type ==
701              EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt ||
702          encoding_type ==
703              EncodingType::kFixedSizeSignedDeltasEarlyWrapAndOptSupported;
704 }
705 
DecodeDeltas(const std::string & input,absl::optional<uint64_t> base,size_t num_of_deltas)706 std::vector<absl::optional<uint64_t>> FixedLengthDeltaDecoder::DecodeDeltas(
707     const std::string& input,
708     absl::optional<uint64_t> base,
709     size_t num_of_deltas) {
710   auto decoder = FixedLengthDeltaDecoder::Create(input, base, num_of_deltas);
711   if (!decoder) {
712     return std::vector<absl::optional<uint64_t>>();
713   }
714 
715   return decoder->Decode();
716 }
717 
Create(const std::string & input,absl::optional<uint64_t> base,size_t num_of_deltas)718 std::unique_ptr<FixedLengthDeltaDecoder> FixedLengthDeltaDecoder::Create(
719     const std::string& input,
720     absl::optional<uint64_t> base,
721     size_t num_of_deltas) {
722   if (input.length() < kBitsInHeaderForEncodingType) {
723     return nullptr;
724   }
725 
726   auto reader = std::make_unique<rtc::BitBuffer>(
727       reinterpret_cast<const uint8_t*>(&input[0]), input.length());
728 
729   // Encoding type
730   uint32_t encoding_type_bits;
731   const bool result =
732       reader->ReadBits(&encoding_type_bits, kBitsInHeaderForEncodingType);
733   RTC_DCHECK(result);
734   const EncodingType encoding = static_cast<EncodingType>(encoding_type_bits);
735   if (encoding != EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt &&
736       encoding !=
737           EncodingType::kFixedSizeSignedDeltasEarlyWrapAndOptSupported) {
738     RTC_LOG(LS_WARNING) << "Unrecognized encoding type.";
739     return nullptr;
740   }
741 
742   uint32_t read_buffer;
743 
744   // delta_width_bits
745   if (!reader->ReadBits(&read_buffer, kBitsInHeaderForDeltaWidthBits)) {
746     return nullptr;
747   }
748   RTC_DCHECK_LE(read_buffer, 64 - 1);  // See encoding for -1's rationale.
749   const uint64_t delta_width_bits =
750       read_buffer + 1;  // See encoding for +1's rationale.
751 
752   // signed_deltas, values_optional, value_width_bits
753   bool signed_deltas;
754   bool values_optional;
755   uint64_t value_width_bits;
756   if (encoding == EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt) {
757     signed_deltas = kDefaultSignedDeltas;
758     values_optional = kDefaultValuesOptional;
759     value_width_bits = kDefaultValueWidthBits;
760   } else {
761     // signed_deltas
762     if (!reader->ReadBits(&read_buffer, kBitsInHeaderForSignedDeltas)) {
763       return nullptr;
764     }
765     signed_deltas = rtc::dchecked_cast<bool>(read_buffer);
766 
767     // values_optional
768     if (!reader->ReadBits(&read_buffer, kBitsInHeaderForValuesOptional)) {
769       return nullptr;
770     }
771     RTC_DCHECK_LE(read_buffer, 1);
772     values_optional = rtc::dchecked_cast<bool>(read_buffer);
773 
774     // value_width_bits
775     if (!reader->ReadBits(&read_buffer, kBitsInHeaderForValueWidthBits)) {
776       return nullptr;
777     }
778     RTC_DCHECK_LE(read_buffer, 64 - 1);  // See encoding for -1's rationale.
779     value_width_bits = read_buffer + 1;  // See encoding for +1's rationale.
780   }
781 
782   // Note: Because of the way the parameters are read, it is not possible
783   // for illegal values to be read. We check nevertheless, in case the code
784   // changes in the future in a way that breaks this promise.
785   if (!FixedLengthEncodingParameters::ValidParameters(
786           delta_width_bits, signed_deltas, values_optional, value_width_bits)) {
787     RTC_LOG(LS_WARNING) << "Corrupt log; illegal encoding parameters.";
788     return nullptr;
789   }
790 
791   FixedLengthEncodingParameters params(delta_width_bits, signed_deltas,
792                                        values_optional, value_width_bits);
793   return absl::WrapUnique(new FixedLengthDeltaDecoder(std::move(reader), params,
794                                                       base, num_of_deltas));
795 }
796 
FixedLengthDeltaDecoder(std::unique_ptr<rtc::BitBuffer> reader,const FixedLengthEncodingParameters & params,absl::optional<uint64_t> base,size_t num_of_deltas)797 FixedLengthDeltaDecoder::FixedLengthDeltaDecoder(
798     std::unique_ptr<rtc::BitBuffer> reader,
799     const FixedLengthEncodingParameters& params,
800     absl::optional<uint64_t> base,
801     size_t num_of_deltas)
802     : reader_(std::move(reader)),
803       params_(params),
804       base_(base),
805       num_of_deltas_(num_of_deltas) {
806   RTC_DCHECK(reader_);
807 }
808 
Decode()809 std::vector<absl::optional<uint64_t>> FixedLengthDeltaDecoder::Decode() {
810   RTC_DCHECK(reader_);
811 
812   std::vector<bool> existing_values(num_of_deltas_);
813   if (params_.values_optional()) {
814     for (size_t i = 0; i < num_of_deltas_; ++i) {
815       uint32_t exists;
816       if (!reader_->ReadBits(&exists, 1u)) {
817         RTC_LOG(LS_WARNING) << "Failed to read existence-indicating bit.";
818         return std::vector<absl::optional<uint64_t>>();
819       }
820       RTC_DCHECK_LE(exists, 1u);
821       existing_values[i] = (exists == 1);
822     }
823   } else {
824     std::fill(existing_values.begin(), existing_values.end(), true);
825   }
826 
827   absl::optional<uint64_t> previous = base_;
828   std::vector<absl::optional<uint64_t>> values(num_of_deltas_);
829 
830   for (size_t i = 0; i < num_of_deltas_; ++i) {
831     if (!existing_values[i]) {
832       RTC_DCHECK(params_.values_optional());
833       continue;
834     }
835 
836     if (!previous) {
837       // If the base is non-existent, the first existent value is encoded as
838       // a varint, rather than as a delta.
839       RTC_DCHECK(!base_.has_value());
840       uint64_t first_value;
841       if (!ParseVarInt(&first_value)) {
842         RTC_LOG(LS_WARNING) << "Failed to read first value.";
843         return std::vector<absl::optional<uint64_t>>();
844       }
845       values[i] = first_value;
846     } else {
847       uint64_t delta;
848       if (!ParseDelta(&delta)) {
849         return std::vector<absl::optional<uint64_t>>();
850       }
851       values[i] = ApplyDelta(previous.value(), delta);
852     }
853 
854     previous = values[i];
855   }
856 
857   return values;
858 }
859 
ParseVarInt(uint64_t * output)860 bool FixedLengthDeltaDecoder::ParseVarInt(uint64_t* output) {
861   RTC_DCHECK(reader_);
862   return DecodeVarInt(reader_.get(), output) != 0;
863 }
864 
ParseDelta(uint64_t * delta)865 bool FixedLengthDeltaDecoder::ParseDelta(uint64_t* delta) {
866   RTC_DCHECK(reader_);
867 
868   // BitBuffer and BitBufferWriter read/write higher bits before lower bits.
869 
870   const size_t lower_bit_count =
871       std::min<uint64_t>(params_.delta_width_bits(), 32u);
872   const size_t higher_bit_count = (params_.delta_width_bits() <= 32u)
873                                       ? 0
874                                       : params_.delta_width_bits() - 32u;
875 
876   uint32_t lower_bits;
877   uint32_t higher_bits;
878 
879   if (higher_bit_count > 0) {
880     if (!reader_->ReadBits(&higher_bits, higher_bit_count)) {
881       RTC_LOG(LS_WARNING) << "Failed to read higher half of delta.";
882       return false;
883     }
884   } else {
885     higher_bits = 0;
886   }
887 
888   if (!reader_->ReadBits(&lower_bits, lower_bit_count)) {
889     RTC_LOG(LS_WARNING) << "Failed to read lower half of delta.";
890     return false;
891   }
892 
893   const uint64_t lower_bits_64 = static_cast<uint64_t>(lower_bits);
894   const uint64_t higher_bits_64 = static_cast<uint64_t>(higher_bits);
895 
896   *delta = (higher_bits_64 << 32) | lower_bits_64;
897   return true;
898 }
899 
ApplyDelta(uint64_t base,uint64_t delta) const900 uint64_t FixedLengthDeltaDecoder::ApplyDelta(uint64_t base,
901                                              uint64_t delta) const {
902   RTC_DCHECK_LE(base, MaxUnsignedValueOfBitWidth(params_.value_width_bits()));
903   RTC_DCHECK_LE(delta, MaxUnsignedValueOfBitWidth(params_.delta_width_bits()));
904   return params_.signed_deltas() ? ApplySignedDelta(base, delta)
905                                  : ApplyUnsignedDelta(base, delta);
906 }
907 
ApplyUnsignedDelta(uint64_t base,uint64_t delta) const908 uint64_t FixedLengthDeltaDecoder::ApplyUnsignedDelta(uint64_t base,
909                                                      uint64_t delta) const {
910   // Note: May still be used if signed deltas used.
911   RTC_DCHECK_LE(base, MaxUnsignedValueOfBitWidth(params_.value_width_bits()));
912   RTC_DCHECK_LE(delta, MaxUnsignedValueOfBitWidth(params_.delta_width_bits()));
913   return (base + delta) & params_.value_mask();
914 }
915 
ApplySignedDelta(uint64_t base,uint64_t delta) const916 uint64_t FixedLengthDeltaDecoder::ApplySignedDelta(uint64_t base,
917                                                    uint64_t delta) const {
918   RTC_DCHECK(params_.signed_deltas());
919   RTC_DCHECK_LE(base, MaxUnsignedValueOfBitWidth(params_.value_width_bits()));
920   RTC_DCHECK_LE(delta, MaxUnsignedValueOfBitWidth(params_.delta_width_bits()));
921 
922   const uint64_t top_bit = static_cast<uint64_t>(1)
923                            << (params_.delta_width_bits() - 1);
924 
925   const bool positive_delta = ((delta & top_bit) == 0);
926   if (positive_delta) {
927     return ApplyUnsignedDelta(base, delta);
928   }
929 
930   const uint64_t delta_abs = (~delta & params_.delta_mask()) + 1;
931   return (base - delta_abs) & params_.value_mask();
932 }
933 
934 }  // namespace
935 
EncodeDeltas(absl::optional<uint64_t> base,const std::vector<absl::optional<uint64_t>> & values)936 std::string EncodeDeltas(absl::optional<uint64_t> base,
937                          const std::vector<absl::optional<uint64_t>>& values) {
938   // TODO(eladalon): Support additional encodings.
939   return FixedLengthDeltaEncoder::EncodeDeltas(base, values);
940 }
941 
DecodeDeltas(const std::string & input,absl::optional<uint64_t> base,size_t num_of_deltas)942 std::vector<absl::optional<uint64_t>> DecodeDeltas(
943     const std::string& input,
944     absl::optional<uint64_t> base,
945     size_t num_of_deltas) {
946   RTC_DCHECK_GT(num_of_deltas, 0);  // Allows empty vector to indicate error.
947 
948   // The empty string is a special case indicating that all values were equal
949   // to the base.
950   if (input.empty()) {
951     std::vector<absl::optional<uint64_t>> result(num_of_deltas);
952     std::fill(result.begin(), result.end(), base);
953     return result;
954   }
955 
956   if (FixedLengthDeltaDecoder::IsSuitableDecoderFor(input)) {
957     return FixedLengthDeltaDecoder::DecodeDeltas(input, base, num_of_deltas);
958   }
959 
960   RTC_LOG(LS_WARNING) << "Could not decode delta-encoded stream.";
961   return std::vector<absl::optional<uint64_t>>();
962 }
963 
SetFixedLengthEncoderDeltaSignednessForTesting(bool signedness)964 void SetFixedLengthEncoderDeltaSignednessForTesting(bool signedness) {
965   g_force_unsigned_for_testing = !signedness;
966   g_force_signed_for_testing = signedness;
967 }
968 
UnsetFixedLengthEncoderDeltaSignednessForTesting()969 void UnsetFixedLengthEncoderDeltaSignednessForTesting() {
970   g_force_unsigned_for_testing = false;
971   g_force_signed_for_testing = false;
972 }
973 
974 }  // namespace webrtc
975