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 #ifdef VIDEO_SUPPORT
17 
18 #define HST_LOG_TAG "AVCConfigDataParser"
19 
20 #include "avc_config_data_parser.h"
21 #include <memory>
22 #include <cstring>
23 #include "bit_reader.h"
24 #include "foundation/log.h"
25 #include "securec.h"
26 
27 namespace OHOS {
28 namespace Media {
29 namespace Plugin {
30 namespace Ffmpeg {
31 #define AVC_MIN_CONFIG_DATA_SIZE 7
32 #define AVC_NAL_HEADER_LEN 4
33 
34 // refer to ISO/IEC 14496-15: AVC NAL size bytes should be 1, 2, 4
35 enum AVC_NAL_SIZE_LEN : int32_t {
36     AVC_NAL_SIZE_LEN_1 = 1,
37     AVC_NAL_SIZE_LEN_2 = 2,
38     AVC_NAL_SIZE_LEN_4 = 4,
39 };
40 
AVCConfigDataParser(const uint8_t * cfgData,const size_t cfgDataSize)41 AVCConfigDataParser::AVCConfigDataParser(const uint8_t* cfgData, const size_t cfgDataSize)
42     : bitReader_(cfgData, cfgDataSize),
43       cfgData_(cfgData),
44       cfgDataSize_(cfgDataSize),
45       version_(1),
46       profile_(0),
47       profile_compat_(0),
48       level_(0),
49       needAddFrameHeader_(false)
50 {
51     cfgSet.count = 0;
52     newCfgData_ = nullptr;
53     newCfgDataSize_ = 0;
54     nalUnitLen_ = AVC_NAL_SIZE_LEN_4;
55     for (int32_t i = 0; i < AVC_MAX_CONFIG_ITEM; i++) {
56         cfgSet.items[i] = nullptr;
57     }
58 }
59 
~AVCConfigDataParser()60 AVCConfigDataParser::~AVCConfigDataParser()
61 {
62     ClearConfigSet();
63 }
64 
ParseConfigData()65 bool AVCConfigDataParser::ParseConfigData()
66 {
67     if (!ParseNal()) {
68         if ((cfgDataSize_ < 3) || !((version_ == 0) && (profile_ == 0) && (profile_compat_ <= 1))) {  // 3
69             needAddFrameHeader_ = true;
70         }
71         if (cfgDataSize_ == 0) {
72             return false;
73         }
74         newCfgDataSize_ = cfgDataSize_;
75         newCfgData_ = std::shared_ptr<uint8_t>(new uint8_t[newCfgDataSize_], std::default_delete<uint8_t[]>());
76         if (newCfgData_ == nullptr) {
77             MEDIA_LOG_E("Alloc new config data memory fail");
78             return false;
79         }
80         (void)memcpy_s(newCfgData_.get(), cfgDataSize_, cfgData_, cfgDataSize_);
81         return true;
82     }
83 
84     needAddFrameHeader_ = true;
85     if (cfgSet.count == 0) {
86         return false;
87     }
88     for (uint32_t i = 0; i < cfgSet.count; ++i) {
89         newCfgDataSize_ += (cfgSet.items[i]->len & 0xFFF);
90     }
91     newCfgData_ = std::shared_ptr<uint8_t>(new uint8_t[newCfgDataSize_], std::default_delete<uint8_t[]>());
92     if (newCfgData_ == nullptr) {
93         MEDIA_LOG_E("Alloc new config data memory fail");
94         return false;
95     }
96     uint32_t usedLen = 0;
97     for (uint32_t i = 0; i < cfgSet.count; ++i) {
98         (void)memcpy_s(newCfgData_.get() + usedLen, cfgSet.items[i]->len, cfgSet.items[i]->SpsOrPps,
99                        cfgSet.items[i]->len);
100         usedLen += cfgSet.items[i]->len;
101     }
102     return true;
103 }
104 
IsNeedAddFrameHeader()105 bool AVCConfigDataParser::IsNeedAddFrameHeader()
106 {
107     return needAddFrameHeader_; // We can add this flag as specific header in newCfgData_, do it later
108 }
109 
GetNewConfigData(std::shared_ptr<uint8_t> & newCfgData,size_t & newCfgDataSize)110 bool AVCConfigDataParser::GetNewConfigData(std::shared_ptr<uint8_t>& newCfgData, size_t& newCfgDataSize)
111 {
112     if (newCfgData_ != nullptr) {
113         newCfgData = newCfgData_;
114         newCfgDataSize = newCfgDataSize_;
115         return true;
116     }
117 
118     return false;
119 }
120 
ClearConfigSet()121 void AVCConfigDataParser::ClearConfigSet()
122 {
123     for (uint32_t i = 0; i < cfgSet.count; i++) {
124         if (cfgSet.items[i]) {
125             delete[] reinterpret_cast<uint8_t*>(cfgSet.items[i]);
126         }
127     }
128 }
129 
ParseNalUnitSizeLen()130 bool AVCConfigDataParser::ParseNalUnitSizeLen()
131 {
132     uint8_t sizeLen_ = 0;
133     if (!bitReader_.ReadBits(1, sizeLen_)) {
134         return false;
135     }
136 
137     nalUnitLen_ = (sizeLen_ & 0x3) + 1; // lengthSize Minus One
138     if ((nalUnitLen_ != AVC_NAL_SIZE_LEN_1) && (nalUnitLen_ != AVC_NAL_SIZE_LEN_2) &&
139         (nalUnitLen_ != AVC_NAL_SIZE_LEN_4)) {
140         MEDIA_LOG_I("Unsupported config data, nalUnitLen_: " PUBLIC_LOG_U8, nalUnitLen_);
141         return false;
142     }
143 
144     return true;
145 }
146 
GetSpsOrPpsLen(uint32_t & len)147 bool AVCConfigDataParser::GetSpsOrPpsLen(uint32_t& len)
148 {
149     uint8_t tmp1;
150     uint8_t tmp2;
151     if (!bitReader_.ReadBits(1, tmp1) || !bitReader_.ReadBits(1, tmp2)) {
152         return false;
153     }
154     len = ((tmp1 << 8) | tmp2) & 0xFFFF;  // 8
155     if (len > bitReader_.GetAvailableBits()) {
156         MEDIA_LOG_E("len: " PUBLIC_LOG_U32 " is too large", len);
157         return false;
158     }
159     return true;
160 }
161 
ParseNalHeader()162 bool AVCConfigDataParser::ParseNalHeader()
163 {
164     if (bitReader_.GetAvailableBits() < AVC_MIN_CONFIG_DATA_SIZE) {
165         MEDIA_LOG_E("Config data size is smaller than MIN: " PUBLIC_LOG_D32,
166                     static_cast<int32_t>(AVC_MIN_CONFIG_DATA_SIZE));
167         return false;
168     }
169     auto ret = bitReader_.ReadBits(1, version_); // configurationVersion = 1
170     if ((ret == false) || (version_ != 1)) {
171         // Some parser has parser config data, so just return
172         MEDIA_LOG_I("Unsupported config data, version: " PUBLIC_LOG_U8, version_);
173         return false;
174     }
175     if (!bitReader_.ReadBits(1, profile_)) { // AVCProfileIndication
176         return false;
177     }
178     if (!bitReader_.ReadBits(1, profile_compat_)) { // profile_compatibility
179         return false;
180     }
181     if (!bitReader_.ReadBits(1, level_)) { // AVCLevelIndication
182         return false;
183     }
184     if (!ParseNalUnitSizeLen()) {
185         return false;
186     }
187     return true;
188 }
189 
CreateConfigSetItem(const uint32_t len)190 bool AVCConfigDataParser::CreateConfigSetItem(const uint32_t len)
191 {
192     uint32_t itemLen = static_cast<uint32_t>(sizeof(NalConfigItem)) + AVC_NAL_HEADER_LEN + len;
193     cfgSet.items[cfgSet.count] = reinterpret_cast<NalConfigItem*>(new (std::nothrow) uint8_t[itemLen]);
194     if (cfgSet.items[cfgSet.count] == nullptr) {
195         MEDIA_LOG_E("Alloc config set item memory fail");
196         return false;
197     }
198     auto& item = cfgSet.items[cfgSet.count];
199     // Add start code: 0x00000001
200     item->SpsOrPps[0] = 0;
201     item->SpsOrPps[1] = 0;
202     item->SpsOrPps[2] = 0;  // 2
203     item->SpsOrPps[3] = 1;  // 3
204     item->len = AVC_NAL_HEADER_LEN + len;
205     return true;
206 }
207 
ParseSpsOrPps(const uint32_t mask)208 bool AVCConfigDataParser::ParseSpsOrPps(const uint32_t mask)
209 {
210     uint32_t setCount = 0;
211     if (!bitReader_.ReadBits(1, setCount)) {
212         return false;
213     }
214     setCount &= mask;
215     for (uint32_t idx = 0; idx < setCount; ++idx) {
216         if (bitReader_.GetAvailableBits() < 2) { // 2
217             MEDIA_LOG_E("Sps data err");
218             return false;
219         }
220         uint32_t len = 0;
221         if (!GetSpsOrPpsLen(len)) {
222             MEDIA_LOG_E("Get sps/pps len fail");
223             return false;
224         }
225         if (cfgSet.count >= AVC_MAX_CONFIG_ITEM) {
226             MEDIA_LOG_E("config set count is larger than: " PUBLIC_LOG_D32,
227                         static_cast<int32_t>(AVC_MAX_CONFIG_ITEM));
228             return false;
229         }
230         if (!CreateConfigSetItem(len)) {
231             MEDIA_LOG_E("Create config set item fail");
232             return false;
233         }
234         (void)memcpy_s(&cfgSet.items[cfgSet.count]->SpsOrPps[AVC_NAL_HEADER_LEN], static_cast<size_t>(len),
235                        bitReader_.GetCurrentPtr(), static_cast<size_t>(len));
236         cfgSet.count++;
237         bitReader_.SkipBits(len);
238     }
239     return true;
240 }
241 
ParseNal()242 bool AVCConfigDataParser::ParseNal()
243 {
244     if (!ParseNalHeader()) {
245         MEDIA_LOG_D("Parse NAL header fail");
246         return false;
247     }
248     // Parse SPS
249     if (!ParseSpsOrPps(0x1F)) {
250         MEDIA_LOG_E("Parse SPS fail");
251         return false;
252     }
253     if (bitReader_.GetAvailableBits() < 1) {
254         return false;
255     }
256     // Parse PPS
257     if (!ParseSpsOrPps(0xFF)) {
258         MEDIA_LOG_E("Parse PPS fail");
259         return false;
260     }
261     return true;
262 }
263 } // namespace Ffmpeg
264 } // namespace Plugin
265 } // namespace Media
266 } // namespace OHOS
267 #endif
268