• 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 #define HST_LOG_TAG "AACDemuxerPlugin"
17 
18 #include "aac_demuxer_plugin.h"
19 #include <algorithm>
20 #include <cstdio>
21 #include <cstring>
22 #include <new>
23 #include <securec.h>
24 #include "foundation/log.h"
25 #include "osal/thread/scoped_lock.h"
26 #include "plugin/common/plugin_buffer.h"
27 #include "constants.h"
28 #include "osal/utils/util.h"
29 
30 namespace OHOS {
31 namespace Media {
32 namespace Plugin {
33 namespace AacDemuxer {
34 namespace {
35     constexpr uint32_t PROBE_READ_LENGTH = 2;
36     constexpr uint32_t GET_INFO_READ_LEN = 7;
37     constexpr uint32_t MEDIA_IO_SIZE = 2048;
38     constexpr uint32_t MAX_RANK = 100;
39     uint32_t usedDataSize_ = 0;
40     int samplingRateMap[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350};
41     int IsAACPattern(const uint8_t *data);
42     int Sniff(const std::string& name, std::shared_ptr<DataSource> dataSource);
43     Status RegisterPlugin(const std::shared_ptr<Register>& reg);
44 }
45 
AACDemuxerPlugin(std::string name)46 AACDemuxerPlugin::AACDemuxerPlugin(std::string name)
47     : DemuxerPlugin(std::move(name)),
48       ioContext_(),
49       fileSize_(0),
50       isSeekable_(false),
51       inIoBuffer_(nullptr),
52       inIoBufferSize_(MEDIA_IO_SIZE),
53       ioDataRemainSize_(0)
54 {
55     FALSE_LOG(memset_s(&aacDemuxerRst_, sizeof(aacDemuxerRst_), 0x00, sizeof(AACDemuxerRst)) == 0);
56     MEDIA_LOG_I("AACDemuxerPlugin, plugin name: " PUBLIC_LOG_S, pluginName_.c_str());
57 }
58 
~AACDemuxerPlugin()59 AACDemuxerPlugin::~AACDemuxerPlugin()
60 {
61     MEDIA_LOG_I("~AACDemuxerPlugin");
62 }
63 
SetDataSource(const std::shared_ptr<DataSource> & source)64 Status AACDemuxerPlugin::SetDataSource(const std::shared_ptr<DataSource>& source)
65 {
66     ioContext_.dataSource = source;
67     if (ioContext_.dataSource != nullptr) {
68         ioContext_.dataSource->GetSize(fileSize_);
69     }
70     MEDIA_LOG_I("fileSize_ " PUBLIC_LOG_ZU, fileSize_);
71     isSeekable_ = fileSize_ > 0 ? true : false;
72     return Status::OK;
73 }
74 
DoReadFromSource(uint32_t readSize)75 Status AACDemuxerPlugin::DoReadFromSource(uint32_t readSize)
76 {
77     if (readSize == 0) {
78         return Status::OK;
79     }
80     auto buffer  = std::make_shared<Buffer>();
81     auto bufData = buffer->AllocMemory(nullptr, readSize);
82     int retryTimes = 0;
83     MEDIA_LOG_D("readSize " PUBLIC_LOG_U32 " inIoBufferSize_ " PUBLIC_LOG_D32 "ioDataRemainSize_ "
84                 PUBLIC_LOG_U32, readSize, inIoBufferSize_, ioDataRemainSize_);
85     do {
86         if (isSeekable_) {
87             auto result = ioContext_.dataSource->ReadAt(ioContext_.offset, buffer, static_cast<size_t>(readSize));
88             MEDIA_LOG_D("ioContext_.offset " PUBLIC_LOG_U32, static_cast<uint32_t>(ioContext_.offset));
89             if (result != Status::OK) {
90                 MEDIA_LOG_W("read data from source warning " PUBLIC_LOG_D32, static_cast<int>(result));
91                 return result;
92             }
93         } else {
94             auto result = ioContext_.dataSource->ReadAt(0, buffer, static_cast<size_t>(readSize));
95             if (result != Status::OK) {
96                 MEDIA_LOG_W("read data from source warning " PUBLIC_LOG_D32, static_cast<int>(result));
97                 return result;
98             }
99         }
100 
101         MEDIA_LOG_D("bufData->GetSize() " PUBLIC_LOG_ZU, bufData->GetSize());
102         if (bufData->GetSize() > 0) {
103             if (readSize >= bufData->GetSize()) {
104                 (void)memcpy_s(inIoBuffer_ + ioDataRemainSize_, readSize,
105                     const_cast<uint8_t *>(bufData->GetReadOnlyData()), bufData->GetSize());
106             } else {
107                 MEDIA_LOG_E("Error: readSize < bufData->GetSize()");
108                 return Status::ERROR_UNKNOWN;
109             }
110             if (isSeekable_) {
111                 ioContext_.offset += bufData->GetSize();
112             }
113             ioDataRemainSize_  += bufData->GetSize();
114         }
115         if (bufData->GetSize() == 0 && ioDataRemainSize_ == 0 && retryTimes < 200) { // 200
116             OSAL::SleepFor(30); // 30
117             retryTimes++;
118             continue;
119         }
120         if (retryTimes >= 200) { // 200
121             MEDIA_LOG_E("Warning: not end of file, but do not have enough data");
122             return Status::ERROR_NOT_ENOUGH_DATA;
123         }
124         break;
125     } while (true);
126     return Status::OK;
127 }
128 
GetDataFromSource()129 Status AACDemuxerPlugin::GetDataFromSource()
130 {
131     uint32_t ioNeedReadSize = inIoBufferSize_ - ioDataRemainSize_;
132     MEDIA_LOG_D("ioDataRemainSize_ " PUBLIC_LOG_U32, " ioNeedReadSize " PUBLIC_LOG_U32, ioDataRemainSize_,
133                 ioNeedReadSize);
134     if (ioDataRemainSize_) {
135         // 将剩余数据移动到buffer的起始位置
136         auto ret = memmove_s(inIoBuffer_,
137                              ioDataRemainSize_,
138                              inIoBuffer_ + usedDataSize_,
139                              ioDataRemainSize_);
140         if (ret != 0) {
141             MEDIA_LOG_E("copy buffer error(" PUBLIC_LOG_D32, ret);
142             return Status::ERROR_UNKNOWN;
143         }
144         ret = memset_s(inIoBuffer_ + ioDataRemainSize_, ioNeedReadSize, 0x00, ioNeedReadSize);
145         if (ret != 0) {
146             MEDIA_LOG_E("memset_s buffer error(" PUBLIC_LOG_D32, ret);
147             return Status::ERROR_UNKNOWN;
148         }
149     }
150     if (isSeekable_) {
151         if (ioContext_.offset >= fileSize_ && ioDataRemainSize_ == 0) {
152             ioContext_.eos = true;
153             ioContext_.offset = 0;
154             return Status::END_OF_STREAM;
155         }
156         if (ioContext_.offset + ioNeedReadSize > fileSize_) {
157             ioNeedReadSize = fileSize_ - ioContext_.offset; // 在读取文件即将结束时,剩余数据不足,更新读取长度
158         }
159     }
160 
161     return DoReadFromSource(ioNeedReadSize);
162 }
163 
GetMediaInfo(MediaInfo & mediaInfo)164 Status AACDemuxerPlugin::GetMediaInfo(MediaInfo& mediaInfo)
165 {
166     Status retStatus = GetDataFromSource();
167     if (retStatus != Status::OK) {
168         return retStatus;
169     }
170     int ret = AudioDemuxerAACPrepare(inIoBuffer_, ioDataRemainSize_, &aacDemuxerRst_);
171     if (ret == 0) {
172         mediaInfo.tracks.resize(1);
173         if (aacDemuxerRst_.frameChannels == 1) {
174             mediaInfo.tracks[0].Insert<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::MONO);
175         } else {
176             mediaInfo.tracks[0].Insert<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::STEREO);
177         }
178         mediaInfo.tracks[0].Insert<Tag::MEDIA_TYPE>(MediaType::AUDIO);
179         mediaInfo.tracks[0].Insert<Tag::AUDIO_SAMPLE_RATE>(aacDemuxerRst_.frameSampleRate);
180         mediaInfo.tracks[0].Insert<Tag::MEDIA_BITRATE>(aacDemuxerRst_.frameBitrateKbps);
181         mediaInfo.tracks[0].Insert<Tag::AUDIO_CHANNELS>(aacDemuxerRst_.frameChannels);
182         mediaInfo.tracks[0].Insert<Tag::TRACK_ID>(0);
183         mediaInfo.tracks[0].Insert<Tag::MIME>(MEDIA_MIME_AUDIO_AAC);
184         mediaInfo.tracks[0].Insert<Tag::AUDIO_MPEG_VERSION>(aacDemuxerRst_.mpegVersion);
185         mediaInfo.tracks[0].Insert<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::S16);
186         mediaInfo.tracks[0].Insert<Tag::AUDIO_SAMPLE_PER_FRAME>(1024);   // 1024
187         mediaInfo.tracks[0].Insert<Tag::AUDIO_AAC_PROFILE>(AudioAacProfile::LC);
188         mediaInfo.tracks[0].Insert<Tag::AUDIO_AAC_STREAM_FORMAT>(AudioAacStreamFormat::MP4ADTS);
189         return Status::OK;
190     } else {
191         return Status::ERROR_UNSUPPORTED_FORMAT;
192     }
193 }
194 
ReadFrame(Buffer & outBuffer,int32_t timeOutMs)195 Status AACDemuxerPlugin::ReadFrame(Buffer& outBuffer, int32_t timeOutMs)
196 {
197     int status  = -1;
198     std::shared_ptr<Memory> aacFrameData;
199     Status retStatus = GetDataFromSource();
200     if (retStatus != Status::OK) {
201         return retStatus;
202     }
203     status = AudioDemuxerAACProcess(inIoBuffer_, ioDataRemainSize_, &aacDemuxerRst_);
204 
205     if (outBuffer.IsEmpty()) {
206         aacFrameData = outBuffer.AllocMemory(nullptr, aacDemuxerRst_.frameLength);
207     } else {
208         aacFrameData = outBuffer.GetMemory();
209     }
210     switch (status) {
211         case 0:
212             aacFrameData->Write(aacDemuxerRst_.frameBuffer, aacDemuxerRst_.frameLength);
213             if (aacDemuxerRst_.frameBuffer) {
214                 free(aacDemuxerRst_.frameBuffer);
215                 aacDemuxerRst_.frameBuffer = nullptr;
216             }
217             usedDataSize_ = aacDemuxerRst_.usedInputLength;
218             ioDataRemainSize_ -= aacDemuxerRst_.usedInputLength;
219             break;
220         case -1:
221         default:
222             if (aacDemuxerRst_.frameBuffer) {
223                 free(aacDemuxerRst_.frameBuffer);
224                 aacDemuxerRst_.frameBuffer = nullptr;
225             }
226             return Status::ERROR_UNKNOWN;
227     }
228 
229     return Status::OK;
230 }
231 
SeekTo(int32_t trackId,int64_t hstTime,SeekMode mode)232 Status AACDemuxerPlugin::SeekTo(int32_t trackId, int64_t hstTime, SeekMode mode)
233 {
234     return Status::OK;
235 }
236 
Init()237 Status AACDemuxerPlugin::Init()
238 {
239     inIoBuffer_ = static_cast<uint8_t *>(malloc(inIoBufferSize_));
240     if (inIoBuffer_ == nullptr) {
241         MEDIA_LOG_E("inIoBuffer_ malloc failed");
242         return Status::ERROR_NO_MEMORY;
243     }
244     (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
245     return Status::OK;
246 }
Deinit()247 Status AACDemuxerPlugin::Deinit()
248 {
249     if (inIoBuffer_) {
250         free(inIoBuffer_);
251         inIoBuffer_ = nullptr;
252     }
253     return Status::OK;
254 }
255 
Prepare()256 Status AACDemuxerPlugin::Prepare()
257 {
258     return Status::OK;
259 }
260 
Reset()261 Status AACDemuxerPlugin::Reset()
262 {
263     ioContext_.eos = false;
264     ioContext_.dataSource.reset();
265     ioContext_.offset = 0;
266     ioContext_.dataSource.reset();
267     ioDataRemainSize_ = 0;
268     (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
269     return Status::OK;
270 }
271 
Start()272 Status AACDemuxerPlugin::Start()
273 {
274     return Status::OK;
275 }
276 
Stop()277 Status AACDemuxerPlugin::Stop()
278 {
279     return Status::OK;
280 }
281 
GetParameter(Tag tag,ValueType & value)282 Status AACDemuxerPlugin::GetParameter(Tag tag, ValueType &value)
283 {
284     return Status::ERROR_UNIMPLEMENTED;
285 }
286 
SetParameter(Tag tag,const ValueType & value)287 Status AACDemuxerPlugin::SetParameter(Tag tag, const ValueType &value)
288 {
289     return Status::ERROR_UNIMPLEMENTED;
290 }
291 
GetAllocator()292 std::shared_ptr<Allocator> AACDemuxerPlugin::GetAllocator()
293 {
294     return nullptr;
295 }
296 
SetCallback(Callback * cb)297 Status AACDemuxerPlugin::SetCallback(Callback* cb)
298 {
299     return Status::OK;
300 }
301 
GetTrackCount()302 size_t AACDemuxerPlugin::GetTrackCount()
303 {
304     return 0;
305 }
306 
SelectTrack(int32_t trackId)307 Status AACDemuxerPlugin::SelectTrack(int32_t trackId)
308 {
309     return Status::OK;
310 }
311 
UnselectTrack(int32_t trackId)312 Status AACDemuxerPlugin::UnselectTrack(int32_t trackId)
313 {
314     return Status::OK;
315 }
316 
GetSelectedTracks(std::vector<int32_t> & trackIds)317 Status AACDemuxerPlugin::GetSelectedTracks(std::vector<int32_t>& trackIds)
318 {
319     return Status::OK;
320 }
321 
GetFrameLength(const uint8_t * data)322 int AACDemuxerPlugin::GetFrameLength(const uint8_t *data)
323 {
324     return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xE0) >> 5); // 根据协议计算帧长
325 }
326 
AudioDemuxerAACOpen(AudioDemuxerUserArg * userArg)327 int AACDemuxerPlugin::AudioDemuxerAACOpen(AudioDemuxerUserArg *userArg)
328 {
329     return 0;
330 }
331 
AudioDemuxerAACClose()332 int AACDemuxerPlugin::AudioDemuxerAACClose()
333 {
334     return 0;
335 }
336 
AudioDemuxerAACPrepare(const uint8_t * buf,uint32_t len,AACDemuxerRst * rst)337 int AACDemuxerPlugin::AudioDemuxerAACPrepare(const uint8_t *buf, uint32_t len, AACDemuxerRst *rst)
338 {
339     if (IsAACPattern(buf)) {
340         int mpegVersionIndex  = ((buf[1] & 0x0F) >> 3); // 根据协议计算 mpegVersionIndex
341         int mpegVersion = -1;
342         if (mpegVersionIndex == 0) {
343             mpegVersion = 4; // 4
344         } else if (mpegVersionIndex == 1) {
345             mpegVersion = 2; // 2
346         } else {
347             return -1;
348         }
349 
350         int sampleIndex = ((buf[2] & 0x3C) >> 2); // 根据协议计算 sampleIndex
351         int channelCount = ((buf[2] & 0x01) << 2) | ((buf[3] & 0xC0) >> 6); // 根据协议计算 channelCount
352 
353         int sample = samplingRateMap[sampleIndex];
354 
355         rst->frameChannels = channelCount;
356         rst->frameSampleRate = sample;
357         rst->mpegVersion = mpegVersion;
358         MEDIA_LOG_D("channel " PUBLIC_LOG_U8 " sample " PUBLIC_LOG_U32, rst->frameChannels, rst->frameSampleRate);
359         return 0;
360     } else {
361         MEDIA_LOG_D("Err:IsAACPattern");
362         return -1;
363     }
364 }
365 
AudioDemuxerAACProcess(const uint8_t * buffer,uint32_t bufferLen,AACDemuxerRst * rst)366 int AACDemuxerPlugin::AudioDemuxerAACProcess(const uint8_t *buffer, uint32_t bufferLen, AACDemuxerRst *rst)
367 {
368     if (rst == nullptr || buffer == nullptr) {
369         return -1;
370     }
371     rst->frameLength = 0;
372     rst->frameBuffer = nullptr;
373     rst->usedInputLength = 0;
374 
375     do {
376         if (IsAACPattern(buffer) == 0) {
377             MEDIA_LOG_D("Err: IsAACPattern");
378             break;
379         }
380 
381         auto length = static_cast<unsigned int>(GetFrameLength(buffer));
382         if (length + 2 > bufferLen) { // 2
383             rst->usedInputLength = bufferLen;
384             return 0;
385         }
386 
387         if (length == 0) {
388             MEDIA_LOG_D("length = 0 error");
389             return -1;
390         }
391 
392         if (IsAACPattern(buffer + length)) {
393             rst->frameBuffer = static_cast<uint8_t *>(malloc(length));
394             if (rst->frameBuffer) {
395                 FALSE_LOG(memcpy_s(rst->frameBuffer, length, buffer, length) == 0);
396                 rst->frameLength = length;
397                 rst->usedInputLength = length;
398             } else {
399                 MEDIA_LOG_E("malloc error, length " PUBLIC_LOG_U32, length);
400             }
401         } else {
402             MEDIA_LOG_D("can't find next aac, length " PUBLIC_LOG_U32 " is error", length);
403             break;
404         }
405 
406         return 0;
407     } while (0);
408 
409     rst->usedInputLength = 1;
410     return 0;
411 }
412 
AudioDemuxerAACFreeFrame(uint8_t * frame)413 int AACDemuxerPlugin::AudioDemuxerAACFreeFrame(uint8_t *frame)
414 {
415     if (frame) {
416         free(frame);
417     }
418     return 0;
419 }
420 
421 namespace {
IsAACPattern(const uint8_t * data)422     int IsAACPattern(const uint8_t *data)
423     {
424         return data[0] == 0xff && (data[1] & 0xf0) == 0xf0 && (data[1] & 0x06) == 0x00; // 根据协议判断是否为AAC帧
425     }
426 
Sniff(const std::string & name,std::shared_ptr<DataSource> dataSource)427     int Sniff(const std::string& name, std::shared_ptr<DataSource> dataSource)
428     {
429         auto buffer = std::make_shared<Buffer>();
430         auto bufData = buffer->AllocMemory(nullptr, PROBE_READ_LENGTH);
431         auto result = dataSource->ReadAt(0, buffer, static_cast<size_t>(PROBE_READ_LENGTH));
432         if (result != Status::OK) {
433             return 0;
434         }
435         auto inputDataPtr = const_cast<uint8_t *>(bufData->GetReadOnlyData());
436         if (IsAACPattern(inputDataPtr) == 0) {
437             MEDIA_LOG_W("Not AAC format");
438             return 0;
439         }
440         return MAX_RANK;
441     }
442 
RegisterPlugin(const std::shared_ptr<Register> & reg)443     Status RegisterPlugin(const std::shared_ptr<Register>& reg)
444     {
445         MEDIA_LOG_I("RegisterPlugin called.");
446         if (!reg) {
447             MEDIA_LOG_E("RegisterPlugin failed due to nullptr pointer for reg.");
448             return Status::ERROR_INVALID_PARAMETER;
449         }
450 
451         std::string pluginName = "AACDemuxerPlugin";
452         DemuxerPluginDef regInfo;
453         regInfo.name = pluginName;
454         regInfo.description = "adapter for aac demuxer plugin";
455         regInfo.rank = MAX_RANK;
456         regInfo.creator = [](const std::string &name) -> std::shared_ptr<DemuxerPlugin> {
457             return std::make_shared<AACDemuxerPlugin>(name);
458         };
459         regInfo.sniffer = Sniff;
460         auto rtv = reg->AddPlugin(regInfo);
461         if (rtv != Status::OK) {
462             MEDIA_LOG_I("RegisterPlugin AddPlugin failed with return " PUBLIC_LOG_D32, static_cast<int>(rtv));
463         }
464         return Status::OK;
465     }
466 }
467 
__anon4ef59f530402null468 PLUGIN_DEFINITION(AACDemuxer, LicenseType::APACHE_V2, RegisterPlugin, [] {});
469 } // namespace AacDemuxer
470 } // namespace Plugin
471 } // namespace Media
472 } // namespace OHOS