• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       newCfgData_(nullptr),
46       newCfgDataSize_(0),
47       nalUnitLen_(AVC_NAL_SIZE_LEN_4),
48       version_(1),
49       profile_(0),
50       profile_compat_(0),
51       level_(0),
52       needAddFrameHeader_(false)
53 {
54     cfgSet.count = 0;
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 (auto 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 (auto 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 (auto 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 "u", 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, tmp2;
147     if (!bitReader_.ReadBits(1, tmp1) || !bitReader_.ReadBits(1, tmp2)) {
148         return false;
149     }
150     len = ((tmp1 << 8) | tmp2) & 0xFFFF;  // 8
151     if (len > bitReader_.GetAvailableBits()) {
152         MEDIA_LOG_E("len: %" PUBLIC_LOG "u is too large", len);
153         return false;
154     }
155     return true;
156 }
157 
ParseNalHeader()158 bool AVCConfigDataParser::ParseNalHeader()
159 {
160     if (bitReader_.GetAvailableBits() < AVC_MIN_CONFIG_DATA_SIZE) {
161         MEDIA_LOG_E("Config data size is smaller than MIN: %" PUBLIC_LOG "d",
162                     static_cast<int32_t>(AVC_MIN_CONFIG_DATA_SIZE));
163         return false;
164     }
165     auto ret = bitReader_.ReadBits(1, version_); // configurationVersion = 1
166     if ((ret == false) || (version_ != 1)) {
167         // Some parser has parser config data, so just return
168         MEDIA_LOG_I("Unsupported config data, version: %" PUBLIC_LOG "u", version_);
169         return false;
170     }
171     if (!bitReader_.ReadBits(1, profile_)) { // AVCProfileIndication
172         return false;
173     }
174     if (!bitReader_.ReadBits(1, profile_compat_)) { // profile_compatibility
175         return false;
176     }
177     if (!bitReader_.ReadBits(1, level_)) { // AVCLevelIndication
178         return false;
179     }
180     if (!ParseNalUnitSizeLen()) {
181         return false;
182     }
183     return true;
184 }
185 
CreateConfigSetItem(const uint32_t len)186 bool AVCConfigDataParser::CreateConfigSetItem(const uint32_t len)
187 {
188     uint32_t itemLen = static_cast<uint32_t>(sizeof(NalConfigItem)) + AVC_NAL_HEADER_LEN + len;
189     cfgSet.items[cfgSet.count] = reinterpret_cast<NalConfigItem*>(new (std::nothrow) uint8_t[itemLen]);
190     if (cfgSet.items[cfgSet.count] == nullptr) {
191         MEDIA_LOG_E("Alloc config set item memory fail");
192         return false;
193     }
194     auto& item = cfgSet.items[cfgSet.count];
195     // Add start code: 0x00000001
196     item->SpsOrPps[0] = 0;
197     item->SpsOrPps[1] = 0;
198     item->SpsOrPps[2] = 0;  // 2
199     item->SpsOrPps[3] = 1;  // 3
200     item->len = AVC_NAL_HEADER_LEN + len;
201     return true;
202 }
203 
ParseSpsOrPps(const uint32_t mask)204 bool AVCConfigDataParser::ParseSpsOrPps(const uint32_t mask)
205 {
206     uint32_t setCount = 0;
207     if (!bitReader_.ReadBits(1, setCount)) {
208         return false;
209     }
210     setCount &= mask;
211     for (auto idx = 0; idx < setCount; ++idx) {
212         if (bitReader_.GetAvailableBits() < 2) { // 2
213             MEDIA_LOG_E("Sps data err");
214             return false;
215         }
216         uint32_t len = 0;
217         if (!GetSpsOrPpsLen(len)) {
218             MEDIA_LOG_E("Get sps/pps len fail");
219             return false;
220         }
221         if (cfgSet.count >= AVC_MAX_CONFIG_ITEM) {
222             MEDIA_LOG_E("config set count is larger than: %" PUBLIC_LOG "d",
223                         static_cast<int32_t>(AVC_MAX_CONFIG_ITEM));
224             return false;
225         }
226         if (!CreateConfigSetItem(len)) {
227             MEDIA_LOG_E("Create config set item fail");
228             return false;
229         }
230         (void)memcpy_s(&cfgSet.items[cfgSet.count]->SpsOrPps[AVC_NAL_HEADER_LEN], static_cast<size_t>(len),
231                        bitReader_.GetCurrentPtr(), static_cast<size_t>(len));
232         cfgSet.count++;
233         bitReader_.SkipBits(len);
234     }
235     return true;
236 }
237 
ParseNal()238 bool AVCConfigDataParser::ParseNal()
239 {
240     if (!ParseNalHeader()) {
241         MEDIA_LOG_D("Parse NAL header fail");
242         return false;
243     }
244     // Parse SPS
245     if (!ParseSpsOrPps(0x1F)) {
246         MEDIA_LOG_E("Parse SPS fail");
247         return false;
248     }
249     if (bitReader_.GetAvailableBits() < 1) {
250         return false;
251     }
252     // Parse PPS
253     if (!ParseSpsOrPps(0xFF)) {
254         MEDIA_LOG_E("Parse PPS fail");
255         return false;
256     }
257     return true;
258 }
259 } // namespace Ffmpeg
260 } // namespace Plugin
261 } // namespace Media
262 } // namespace OHOS
263 #endif
264