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 "Minimp3DemuxerPlugin"
17
18 #include "minimp3_demuxer_plugin.h"
19 #include <algorithm>
20 #include <cstdio>
21 #include <cstring>
22 #include <new>
23 #include "foundation/log.h"
24 #include "osal/thread/scoped_lock.h"
25 #include "plugin/common/plugin_buffer.h"
26 #include "plugin/common/plugin_time.h"
27 #include "osal/utils/util.h"
28 #include "utils/constants.h"
29
30 namespace OHOS {
31 namespace Media {
32 namespace Plugin {
33 namespace Minimp3 {
34 namespace {
35 constexpr uint32_t MAX_SAMPLES_PERFRAME = 1152 * 2;
36 constexpr uint32_t MP3_SEEK_DISCARD_ITEMS = 2;
37 constexpr uint32_t ID3_DETECT_SIZE = 10;
38 constexpr uint32_t PROBE_READ_LENGTH = 16 * 1024;
39 constexpr uint32_t MAX_RANK = 100;
40 constexpr uint32_t MEDIA_IO_SIZE = 4 * 1024;
41 constexpr uint32_t MAX_FRAME_SIZE = MEDIA_IO_SIZE;
42 constexpr uint32_t AUDIO_DEMUXER_SOURCE_ONCE_LENGTH_MAX = 1024;
43 uint32_t durationMs = 0;
44 uint32_t fileSize = 0;
45 AudioDemuxerMp3Attr mp3ProbeAttr;
46 AudioDemuxerRst mp3ProbeRst;
47 std::vector<uint32_t> infoLayer = {1, 2, 3};
48 std::vector<uint32_t> infoSampleRate = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
49 std::vector<uint32_t> infoBitrateKbps = {8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176,
50 192, 224, 256, 288, 320, 352, 384, 416, 448};
51 size_t AudioDecmuxerMp3Id3v2SizeCalculate(const uint8_t *buf);
52 bool AudioDemuxerMp3HasId3v2(const uint8_t *buf);
53 size_t AudioDemuxerMp3GetId3v2Size(const uint8_t *buf, size_t bufSize);
54 int AudioDemuxerMp3ProbeDecodeCheck(Mp3DemuxerFrameInfo *info);
55 int AudioDemuxerMp3IterateCallbackForProbe(void *userData, const uint8_t *frame, int frameSize, int freeFormatBytes,
56 size_t bufSize, uint64_t offset, Mp3DemuxerFrameInfo *info);
57 Status AudioDemuxerMp3Probe(AudioDemuxerMp3Attr *mp3DemuxerAttr, uint8_t *inputBuffer, uint32_t inputLength,
58 AudioDemuxerRst *mp3DemuxerRst);
59 int Sniff(const std::string& pluginName, std::shared_ptr<DataSource> dataSource);
60 Status RegisterPlugin(const std::shared_ptr<Register>& reg);
61 }
62
Minimp3DemuxerPlugin(std::string name)63 Minimp3DemuxerPlugin::Minimp3DemuxerPlugin(std::string name)
64 : DemuxerPlugin(std::move(name)),
65 inIoBufferSize_(MEDIA_IO_SIZE),
66 fileSize_(0),
67 inIoBuffer_(nullptr),
68 ioDataRemainSize_(0),
69 currentDemuxerPos_(0),
70 durationMs_(0),
71 ioContext_()
72 {
73 FALSE_LOG(memset_s(&mp3DemuxerAttr_, sizeof(mp3DemuxerAttr_), 0x00, sizeof(AudioDemuxerMp3Attr)) == 0);
74 FALSE_LOG(memset_s(&mp3DemuxerRst_, sizeof(mp3DemuxerRst_), 0x00, sizeof(AudioDemuxerRst)) == 0);
75 FALSE_LOG(memset_s(&mp3ProbeAttr, sizeof(mp3ProbeAttr), 0x00, sizeof(AudioDemuxerMp3Attr)) == 0);
76 FALSE_LOG(memset_s(&mp3ProbeRst, sizeof(mp3ProbeRst), 0x00, sizeof(AudioDemuxerRst)) == 0);
77 FALSE_LOG(memset_s(&minimp3DemuxerImpl_, sizeof(minimp3DemuxerImpl_), 0x00, sizeof(Minimp3DemuxerOp)) == 0);
78 MEDIA_LOG_I("Minimp3DemuxerPlugin, plugin name: " PUBLIC_LOG_S, pluginName_.c_str());
79 }
80
~Minimp3DemuxerPlugin()81 Minimp3DemuxerPlugin::~Minimp3DemuxerPlugin()
82 {
83 MEDIA_LOG_I("~Minimp3DemuxerPlugin");
84 }
85
SetDataSource(const std::shared_ptr<DataSource> & source)86 Status Minimp3DemuxerPlugin::SetDataSource(const std::shared_ptr<DataSource>& source)
87 {
88 ioContext_.dataSource = source;
89 if (ioContext_.dataSource != nullptr) {
90 ioContext_.dataSource->GetSize(fileSize_);
91 }
92 mp3DemuxerAttr_.fileSize = fileSize_;
93 fileSize = fileSize_;
94 seekable_ = source->GetSeekable();
95 MEDIA_LOG_I("fileSize_ " PUBLIC_LOG_ZU, fileSize_);
96 return Status::OK;
97 }
98
DoReadFromSource(uint32_t readSize)99 Status Minimp3DemuxerPlugin::DoReadFromSource(uint32_t readSize)
100 {
101 auto buffer = std::make_shared<Buffer>();
102 auto bufData = buffer->AllocMemory(nullptr, readSize);
103 int retryTimes = 0;
104 MEDIA_LOG_DD("ioNeedReadSize " PUBLIC_LOG_U32 " inIoBufferSize_ " PUBLIC_LOG_D32 " ioDataRemainSize_ "
105 PUBLIC_LOG_U32, readSize, inIoBufferSize_, ioDataRemainSize_);
106 do {
107 auto res = ioContext_.dataSource->ReadAt(ioContext_.offset, buffer, static_cast<size_t>(readSize));
108 FALSE_RETURN_V_MSG_W(res == Status::OK, res, "read data from source error " PUBLIC_LOG_D32, (int)res);
109 if (bufData->GetSize() == 0 && retryTimes < 200 && ioDataRemainSize_ == 0) { // 200
110 MEDIA_LOG_DD("bufData->GetSize() == 0 retryTimes = " PUBLIC_LOG_D32, retryTimes);
111 OSAL::SleepFor(30); // 30
112 retryTimes++;
113 continue;
114 }
115 FALSE_RETURN_V_MSG_E(retryTimes < 200, Status::ERROR_NOT_ENOUGH_DATA, // 200 times
116 "not eof, but doesn't have enough data");
117 MEDIA_LOG_DD("bufData->GetSize() " PUBLIC_LOG "d", bufData->GetSize());
118 if (bufData->GetSize() > 0) {
119 if (readSize < bufData->GetSize()) {
120 MEDIA_LOG_E("Error: ioNeedReadSize < bufData->GetSize()");
121 return Status::ERROR_UNKNOWN;
122 }
123 auto ret = memcpy_s(inIoBuffer_ + ioDataRemainSize_, readSize,
124 const_cast<uint8_t *>(bufData->GetReadOnlyData()), bufData->GetSize());
125 if (ret != EOK) {
126 MEDIA_LOG_W("memcpy into buffer failed with code " PUBLIC_LOG_D32, ret);
127 return Status::ERROR_UNKNOWN;
128 }
129 ioContext_.offset += bufData->GetSize();
130 ioDataRemainSize_ += bufData->GetSize();
131 }
132 break;
133 } while (true);
134 return Status::OK;
135 }
136
GetDataFromSource()137 Status Minimp3DemuxerPlugin::GetDataFromSource()
138 {
139 uint32_t ioNeedReadSize = inIoBufferSize_ - ioDataRemainSize_;
140 MEDIA_LOG_DD("remain size_ " PUBLIC_LOG_D32 " need read size " PUBLIC_LOG_D32, ioDataRemainSize_, ioNeedReadSize);
141 if (ioDataRemainSize_) {
142 // 将剩余数据移动到buffer的起始位置
143 auto ret = memmove_s(inIoBuffer_, ioDataRemainSize_, inIoBuffer_ + mp3DemuxerRst_.usedInputLength,
144 ioDataRemainSize_);
145 FALSE_RETURN_V_MSG_W(ret == 0, Status::ERROR_UNKNOWN, "copy buffer error " PUBLIC_LOG_D32, ret);
146 ret = memset_s(inIoBuffer_ + ioDataRemainSize_, ioNeedReadSize, 0x00, ioNeedReadSize);
147 FALSE_RETURN_V_MSG_W(ret == 0, Status::ERROR_UNKNOWN, "memset_s buffer error " PUBLIC_LOG_D32, ret);
148 }
149 if (ioContext_.offset >= fileSize_ && ioDataRemainSize_ == 0) {
150 ioContext_.eos = true;
151 return Status::END_OF_STREAM;
152 }
153 if (ioContext_.offset + ioNeedReadSize > fileSize_) {
154 ioNeedReadSize = fileSize_ - ioContext_.offset; // 在读取文件即将结束时,剩余数据不足,更新读取长度
155 }
156 if (ioNeedReadSize == 0) {
157 return Status::OK;
158 }
159 return DoReadFromSource(ioNeedReadSize);
160 }
161
FillInMediaInfo(MediaInfo & mediaInfo) const162 void Minimp3DemuxerPlugin::FillInMediaInfo(MediaInfo& mediaInfo) const
163 {
164 mediaInfo.tracks.resize(1);
165 if (mp3DemuxerRst_.frameChannels == 1) {
166 mediaInfo.tracks[0].Insert<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::MONO);
167 } else {
168 mediaInfo.tracks[0].Insert<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::STEREO);
169 }
170 int64_t durationHst;
171 Ms2HstTime(durationMs, durationHst);
172 mediaInfo.tracks[0].Insert<Tag::MEDIA_TYPE>(MediaType::AUDIO);
173 mediaInfo.tracks[0].Insert<Tag::AUDIO_SAMPLE_RATE>(mp3DemuxerRst_.frameSampleRate);
174 mediaInfo.tracks[0].Insert<Tag::MEDIA_BITRATE>(mp3DemuxerRst_.frameBitrateKbps);
175 mediaInfo.tracks[0].Insert<Tag::AUDIO_CHANNELS>(mp3DemuxerRst_.frameChannels);
176 mediaInfo.tracks[0].Insert<Tag::TRACK_ID>(0);
177 mediaInfo.tracks[0].Insert<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
178 mediaInfo.tracks[0].Insert<Tag::AUDIO_MPEG_VERSION>(1);
179 mediaInfo.tracks[0].Insert<Tag::AUDIO_MPEG_LAYER>(mp3DemuxerRst_.audioLayer);
180 mediaInfo.tracks[0].Insert<Tag::AUDIO_SAMPLE_PER_FRAME>(mp3DemuxerRst_.samplesPerFrame);
181 mediaInfo.tracks[0].Insert<Tag::MEDIA_DURATION>(durationHst);
182 }
183
GetMediaInfo(MediaInfo & mediaInfo)184 Status Minimp3DemuxerPlugin::GetMediaInfo(MediaInfo& mediaInfo)
185 {
186 int processLoop = 1;
187 Status status;
188 while (processLoop) {
189 status = GetDataFromSource();
190 if (status != Status::OK) {
191 return status;
192 }
193 status = AudioDemuxerMp3Prepare(&mp3DemuxerAttr_, inIoBuffer_, ioDataRemainSize_, &mp3DemuxerRst_);
194 switch (status) {
195 case Status::ERROR_NOT_ENOUGH_DATA:
196 MEDIA_LOG_D("GetMediaInfo: need more data usedInputLength " PUBLIC_LOG_U64,
197 mp3DemuxerRst_.usedInputLength);
198 ioDataRemainSize_ -= mp3DemuxerRst_.usedInputLength;
199 currentDemuxerPos_ += mp3DemuxerRst_.usedInputLength;
200 processLoop = 1;
201 break;
202 case Status::OK:
203 MEDIA_LOG_D("GetMediaInfo: OK usedInputLength " PUBLIC_LOG_U64, mp3DemuxerRst_.usedInputLength);
204 ioDataRemainSize_ -= mp3DemuxerRst_.usedInputLength;
205 currentDemuxerPos_ += mp3DemuxerRst_.usedInputLength;
206 FillInMediaInfo(mediaInfo);
207 processLoop = 0;
208 break;
209 case Status::ERROR_UNSUPPORTED_FORMAT:
210 return Status::ERROR_UNSUPPORTED_FORMAT;
211 case Status::ERROR_UNKNOWN:
212 default:
213 MEDIA_LOG_I("AUDIO_DEMUXER_PREPARE_UNMATCHED_FORMAT " PUBLIC_LOG_D32, status);
214 return Status::ERROR_UNKNOWN;
215 }
216 }
217
218 mp3DemuxerAttr_.bitRate = mp3DemuxerRst_.frameBitrateKbps;
219 MEDIA_LOG_D("mp3DemuxerAttr_.bitRate " PUBLIC_LOG_U32 "kbps durationMs " PUBLIC_LOG_U32 " ms",
220 mp3DemuxerRst_.frameBitrateKbps, durationMs);
221 return Status::OK;
222 }
223
GetCurrentPositionTimeS(void)224 uint64_t Minimp3DemuxerPlugin::GetCurrentPositionTimeS(void)
225 {
226 uint64_t currentTime = (static_cast<uint64_t>(currentDemuxerPos_ - mp3DemuxerAttr_.id3v2Size) * 8 * HST_MSECOND) /
227 mp3DemuxerAttr_.bitRate;
228 return currentTime;
229 }
230
ReadFrame(Buffer & outBuffer,int32_t timeOutMs)231 Status Minimp3DemuxerPlugin::ReadFrame(Buffer& outBuffer, int32_t timeOutMs)
232 {
233 int status = -1;
234 Status retResult = Status::OK;
235 std::shared_ptr<Memory> mp3FrameData;
236 retResult = GetDataFromSource();
237 if (retResult != Status::OK) {
238 return retResult;
239 }
240 MEDIA_LOG_DD("ioDataRemainSize_ = " PUBLIC_LOG_D32, ioDataRemainSize_);
241 status = AudioDemuxerMp3Process(inIoBuffer_, ioDataRemainSize_);
242 if (outBuffer.IsEmpty()) {
243 mp3FrameData = outBuffer.AllocMemory(nullptr, mp3DemuxerRst_.frameLength);
244 } else {
245 mp3FrameData = outBuffer.GetMemory();
246 }
247 MEDIA_LOG_DD("status = " PUBLIC_LOG_D32, status);
248 switch (status) {
249 case AUDIO_DEMUXER_SUCCESS:
250 MEDIA_LOG_DD("ReadFrame: success usedInputLength " PUBLIC_LOG_D32 " ioDataRemainSize_ " PUBLIC_LOG_D32,
251 (uint32_t)mp3DemuxerRst_.usedInputLength, ioDataRemainSize_);
252 if (mp3DemuxerRst_.frameLength) {
253 mp3FrameData->Write(mp3DemuxerRst_.frameBuffer, mp3DemuxerRst_.frameLength);
254 ioDataRemainSize_ -= mp3DemuxerRst_.usedInputLength;
255 currentDemuxerPos_ += mp3DemuxerRst_.usedInputLength;
256 } else if (mp3DemuxerRst_.usedInputLength == 0) {
257 if (ioDataRemainSize_ > AUDIO_DEMUXER_SOURCE_ONCE_LENGTH_MAX) {
258 ioDataRemainSize_ = ioDataRemainSize_ - AUDIO_DEMUXER_SOURCE_ONCE_LENGTH_MAX;
259 currentDemuxerPos_ += AUDIO_DEMUXER_SOURCE_ONCE_LENGTH_MAX;
260 } else {
261 currentDemuxerPos_ += ioDataRemainSize_;
262 ioDataRemainSize_ = 0;
263 }
264 } else {
265 ioDataRemainSize_ -= mp3DemuxerRst_.usedInputLength;
266 currentDemuxerPos_ += mp3DemuxerRst_.usedInputLength;
267 }
268 outBuffer.pts = GetCurrentPositionTimeS();
269 MEDIA_LOG_DD("ReadFrame: mp3DemuxerRst_.frameLength " PUBLIC_LOG_U32 ", pts " PUBLIC_LOG_U64,
270 mp3DemuxerRst_.frameLength, outBuffer.pts);
271 if (mp3DemuxerRst_.frameBuffer) {
272 free(mp3DemuxerRst_.frameBuffer);
273 mp3DemuxerRst_.frameBuffer = nullptr;
274 }
275 break;
276 case AUDIO_DEMUXER_PROCESS_NEED_MORE_DATA:
277 ioDataRemainSize_ -= mp3DemuxerRst_.usedInputLength;
278 currentDemuxerPos_ += mp3DemuxerRst_.usedInputLength;
279 MEDIA_LOG_D("ReadFrame: need more data usedInputLength " PUBLIC_LOG_U64 " ioDataRemainSize_ "
280 PUBLIC_LOG_U32, mp3DemuxerRst_.usedInputLength, ioDataRemainSize_);
281 break;
282 case AUDIO_DEMUXER_ERROR:
283 default:
284 MEDIA_LOG_E("ReadFrame error");
285 if (mp3DemuxerRst_.frameBuffer) {
286 free(mp3DemuxerRst_.frameBuffer);
287 mp3DemuxerRst_.frameBuffer = nullptr;
288 }
289 retResult = Status::ERROR_UNKNOWN;
290 break;
291 }
292 return retResult;
293 }
294
SeekTo(int32_t trackId,int64_t hstTime,SeekMode mode)295 Status Minimp3DemuxerPlugin::SeekTo(int32_t trackId, int64_t hstTime, SeekMode mode)
296 {
297 uint64_t pos = 0;
298 uint32_t targetTimeMs = static_cast<uint32_t>(HstTime2Ms(hstTime));
299 if (AudioDemuxerMp3GetSeekPosition(targetTimeMs, &pos) == 0) {
300 ioContext_.offset = pos;
301 ioDataRemainSize_ = 0;
302 currentDemuxerPos_ = pos;
303 MEDIA_LOG_D("ioContext_.offset " PUBLIC_LOG_D32, static_cast<uint32_t>(ioContext_.offset));
304 (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
305 } else {
306 return Status::ERROR_INVALID_PARAMETER;
307 }
308 return Status::OK;
309 }
310
Init()311 Status Minimp3DemuxerPlugin::Init()
312 {
313 minimp3DemuxerImpl_ = MiniMp3GetOpt();
314 AudioDemuxerMp3Open();
315 inIoBuffer_ = (uint8_t *)(malloc(inIoBufferSize_));
316 if (inIoBuffer_ == nullptr) {
317 MEDIA_LOG_E("inIoBuffer_ malloc failed");
318 return Status::ERROR_NO_MEMORY;
319 }
320 (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
321 return Status::OK;
322 }
323
Deinit()324 Status Minimp3DemuxerPlugin::Deinit()
325 {
326 if (inIoBuffer_) {
327 free(inIoBuffer_);
328 inIoBuffer_ = nullptr;
329 }
330 return Status::OK;
331 }
332
Prepare()333 Status Minimp3DemuxerPlugin::Prepare()
334 {
335 return Status::OK;
336 }
337
Reset()338 Status Minimp3DemuxerPlugin::Reset()
339 {
340 ioContext_.eos = false;
341 ioContext_.dataSource.reset();
342 ioContext_.offset = 0;
343 ioDataRemainSize_ = 0;
344 currentDemuxerPos_ = 0;
345 (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
346 return Status::OK;
347 }
348
Start()349 Status Minimp3DemuxerPlugin::Start()
350 {
351 return Status::OK;
352 }
353
Stop()354 Status Minimp3DemuxerPlugin::Stop()
355 {
356 return Status::OK;
357 }
358
GetParameter(Tag tag,ValueType & value)359 Status Minimp3DemuxerPlugin::GetParameter(Tag tag, ValueType &value)
360 {
361 return Status::ERROR_UNIMPLEMENTED;
362 }
363
SetParameter(Tag tag,const ValueType & value)364 Status Minimp3DemuxerPlugin::SetParameter(Tag tag, const ValueType &value)
365 {
366 return Status::ERROR_UNIMPLEMENTED;
367 }
368
GetAllocator()369 std::shared_ptr<Allocator> Minimp3DemuxerPlugin::GetAllocator()
370 {
371 return nullptr;
372 }
373
SetCallback(Callback * cb)374 Status Minimp3DemuxerPlugin::SetCallback(Callback* cb)
375 {
376 return Status::OK;
377 }
378
GetTrackCount()379 size_t Minimp3DemuxerPlugin::GetTrackCount()
380 {
381 return 0;
382 }
SelectTrack(int32_t trackId)383 Status Minimp3DemuxerPlugin::SelectTrack(int32_t trackId)
384 {
385 return Status::OK;
386 }
UnselectTrack(int32_t trackId)387 Status Minimp3DemuxerPlugin::UnselectTrack(int32_t trackId)
388 {
389 return Status::OK;
390 }
GetSelectedTracks(std::vector<int32_t> & trackIds)391 Status Minimp3DemuxerPlugin::GetSelectedTracks(std::vector<int32_t>& trackIds)
392 {
393 return Status::OK;
394 }
395
AudioDemuxerMp3IgnoreTailZero(uint8_t * data,uint32_t * dataLen)396 void Minimp3DemuxerPlugin::AudioDemuxerMp3IgnoreTailZero(uint8_t *data, uint32_t *dataLen)
397 {
398 if ((data == nullptr) || (dataLen == nullptr) || (*dataLen == 0)) {
399 return;
400 }
401
402 uint32_t len = *dataLen;
403 uint8_t *ptr = data + len - 1;
404
405 do {
406 if (*ptr == 0) {
407 ptr--;
408 len--;
409 } else {
410 break;
411 }
412 } while (len);
413
414 *dataLen = len;
415 }
416
AudioDemuxerMp3IterateCallback(void * userData,const uint8_t * frame,int frameSize,int freeFormatBytes,size_t bufSize,uint64_t offset,Mp3DemuxerFrameInfo * info)417 int Minimp3DemuxerPlugin::AudioDemuxerMp3IterateCallback(void *userData, const uint8_t *frame, int frameSize,
418 int freeFormatBytes, size_t bufSize, uint64_t offset,
419 Mp3DemuxerFrameInfo *info)
420 {
421 AudioDemuxerMp3Attr *mp3Demuxer = static_cast<AudioDemuxerMp3Attr *>(userData);
422 AudioDemuxerRst *rst = mp3Demuxer->rst;
423 uint64_t usedInputLength = 0;
424
425 if (mp3Demuxer->internalRemainLen >= offset + frameSize) {
426 usedInputLength = offset + frameSize;
427 } else if (mp3Demuxer->internalRemainLen >= offset) {
428 usedInputLength = offset;
429 } else {
430 usedInputLength = 0;
431 }
432 MEDIA_LOG_DD("offset = " PUBLIC_LOG_U64 " internalRemainLen " PUBLIC_LOG_U32 " frameSize "
433 PUBLIC_LOG_D32, offset, mp3Demuxer->internalRemainLen, frameSize);
434
435 if (frameSize == 0) {
436 rst->usedInputLength = 0;
437 rst->frameBuffer = nullptr;
438 rst->frameLength = 0;
439 return 0;
440 }
441
442 if (frameSize >= MAX_FRAME_SIZE) {
443 return AUDIO_DEMUXER_ERROR;
444 }
445
446 uint8_t *rstFrame = static_cast<uint8_t *>(calloc(frameSize, sizeof(uint8_t)));
447 if (!rstFrame) {
448 MEDIA_LOG_E("rstFrame null error");
449 return AUDIO_DEMUXER_ERROR;
450 }
451
452 (void)memcpy_s(rstFrame, frameSize, frame, frameSize);
453 rst->frameBuffer = rstFrame;
454 rst->frameLength = frameSize;
455 rst->frameBitrateKbps = info->bitrate_kbps;
456 rst->frameChannels = info->channels;
457 rst->frameSampleRate = info->hz;
458 rst->usedInputLength = usedInputLength;
459 return 1;
460 }
461
AudioDemuxerMp3IterateCallbackForPrepare(void * userData,const uint8_t * frame,int frameSize,int freeFormatBytes,size_t bufSize,uint64_t offset,Mp3DemuxerFrameInfo * info)462 int Minimp3DemuxerPlugin::AudioDemuxerMp3IterateCallbackForPrepare(void *userData, const uint8_t *frame,
463 int frameSize, int freeFormatBytes,
464 size_t bufSize, uint64_t offset,
465 Mp3DemuxerFrameInfo *info)
466 {
467 return AudioDemuxerMp3IterateCallbackForProbe(userData, frame, frameSize, freeFormatBytes, bufSize, offset, info);
468 }
469
AudioDemuxerMp3Open()470 void Minimp3DemuxerPlugin::AudioDemuxerMp3Open()
471 {
472 minimp3DemuxerImpl_.init(&mp3DemuxerAttr_.mp3DemuxerHandle);
473 return;
474 }
475
AudioDemuxerMp3Close()476 int Minimp3DemuxerPlugin::AudioDemuxerMp3Close()
477 {
478 return 0;
479 }
480
AudioDemuxerMp3Prepare(AudioDemuxerMp3Attr * mp3DemuxerAttr,uint8_t * inputBuffer,uint32_t inputLength,AudioDemuxerRst * mp3DemuxerRst)481 Status Minimp3DemuxerPlugin::AudioDemuxerMp3Prepare(AudioDemuxerMp3Attr *mp3DemuxerAttr, uint8_t *inputBuffer,
482 uint32_t inputLength, AudioDemuxerRst *mp3DemuxerRst)
483 {
484 return AudioDemuxerMp3Probe(mp3DemuxerAttr, inputBuffer, inputLength, mp3DemuxerRst);
485 }
486
AudioDemuxerMp3Process(uint8_t * buf,uint32_t len)487 int Minimp3DemuxerPlugin::AudioDemuxerMp3Process(uint8_t *buf, uint32_t len)
488 {
489 if ((buf == nullptr) || (len < 0)) {
490 MEDIA_LOG_E(PUBLIC_LOG_S " arg error", __func__);
491 return AUDIO_DEMUXER_ERROR;
492 }
493 if (len == 0) {
494 MEDIA_LOG_W("len == 0");
495 return AUDIO_DEMUXER_PROCESS_NEED_MORE_DATA;
496 }
497 int ret = 0;
498 uint32_t processLen = len;
499 AudioDemuxerMp3IgnoreTailZero(buf, &processLen);
500 // this memset_s will always success
501 (void)memset_s(&mp3DemuxerRst_, sizeof(AudioDemuxerRst), 0x00, sizeof(AudioDemuxerRst));
502 mp3DemuxerAttr_.rst = &mp3DemuxerRst_;
503 mp3DemuxerAttr_.internalRemainLen = processLen;
504 ret = minimp3DemuxerImpl_.iterateBuf(buf, processLen, AudioDemuxerMp3IterateCallback, &mp3DemuxerAttr_);
505 if (mp3DemuxerAttr_.mp3SeekFlag == 1 && mp3DemuxerAttr_.discardItemCount < MP3_SEEK_DISCARD_ITEMS) {
506 (void)memset_s(mp3DemuxerRst_.frameBuffer, mp3DemuxerRst_.frameLength, 0x00, mp3DemuxerRst_.frameLength);
507 mp3DemuxerAttr_.discardItemCount++;
508 } else {
509 mp3DemuxerAttr_.discardItemCount = 0;
510 mp3DemuxerAttr_.mp3SeekFlag = 0;
511 }
512 if (ret == 0 || ret == 1) {
513 return AUDIO_DEMUXER_SUCCESS;
514 } else {
515 return AUDIO_DEMUXER_ERROR;
516 }
517 }
518
AudioDemuxerMp3FreeFrame(uint8_t * frame)519 int Minimp3DemuxerPlugin::AudioDemuxerMp3FreeFrame(uint8_t *frame)
520 {
521 if (frame) {
522 free(frame);
523 return 0;
524 } else {
525 return -1;
526 }
527 }
528
AudioDemuxerMp3Seek(uint32_t pos,uint8_t * buf,uint32_t len,AudioDemuxerRst * rst)529 int Minimp3DemuxerPlugin::AudioDemuxerMp3Seek(uint32_t pos, uint8_t *buf, uint32_t len, AudioDemuxerRst *rst)
530 {
531 return 0;
532 }
533
AudioDemuxerMp3GetSeekPosition(uint32_t targetTimeMs,uint64_t * pos)534 int Minimp3DemuxerPlugin::AudioDemuxerMp3GetSeekPosition(uint32_t targetTimeMs, uint64_t *pos)
535 {
536 if (!pos) {
537 MEDIA_LOG_I("pos nullptr error");
538 return AUDIO_DEMUXER_ERROR;
539 }
540 uint32_t targetPos = targetTimeMs * mp3DemuxerAttr_.bitRate / 8 + mp3DemuxerAttr_.id3v2Size;
541 if (targetPos > mp3DemuxerAttr_.fileSize) {
542 *pos = 0;
543 return -1;
544 }
545 *pos = static_cast<uint64_t>(targetPos);
546 mp3DemuxerAttr_.mp3SeekFlag = 1;
547 return 0;
548 }
549
550 namespace {
AudioDecmuxerMp3Id3v2SizeCalculate(const uint8_t * buf)551 size_t AudioDecmuxerMp3Id3v2SizeCalculate(const uint8_t *buf)
552 {
553 return (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
554 }
555
AudioDemuxerMp3HasId3v2(const uint8_t * buf)556 bool AudioDemuxerMp3HasId3v2(const uint8_t *buf)
557 {
558 return !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) ||
559 (buf[8] & 0x80) || (buf[9] & 0x80));
560 }
561
AudioDemuxerMp3GetId3v2Size(const uint8_t * buf,size_t bufSize)562 size_t AudioDemuxerMp3GetId3v2Size(const uint8_t *buf, size_t bufSize)
563 {
564 if (bufSize >= ID3_DETECT_SIZE && AudioDemuxerMp3HasId3v2(buf)) {
565 size_t id3v2Size = AudioDecmuxerMp3Id3v2SizeCalculate(buf);
566 if ((buf[5] & 16)) { // 5, 16
567 id3v2Size += 10; // 10
568 }
569 return id3v2Size;
570 }
571 return 0;
572 }
573
AudioDemuxerMp3ProbeDecodeCheck(Mp3DemuxerFrameInfo * info)574 int AudioDemuxerMp3ProbeDecodeCheck(Mp3DemuxerFrameInfo *info)
575 {
576 if (!info) {
577 return -1;
578 }
579
580 std::vector<uint32_t>::iterator it = find (infoLayer.begin(), infoLayer.end(), info->layer);
581 if (it == infoLayer.end()) {
582 return -1;
583 }
584
585 it = find (infoSampleRate.begin(), infoSampleRate.end(), info->hz);
586 if (it == infoSampleRate.end()) {
587 return -1;
588 }
589
590 it = find (infoBitrateKbps.begin(), infoBitrateKbps.end(), info->bitrate_kbps);
591 if (it == infoBitrateKbps.end()) {
592 return -1;
593 }
594
595 return 0;
596 }
597
AudioDemuxerMp3IterateCallbackForProbe(void * userData,const uint8_t * frame,int frameSize,int freeFormatBytes,size_t bufSize,uint64_t offset,Mp3DemuxerFrameInfo * info)598 int AudioDemuxerMp3IterateCallbackForProbe(void *userData, const uint8_t *frame, int frameSize, int freeFormatBytes,
599 size_t bufSize, uint64_t offset, Mp3DemuxerFrameInfo *info)
600 {
601 int sampleCount;
602 Minimp3WrapperMp3decFrameInfo frameInfo;
603 AudioDemuxerMp3Attr *mp3Demuxer = static_cast<AudioDemuxerMp3Attr *>(userData);
604 AudioDemuxerRst *rst = mp3Demuxer->rst;
605 rst->frameBitrateKbps = info->bitrate_kbps;
606 rst->frameChannels = info->channels;
607 rst->frameSampleRate = info->hz;
608 rst->audioLayer = info->layer;
609 rst->samplesPerFrame = info->samples_per_frame;
610 sampleCount = Minimp3WrapperMp3decDecodeFrame(&mp3Demuxer->mp3DemuxerHandle, frame, frameSize,
611 mp3Demuxer->probePcmBuf, &frameInfo);
612 if (sampleCount <= 0 && AudioDemuxerMp3ProbeDecodeCheck(info) != 0) {
613 return -1;
614 }
615 return 1;
616 }
617
AudioDemuxerMp3Probe(AudioDemuxerMp3Attr * mp3DemuxerAttr,uint8_t * inputBuffer,uint32_t inputLength,AudioDemuxerRst * mp3DemuxerRst)618 Status AudioDemuxerMp3Probe(AudioDemuxerMp3Attr* mp3DemuxerAttr, uint8_t* inputBuffer, uint32_t inputLength,
619 AudioDemuxerRst* mp3DemuxerRst)
620 {
621 FALSE_RETURN_V_MSG_W(inputBuffer != nullptr && inputLength >= 0, Status::ERROR_INVALID_PARAMETER, "invalid parameter");
622 if (inputLength == 0) {
623 return Status::ERROR_NOT_ENOUGH_DATA;
624 }
625 int ret = -1;
626 if (mp3DemuxerAttr->id3v2SkipFlag == 0) {
627 if (mp3DemuxerAttr->id3v2Offset == 0) {
628 if (inputLength < ID3_DETECT_SIZE) {
629 mp3DemuxerRst->usedInputLength = 0;
630 return Status::ERROR_NOT_ENOUGH_DATA;
631 } else {
632 mp3DemuxerAttr->id3v2Size = AudioDemuxerMp3GetId3v2Size(inputBuffer, inputLength);
633 mp3DemuxerAttr->id3v2Offset = mp3DemuxerAttr->id3v2Size;
634 }
635 }
636
637 if (mp3DemuxerAttr->id3v2Offset) {
638 MEDIA_LOG_D("mp3 id3v2Offset = " PUBLIC_LOG_U32 ", input data inputLength " PUBLIC_LOG_U32,
639 mp3DemuxerAttr->id3v2Offset, inputLength);
640 if (inputLength >= mp3DemuxerAttr->id3v2Offset) {
641 mp3DemuxerRst->usedInputLength = mp3DemuxerAttr->id3v2Offset;
642 mp3DemuxerAttr->id3v2SkipFlag = 1;
643 inputLength -= mp3DemuxerAttr->id3v2Offset;
644 inputBuffer += mp3DemuxerAttr->id3v2Offset;
645 mp3DemuxerAttr->id3v2Offset = 0;
646 } else {
647 mp3DemuxerRst->usedInputLength = inputLength;
648 mp3DemuxerAttr->id3v2Offset = mp3DemuxerAttr->id3v2Offset - inputLength;
649 return Status::ERROR_NOT_ENOUGH_DATA;
650 }
651 }
652 }
653 mp3DemuxerAttr->rst = mp3DemuxerRst;
654 mp3DemuxerAttr->internalRemainLen = inputLength;
655 ret = Minimp3WrapperMp3decIterateBuf(inputBuffer, inputLength, AudioDemuxerMp3IterateCallbackForProbe,
656 mp3DemuxerAttr);
657 if (ret != 1) {
658 if (mp3DemuxerAttr->id3v2SkipFlag) {
659 return Status::ERROR_NOT_ENOUGH_DATA;
660 }
661 return Status::ERROR_UNSUPPORTED_FORMAT;
662 }
663 if (mp3DemuxerRst->frameBitrateKbps != 0) {
664 durationMs = static_cast<uint64_t>(fileSize * 8 / mp3DemuxerRst->frameBitrateKbps); // 8
665 }
666 MEDIA_LOG_I("bitrate_kbps = " PUBLIC_LOG_U32 " info->channels = " PUBLIC_LOG_U8 " info->hz = "
667 PUBLIC_LOG_U32, mp3DemuxerRst->frameBitrateKbps, mp3DemuxerRst->frameChannels,
668 mp3DemuxerRst->frameSampleRate);
669 return Status::OK;
670 }
671
Sniff(const std::string & name,std::shared_ptr<DataSource> dataSource)672 int Sniff(const std::string& name, std::shared_ptr<DataSource> dataSource)
673 {
674 MEDIA_LOG_I("Sniff in");
675 Status status;
676 auto buffer = std::make_shared<Buffer>();
677 auto bufData = buffer->AllocMemory(nullptr, PROBE_READ_LENGTH);
678 int processLoop = 1;
679 uint8_t *inputDataPtr = nullptr;
680 int offset = 0;
681 int readSize = PROBE_READ_LENGTH;
682 size_t sourceSize = 0;
683 dataSource->GetSize(sourceSize);
684 while (processLoop) {
685 if (sourceSize < PROBE_READ_LENGTH && sourceSize != 0) {
686 readSize = sourceSize;
687 }
688 status = dataSource->ReadAt(offset, buffer, static_cast<size_t>(readSize));
689 if (status != Status::OK) {
690 MEDIA_LOG_E("Sniff Read Data Error");
691 return 0;
692 }
693 inputDataPtr = const_cast<uint8_t *>(bufData->GetReadOnlyData());
694
695 status = AudioDemuxerMp3Probe(&mp3ProbeAttr, inputDataPtr, bufData->GetSize(), &mp3ProbeRst);
696 switch (status) {
697 case Status::ERROR_NOT_ENOUGH_DATA:
698 OSAL::SleepFor(100); // 100
699 offset += mp3ProbeRst.usedInputLength;
700 MEDIA_LOG_D("offset " PUBLIC_LOG_D32, offset);
701 processLoop = 1;
702 break;
703 case Status::OK:
704 processLoop = 0;
705 break;
706 case Status::ERROR_UNSUPPORTED_FORMAT:
707 return 0;
708 case Status::ERROR_UNKNOWN:
709 default:
710 MEDIA_LOG_I("AUDIO_DEMUXER_PREPARE_UNMATCHED_FORMAT " PUBLIC_LOG_D32, status);
711 return 0;
712 }
713 }
714 return MAX_RANK;
715 }
716
RegisterPlugin(const std::shared_ptr<Register> & reg)717 Status RegisterPlugin(const std::shared_ptr<Register>& reg)
718 {
719 MEDIA_LOG_I("RegisterPlugin called.");
720 if (!reg) {
721 MEDIA_LOG_I("RegisterPlugin failed due to nullptr pointer for reg.");
722 return Status::ERROR_INVALID_PARAMETER;
723 }
724
725 std::string pluginName = "Minimp3DemuxerPlugin";
726 DemuxerPluginDef regInfo;
727 regInfo.name = pluginName;
728 regInfo.description = "adapter for minimp3 demuxer plugin";
729 regInfo.rank = MAX_RANK;
730 regInfo.creator = [](const std::string &name) -> std::shared_ptr<DemuxerPlugin> {
731 return std::make_shared<Minimp3DemuxerPlugin>(name);
732 };
733 regInfo.sniffer = Sniff;
734 auto rtv = reg->AddPlugin(regInfo);
735 if (rtv != Status::OK) {
736 MEDIA_LOG_I("RegisterPlugin AddPlugin failed with return " PUBLIC_LOG_D32, static_cast<int>(rtv));
737 }
738 return Status::OK;
739 }
740 }
741
__anon44bb28410402null742 PLUGIN_DEFINITION(Minimp3Demuxer, LicenseType::CC0, RegisterPlugin, [] {});
743 } // namespace Minimp3
744 } // namespace Plugin
745 } // namespace Media
746 } // namespace OHOS
747