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