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