1 /*
2  * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef HISTREAMER_BIT_READER_H
17 #define HISTREAMER_BIT_READER_H
18 
19 #include <algorithm>
20 #include <cstdint> // NOLINT
21 
22 namespace OHOS {
23 namespace Media {
24 namespace Plugin {
25 namespace Ffmpeg {
26 class BitReader {
27 public:
28     BitReader();
29 
30     BitReader(const uint8_t* buffer, size_t bufferSize);
31 
32     BitReader(const uint8_t* begin, const uint8_t* end);
33 
34     template <typename T>
BitReader(const T * buffer,size_t bufferSize)35     BitReader(const T* buffer, size_t bufferSize) : BitReader(buffer, buffer + bufferSize)
36     {
37     }
38 
39     template <typename T>
BitReader(const T * begin,const T * end)40     BitReader(const T* begin, const T* end)
41         : BitReader(reinterpret_cast<const uint8_t*>(begin), reinterpret_cast<const uint8_t*>(end)) // NOLINT: cast
42     {
43     }
44 
45     ~BitReader();
46 
47     template <typename T, typename std::enable_if<std::is_unsigned<T>::value, bool>::type = true>
ReadBits(uint8_t bits,T & val)48     bool ReadBits(uint8_t bits, T& val)
49     {
50         if (GetAvailableBits() < bits) {
51             return false;
52         }
53         val = 0;
54         uint8_t remainBits = bits;
55         for (uint8_t toRead = 0; remainBits; remainBits -= toRead) {
56             if (availBits_ == 0) {
57                 ++cur_;
58                 availBits_ = 8; // 8
59             }
60             toRead = std::min(remainBits, availBits_);
61             uint8_t shift = availBits_ - toRead;
62             uint64_t mask = 0xFF >> (0x08 - toRead);
63             val = static_cast<T>((val << toRead) | static_cast<T>(((*cur_) >> shift) & mask));
64             availBits_ -= toRead;
65         }
66         return true;
67     }
68 
69     size_t GetAvailableBits() const;
70 
71     const uint8_t* GetCurrentPtr() const;
72 
73     void SkipBits(size_t bits);
74 
75     bool SeekTo(size_t bitPos);
76 
77     template <typename T>
PeekBits(uint8_t bits,T & val)78     bool PeekBits(uint8_t bits, T& val)
79     {
80         auto tmp = *this;
81         return tmp.ReadBits<T>(bits, val);
82     }
83 
84     template <typename T>
Reset(const T * buffer,size_t bufferSize)85     void Reset(const T* buffer, size_t bufferSize)
86     {
87         Reset(buffer, buffer + bufferSize);
88     }
89 
90     template <typename T>
Reset(const T * begin,const T * end)91     void Reset(const T* begin, const T* end)
92     {
93         Reset(reinterpret_cast<const uint8_t*>(begin), reinterpret_cast<const uint8_t*>(end)); // NOLINT: cast
94     }
95 
96 private:
97     void Reset(const uint8_t* begin, const uint8_t* end);
98 
99     const uint8_t* begin_;
100     const uint8_t* cur_;
101     const uint8_t* end_;
102     uint8_t availBits_{8};
103 };
104 } // namespace Ffmpeg
105 } // namespace Plugin
106 } // namespace Media
107 } // namespace OHOS
108 #endif // HISTREAMER_BIT_READER_H
109