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