OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef MEDIA_CAST_COMMON_EXPANDED_VALUE_BASE_H_ |
| 6 #define MEDIA_CAST_COMMON_EXPANDED_VALUE_BASE_H_ |
| 7 |
| 8 #include <stdint.h> |
| 9 |
| 10 #include <limits> |
| 11 |
| 12 namespace media { |
| 13 namespace cast { |
| 14 |
| 15 // Abstract base template class for common "sequence value" data types such as |
| 16 // RtpTimeTicks, FrameId, or PacketId which generally increment/decrement in |
| 17 // predictable amounts as media is streamed, and which often need to be reliably |
| 18 // truncated and re-expanded for over-the-wire transmission. |
| 19 // |
| 20 // FullPrecisionInteger should be a signed integer POD type that is of |
| 21 // sufficiently high precision to never wrap-around in the system. Subclass is |
| 22 // the class inheriting the common functionality provided in this template, and |
| 23 // is used to provide operator overloads. The Subclass must friend this class |
| 24 // to enable these operator overloads. |
| 25 // |
| 26 // Please see RtpTimeTicks and unit test code for examples of how to define |
| 27 // Subclasses and add features specific to their concrete data type, and how to |
| 28 // use data types derived from ExpandedValueBase. For example, a RtpTimeTicks |
| 29 // adds math operators consisting of the meaningful and valid set of operations |
| 30 // allowed for doing "time math." On the other hand, FrameId only adds math |
| 31 // operators for incrementing/decrementing since multiplication and division are |
| 32 // meaningless. |
| 33 template <typename FullPrecisionInteger, class Subclass> |
| 34 class ExpandedValueBase { |
| 35 static_assert(std::numeric_limits<FullPrecisionInteger>::is_signed, |
| 36 "FullPrecisionInteger must be a signed integer."); |
| 37 static_assert(std::numeric_limits<FullPrecisionInteger>::is_integer, |
| 38 "FullPrecisionInteger must be a signed integer."); |
| 39 |
| 40 public: |
| 41 // Methods that return the lower bits of this value. This should only be used |
| 42 // for serializing/wire-formatting, and not to subvert the restricted set of |
| 43 // operators allowed on this data type. |
| 44 uint8_t lower_8_bits() const { return static_cast<uint8_t>(value_); } |
| 45 uint16_t lower_16_bits() const { return static_cast<uint16_t>(value_); } |
| 46 uint32_t lower_32_bits() const { return static_cast<uint32_t>(value_); } |
| 47 |
| 48 // Compute the value closest to |this| value whose lower bits are those of |
| 49 // |x|. The result is always within |max_distance_for_expansion()| of |this| |
| 50 // value. |
| 51 // |
| 52 // The purpose of this method is to re-instantiate an original value from its |
| 53 // truncated form, usually when deserializing off-the-wire. Therefore, it is |
| 54 // always important to call this method on an instance known to be close in |
| 55 // distance to |x|. |
| 56 template <typename ShortUnsigned> |
| 57 Subclass Expand(ShortUnsigned x) const { |
| 58 static_assert(!std::numeric_limits<ShortUnsigned>::is_signed, |
| 59 "|x| must be an unsigned integer."); |
| 60 static_assert(std::numeric_limits<ShortUnsigned>::is_integer, |
| 61 "|x| must be an unsigned integer."); |
| 62 static_assert(sizeof(ShortUnsigned) <= sizeof(FullPrecisionInteger), |
| 63 "|x| must fit within the FullPrecisionInteger."); |
| 64 |
| 65 if (sizeof(ShortUnsigned) < sizeof(FullPrecisionInteger)) { |
| 66 // Initially, the |result| is composed of upper bits from |value_| and |
| 67 // lower bits from |x|. |
| 68 const FullPrecisionInteger short_max = |
| 69 std::numeric_limits<ShortUnsigned>::max(); |
| 70 FullPrecisionInteger result = (value_ & ~short_max) | x; |
| 71 |
| 72 // Determine whether the shorter integer type encountered wrap-around, and |
| 73 // increment/decrement the upper bits by one to account for that. |
| 74 const FullPrecisionInteger diff = result - value_; |
| 75 const FullPrecisionInteger pivot = |
| 76 max_distance_for_expansion<ShortUnsigned>(); |
| 77 if (diff > pivot) |
| 78 result -= short_max + 1; |
| 79 else if (diff < -(pivot + 1)) |
| 80 result += short_max + 1; |
| 81 return Subclass(result); |
| 82 } else { |
| 83 return Subclass(x); |
| 84 } |
| 85 } |
| 86 |
| 87 // Comparison operators. |
| 88 bool operator==(Subclass rhs) const { return value_ == rhs.value_; } |
| 89 bool operator!=(Subclass rhs) const { return value_ != rhs.value_; } |
| 90 bool operator<(Subclass rhs) const { return value_ < rhs.value_; } |
| 91 bool operator>(Subclass rhs) const { return value_ > rhs.value_; } |
| 92 bool operator<=(Subclass rhs) const { return value_ <= rhs.value_; } |
| 93 bool operator>=(Subclass rhs) const { return value_ >= rhs.value_; } |
| 94 |
| 95 // (De)Serialize for transmission over IPC. Do not use these to subvert the |
| 96 // valid set of operators allowed by this class or its Subclass. |
| 97 uint64_t SerializeForIPC() const { |
| 98 static_assert(sizeof(uint64_t) >= sizeof(FullPrecisionInteger), |
| 99 "Cannot serialize FullPrecisionInteger into an uint64_t."); |
| 100 return static_cast<uint64_t>(value_); |
| 101 } |
| 102 static Subclass DeserializeForIPC(uint64_t serialized) { |
| 103 return Subclass(static_cast<FullPrecisionInteger>(serialized)); |
| 104 } |
| 105 |
| 106 // Design limit: Values that are truncated to the ShortUnsigned type must be |
| 107 // no more than this maximum distance from each other in order to ensure the |
| 108 // original value can be determined correctly. |
| 109 template <typename ShortUnsigned> |
| 110 static FullPrecisionInteger max_distance_for_expansion() { |
| 111 return std::numeric_limits<ShortUnsigned>::max() / 2; |
| 112 } |
| 113 |
| 114 protected: |
| 115 // Only subclasses are permitted to instantiate directly. |
| 116 explicit ExpandedValueBase(FullPrecisionInteger value) : value_(value) {} |
| 117 |
| 118 FullPrecisionInteger value_; |
| 119 }; |
| 120 |
| 121 } // namespace cast |
| 122 } // namespace media |
| 123 |
| 124 #endif // MEDIA_CAST_COMMON_EXPANDED_VALUE_BASE_H_ |
OLD | NEW |