• 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 "core/plugin_manager.h"
25 #include "foundation/log.h"
26 #include "osal/thread/scoped_lock.h"
27 #include "plugin/common/plugin_buffer.h"
28 #include "constants.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     int samplingRateMap[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350};
39     int IsAACPattern(const uint8_t *data);
40     int Sniff(const std::string& name, std::shared_ptr<DataSource> dataSource);
41     Status RegisterPlugin(const std::shared_ptr<Register>& reg);
42     void UpdatePluginDefinition(CodecPluginDef& definition);
43 }
44 
AACDemuxerPlugin(std::string name)45 AACDemuxerPlugin::AACDemuxerPlugin(std::string name)
46     : DemuxerPlugin(std::move(name)),
47       ioContext_(),
48       mediaIOSize_(MEDIA_IO_SIZE),
49       fileSize_(0)
50 {
51     FALSE_LOG(memset_s(&aacDemuxerRst_, sizeof(aacDemuxerRst_), 0x00, sizeof(AACDemuxerRst)) == 0);
52     MEDIA_LOG_I("AACDemuxerPlugin, plugin name: %" PUBLIC_LOG "s", pluginName_.c_str());
53 }
54 
~AACDemuxerPlugin()55 AACDemuxerPlugin::~AACDemuxerPlugin()
56 {
57     MEDIA_LOG_I("~AACDemuxerPlugin");
58 }
59 
SetDataSource(const std::shared_ptr<DataSource> & source)60 Status AACDemuxerPlugin::SetDataSource(const std::shared_ptr<DataSource>& source)
61 {
62     ioContext_.dataSource = source;
63     if (ioContext_.dataSource != nullptr) {
64         ioContext_.dataSource->GetSize(fileSize_);
65     }
66     MEDIA_LOG_I("fileSize_ %" PUBLIC_LOG "d", fileSize_);
67     return Status::OK;
68 }
69 
GetMediaInfo(MediaInfo & mediaInfo)70 Status AACDemuxerPlugin::GetMediaInfo(MediaInfo& mediaInfo)
71 {
72     Status status = Status::ERROR_UNKNOWN;
73     auto buffer = std::make_shared<Buffer>();
74     auto bufData = buffer->AllocMemory(nullptr, GET_INFO_READ_LEN);
75     uint8_t *inputDataPtr = nullptr;
76     auto result = ioContext_.dataSource->ReadAt(ioContext_.offset, buffer, static_cast<size_t>(GET_INFO_READ_LEN));
77     inputDataPtr = (uint8_t *)bufData->GetReadOnlyData();
78     int ret = AudioDemuxerAACPrepare(inputDataPtr, bufData->GetSize(), &aacDemuxerRst_);
79     if (ret == 0) {
80         mediaInfo.tracks.resize(1);
81         if (aacDemuxerRst_.frameChannels == 1) {
82             mediaInfo.tracks[0].insert({Tag::AUDIO_CHANNEL_LAYOUT, AudioChannelLayout::MONO});
83         } else {
84             mediaInfo.tracks[0].insert({Tag::AUDIO_CHANNEL_LAYOUT, AudioChannelLayout::STEREO});
85         }
86         mediaInfo.tracks[0].insert({Tag::AUDIO_SAMPLE_RATE, (uint32_t)aacDemuxerRst_.frameSampleRate});
87         mediaInfo.tracks[0].insert({Tag::MEDIA_BITRATE, (uint32_t)aacDemuxerRst_.frameBitrateKbps});
88         mediaInfo.tracks[0].insert({Tag::AUDIO_CHANNELS, (uint32_t)aacDemuxerRst_.frameChannels});
89         mediaInfo.tracks[0].insert({Tag::TRACK_ID, (uint32_t)0});
90         mediaInfo.tracks[0].insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_AAC)});
91         mediaInfo.tracks[0].insert({Tag::AUDIO_MPEG_VERSION, (uint32_t)aacDemuxerRst_.mpegVersion});
92         mediaInfo.tracks[0].insert({Tag::AUDIO_SAMPLE_FORMAT, AudioSampleFormat::S16P});
93         mediaInfo.tracks[0].insert({Tag::AUDIO_SAMPLE_PER_FRAME, (uint32_t)(1024)});
94         mediaInfo.tracks[0].insert({Tag::AUDIO_AAC_PROFILE, AudioAacProfile::LC});
95         mediaInfo.tracks[0].insert({Tag::AUDIO_AAC_STREAM_FORMAT, AudioAacStreamFormat::MP4ADTS});
96         return Status::OK;
97     } else {
98         return Status::ERROR_UNSUPPORTED_FORMAT;
99     }
100 }
101 
ReadFrame(Buffer & outBuffer,int32_t timeOutMs)102 Status AACDemuxerPlugin::ReadFrame(Buffer& outBuffer, int32_t timeOutMs)
103 {
104     int  status  = -1;
105     std::shared_ptr<Memory> aacFrameData;
106     auto buffer  = std::make_shared<Buffer>();
107     auto bufData = buffer->AllocMemory(nullptr, mediaIOSize_);
108     auto result  = ioContext_.dataSource->ReadAt(ioContext_.offset, buffer, static_cast<size_t>(mediaIOSize_));
109     if (result != Status::OK) {
110         ioContext_.eos = true;
111         ioContext_.offset = 0;
112         MEDIA_LOG_I("result is %" PUBLIC_LOG "d", result);
113         return result;
114     }
115 
116     uint8_t *inputPtr = (uint8_t *)bufData->GetReadOnlyData();
117     status = AudioDemuxerAACProcess(inputPtr, bufData->GetSize(), &aacDemuxerRst_);
118 
119     if (outBuffer.IsEmpty()) {
120         aacFrameData = outBuffer.AllocMemory(nullptr, aacDemuxerRst_.frameLength);
121     } else {
122         aacFrameData = outBuffer.GetMemory();
123     }
124     switch (status) {
125         case 0:
126             ioContext_.offset += aacDemuxerRst_.usedInputLength;
127             aacFrameData->Write(aacDemuxerRst_.frameBuffer, aacDemuxerRst_.frameLength);
128             if (aacDemuxerRst_.frameBuffer) {
129                 free(aacDemuxerRst_.frameBuffer);
130                 aacDemuxerRst_.frameBuffer = nullptr;
131             }
132             break;
133         case -1:
134         default:
135             if (aacDemuxerRst_.frameBuffer) {
136                 free(aacDemuxerRst_.frameBuffer);
137                 aacDemuxerRst_.frameBuffer = nullptr;
138             }
139             return Status::ERROR_UNKNOWN;
140     }
141 
142     return Status::OK;
143 }
144 
SeekTo(int32_t trackId,int64_t hstTime,SeekMode mode)145 Status AACDemuxerPlugin::SeekTo(int32_t trackId, int64_t hstTime, SeekMode mode)
146 {
147     return Status::OK;
148 }
149 
Init()150 Status AACDemuxerPlugin::Init()
151 {
152     return Status::OK;
153 }
Deinit()154 Status AACDemuxerPlugin::Deinit()
155 {
156     return Status::OK;
157 }
158 
Prepare()159 Status AACDemuxerPlugin::Prepare()
160 {
161     return Status::OK;
162 }
163 
Reset()164 Status AACDemuxerPlugin::Reset()
165 {
166     ioContext_.eos = false;
167     ioContext_.dataSource.reset();
168     ioContext_.offset = 0;
169     return Status::OK;
170 }
171 
Start()172 Status AACDemuxerPlugin::Start()
173 {
174     return Status::OK;
175 }
176 
Stop()177 Status AACDemuxerPlugin::Stop()
178 {
179     return Status::OK;
180 }
181 
IsParameterSupported(Tag tag)182 bool AACDemuxerPlugin::IsParameterSupported(Tag tag)
183 {
184     return false;
185 }
186 
GetParameter(Tag tag,ValueType & value)187 Status AACDemuxerPlugin::GetParameter(Tag tag, ValueType &value)
188 {
189     return Status::ERROR_UNIMPLEMENTED;
190 }
191 
SetParameter(Tag tag,const ValueType & value)192 Status AACDemuxerPlugin::SetParameter(Tag tag, const ValueType &value)
193 {
194     return Status::ERROR_UNIMPLEMENTED;
195 }
196 
GetAllocator()197 std::shared_ptr<Allocator> AACDemuxerPlugin::GetAllocator()
198 {
199     return nullptr;
200 }
201 
SetCallback(const std::shared_ptr<Callback> & cb)202 Status AACDemuxerPlugin::SetCallback(const std::shared_ptr<Callback>& cb)
203 {
204     return Status::OK;
205 }
206 
GetTrackCount()207 size_t AACDemuxerPlugin::GetTrackCount()
208 {
209     return 0;
210 }
211 
SelectTrack(int32_t trackId)212 Status AACDemuxerPlugin::SelectTrack(int32_t trackId)
213 {
214     return Status::OK;
215 }
216 
UnselectTrack(int32_t trackId)217 Status AACDemuxerPlugin::UnselectTrack(int32_t trackId)
218 {
219     return Status::OK;
220 }
221 
GetSelectedTracks(std::vector<int32_t> & trackIds)222 Status AACDemuxerPlugin::GetSelectedTracks(std::vector<int32_t>& trackIds)
223 {
224     return Status::OK;
225 }
226 
getFrameLength(const uint8_t * data)227 int AACDemuxerPlugin::getFrameLength(const uint8_t *data)
228 {
229     return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xE0) >> 5);
230 }
231 
AudioDemuxerAACOpen(AudioDemuxerUserArg * userArg)232 int AACDemuxerPlugin::AudioDemuxerAACOpen(AudioDemuxerUserArg *userArg)
233 {
234     return 0;
235 }
236 
AudioDemuxerAACClose()237 int AACDemuxerPlugin::AudioDemuxerAACClose()
238 {
239     return 0;
240 }
241 
AudioDemuxerAACPrepare(const uint8_t * buf,uint32_t len,AACDemuxerRst * rst)242 int AACDemuxerPlugin::AudioDemuxerAACPrepare(const uint8_t *buf, uint32_t len, AACDemuxerRst *rst)
243 {
244     if (IsAACPattern(buf)) {
245         int mpegVersionIndex  = ((buf[1] & 0x0F) >> 3);
246         int mpegVersion = -1;
247         if (mpegVersionIndex == 0) {
248             mpegVersion = 4; // 4
249         } else if (mpegVersionIndex == 1) {
250             mpegVersion = 2; // 2
251         } else {
252             return -1;
253         }
254 
255         int sampleIndex = ((buf[2] & 0x3C) >> 2);
256         int channelCount = ((buf[2] & 0x01) << 2) | ((buf[3] & 0xC0) >> 6);
257 
258         int sample = samplingRateMap[sampleIndex];
259 
260         rst->frameChannels = channelCount;
261         rst->frameSampleRate = sample;
262         rst->mpegVersion = mpegVersion;
263         MEDIA_LOG_D("channel %" PUBLIC_LOG "d sample %" PUBLIC_LOG "d", rst->frameChannels, rst->frameSampleRate);
264         return 0;
265     } else {
266         MEDIA_LOG_D("Err:IsAACPattern");
267         return -1;
268     }
269 }
270 
AudioDemuxerAACProcess(const uint8_t * buffer,uint32_t bufferLen,AACDemuxerRst * rst)271 int AACDemuxerPlugin::AudioDemuxerAACProcess(const uint8_t *buffer, uint32_t bufferLen, AACDemuxerRst *rst)
272 {
273     if (rst == nullptr || buffer == nullptr) {
274         return -1;
275     }
276     rst->frameLength = 0;
277     rst->frameBuffer = nullptr;
278     rst->usedInputLength = 0;
279 
280     unsigned int length = 0;
281     do {
282         if (IsAACPattern(buffer) == 0) {
283             MEDIA_LOG_D("Err: IsAACPattern");
284             break;
285         }
286 
287         length = static_cast<unsigned int>(getFrameLength(buffer));
288         if (length + 2 > bufferLen) { // 2
289             rst->usedInputLength = bufferLen;
290             return 0;
291         }
292 
293         if (length == 0) {
294             MEDIA_LOG_D("length = 0 error");
295             return -1;
296         }
297 
298         if (IsAACPattern(buffer + length)) {
299             rst->frameBuffer = (uint8_t *)malloc(length);
300             if (rst->frameBuffer) {
301                 FALSE_LOG(memcpy_s(rst->frameBuffer, length, buffer, length) == 0);
302                 rst->frameLength = length;
303                 rst->usedInputLength = length;
304             } else {
305                 MEDIA_LOG_E("malloc error, length %" PUBLIC_LOG "d\n", length);
306             }
307         } else {
308             MEDIA_LOG_D("can't find next aac, length %" PUBLIC_LOG "d is error\n", length);
309             break;
310         }
311 
312         return 0;
313     } while (0);
314 
315     rst->usedInputLength = 1;
316     return 0;
317 }
318 
AudioDemuxerAACFreeFrame(uint8_t * frame)319 int AACDemuxerPlugin::AudioDemuxerAACFreeFrame(uint8_t *frame)
320 {
321     if (frame) {
322         free(frame);
323     }
324     return 0;
325 }
326 
327 namespace {
IsAACPattern(const uint8_t * data)328     int IsAACPattern(const uint8_t *data)
329     {
330         return data[0] == 0xff && (data[1] & 0xf0) == 0xf0 && (data[1] & 0x06) == 0x00;
331     }
332 
Sniff(const std::string & name,std::shared_ptr<DataSource> dataSource)333     int Sniff(const std::string& name, std::shared_ptr<DataSource> dataSource)
334     {
335         Status status = Status::ERROR_UNKNOWN;
336         auto buffer = std::make_shared<Buffer>();
337         auto bufData = buffer->AllocMemory(nullptr, PROBE_READ_LENGTH);
338         int processLoop = 1;
339         uint8_t *inputDataPtr = nullptr;
340         auto result = dataSource->ReadAt(0, buffer, static_cast<size_t>(PROBE_READ_LENGTH));
341         if (result != Status::OK) {
342             return 0;
343         }
344 
345         inputDataPtr = (uint8_t *)bufData->GetReadOnlyData();
346         if (IsAACPattern(inputDataPtr) == 0) {
347             return 0;
348         }
349 
350         return 100; // 100
351     }
352 
RegisterPlugin(const std::shared_ptr<Register> & reg)353     Status RegisterPlugin(const std::shared_ptr<Register>& reg)
354     {
355         MEDIA_LOG_I("RegisterPlugin called.");
356         if (!reg) {
357             MEDIA_LOG_I("RegisterPlugin failed due to nullptr pointer for reg.");
358             return Status::ERROR_INVALID_PARAMETER;
359         }
360 
361         std::string pluginName = "AACDemuxerPlugin";
362         DemuxerPluginDef regInfo;
363         regInfo.name = pluginName;
364         regInfo.description = "adapter for aac demuxer plugin";
365         regInfo.rank = 100; // 100
366         regInfo.creator = [](const std::string &name) -> std::shared_ptr<DemuxerPlugin> {
367             return std::make_shared<AACDemuxerPlugin>(name);
368         };
369         regInfo.sniffer = Sniff;
370         auto rtv = reg->AddPlugin(regInfo);
371         if (rtv != Status::OK) {
372             MEDIA_LOG_I("RegisterPlugin AddPlugin failed with return %" PUBLIC_LOG "d", static_cast<int>(rtv));
373         }
374         return Status::OK;
375     }
376 }
377 
__anonbaff51580402null378 PLUGIN_DEFINITION(AACDemuxer, LicenseType::APACHE_V2, RegisterPlugin, [] {});
379 } // namespace AacDemuxer
380 } // namespace Plugin
381 } // namespace Media
382 } // namespace OHOS