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,
55                                            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,uint64_t offset,Mp3DemuxerFrameInfo * info)418 int Minimp3DemuxerPlugin::AudioDemuxerMp3IterateCallback(void *userData, const uint8_t *frame, int frameSize,
419                                                          uint64_t offset, 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,Mp3DemuxerFrameInfo * info)462 int Minimp3DemuxerPlugin::AudioDemuxerMp3IterateCallbackForPrepare(void *userData, const uint8_t *frame,
463                                                                    int frameSize, Mp3DemuxerFrameInfo *info)
464 {
465     return AudioDemuxerMp3IterateCallbackForProbe(userData, frame, frameSize, info);
466 }
467 
AudioDemuxerMp3Open()468 void Minimp3DemuxerPlugin::AudioDemuxerMp3Open()
469 {
470     minimp3DemuxerImpl_.init(&mp3DemuxerAttr_.mp3DemuxerHandle);
471     return;
472 }
473 
AudioDemuxerMp3Close()474 int  Minimp3DemuxerPlugin::AudioDemuxerMp3Close()
475 {
476     return 0;
477 }
478 
AudioDemuxerMp3Prepare(AudioDemuxerMp3Attr * mp3DemuxerAttr,uint8_t * inputBuffer,uint32_t inputLength,AudioDemuxerRst * mp3DemuxerRst)479 Status Minimp3DemuxerPlugin::AudioDemuxerMp3Prepare(AudioDemuxerMp3Attr *mp3DemuxerAttr, uint8_t *inputBuffer,
480                                                     uint32_t inputLength, AudioDemuxerRst *mp3DemuxerRst)
481 {
482     return AudioDemuxerMp3Probe(mp3DemuxerAttr, inputBuffer, inputLength, mp3DemuxerRst);
483 }
484 
AudioDemuxerMp3Process(uint8_t * buf,uint32_t len)485 int Minimp3DemuxerPlugin::AudioDemuxerMp3Process(uint8_t *buf, uint32_t len)
486 {
487     if ((buf == nullptr) || (len < 0)) {
488         MEDIA_LOG_E(PUBLIC_LOG_S " arg error", __func__);
489         return AUDIO_DEMUXER_ERROR;
490     }
491     if (len == 0) {
492         MEDIA_LOG_W("len == 0");
493         return AUDIO_DEMUXER_PROCESS_NEED_MORE_DATA;
494     }
495     int ret = 0;
496     uint32_t processLen = len;
497     AudioDemuxerMp3IgnoreTailZero(buf, &processLen);
498     // this memset_s will always success
499     (void)memset_s(&mp3DemuxerRst_, sizeof(AudioDemuxerRst), 0x00, sizeof(AudioDemuxerRst));
500     mp3DemuxerAttr_.rst = &mp3DemuxerRst_;
501     mp3DemuxerAttr_.internalRemainLen = processLen;
502     ret = minimp3DemuxerImpl_.iterateBuf(buf, processLen, AudioDemuxerMp3IterateCallback, &mp3DemuxerAttr_);
503     if (mp3DemuxerAttr_.mp3SeekFlag == 1 && mp3DemuxerAttr_.discardItemCount < MP3_SEEK_DISCARD_ITEMS) {
504         (void)memset_s(mp3DemuxerRst_.frameBuffer, mp3DemuxerRst_.frameLength, 0x00, mp3DemuxerRst_.frameLength);
505         mp3DemuxerAttr_.discardItemCount++;
506     } else {
507         mp3DemuxerAttr_.discardItemCount = 0;
508         mp3DemuxerAttr_.mp3SeekFlag = 0;
509     }
510     if (ret == 0 || ret == 1) {
511         return AUDIO_DEMUXER_SUCCESS;
512     } else {
513         return AUDIO_DEMUXER_ERROR;
514     }
515 }
516 
AudioDemuxerMp3FreeFrame(uint8_t * frame)517 int Minimp3DemuxerPlugin::AudioDemuxerMp3FreeFrame(uint8_t *frame)
518 {
519     if (frame) {
520         free(frame);
521         return 0;
522     } else {
523         return -1;
524     }
525 }
526 
AudioDemuxerMp3Seek(uint32_t pos,uint8_t * buf,uint32_t len,AudioDemuxerRst * rst)527 int Minimp3DemuxerPlugin::AudioDemuxerMp3Seek(uint32_t pos, uint8_t *buf, uint32_t len, AudioDemuxerRst *rst)
528 {
529     return 0;
530 }
531 
AudioDemuxerMp3GetSeekPosition(uint32_t targetTimeMs,uint64_t * pos)532 int Minimp3DemuxerPlugin::AudioDemuxerMp3GetSeekPosition(uint32_t targetTimeMs, uint64_t *pos)
533 {
534     if (!pos) {
535         MEDIA_LOG_I("pos nullptr error");
536         return AUDIO_DEMUXER_ERROR;
537     }
538     uint32_t targetPos = targetTimeMs * mp3DemuxerAttr_.bitRate / 8 + mp3DemuxerAttr_.id3v2Size;
539     if (targetPos > mp3DemuxerAttr_.fileSize) {
540         *pos = 0;
541         return -1;
542     }
543     *pos = static_cast<uint64_t>(targetPos);
544     mp3DemuxerAttr_.mp3SeekFlag = 1;
545     return 0;
546 }
547 
548 namespace {
AudioDecmuxerMp3Id3v2SizeCalculate(const uint8_t * buf)549 size_t AudioDecmuxerMp3Id3v2SizeCalculate(const uint8_t *buf)
550 {
551     return (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
552 }
553 
AudioDemuxerMp3HasId3v2(const uint8_t * buf)554 bool AudioDemuxerMp3HasId3v2(const uint8_t *buf)
555 {
556     return !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) ||
557                   (buf[8] & 0x80) || (buf[9] & 0x80));
558 }
559 
AudioDemuxerMp3GetId3v2Size(const uint8_t * buf,size_t bufSize)560 size_t AudioDemuxerMp3GetId3v2Size(const uint8_t *buf, size_t bufSize)
561 {
562     if (bufSize >= ID3_DETECT_SIZE && AudioDemuxerMp3HasId3v2(buf)) {
563         size_t id3v2Size = AudioDecmuxerMp3Id3v2SizeCalculate(buf);
564         if ((buf[5] & 16)) { // 5, 16
565             id3v2Size += 10; // 10
566         }
567         return id3v2Size;
568     }
569     return 0;
570 }
571 
AudioDemuxerMp3ProbeDecodeCheck(Mp3DemuxerFrameInfo * info)572 int AudioDemuxerMp3ProbeDecodeCheck(Mp3DemuxerFrameInfo *info)
573 {
574     if (!info) {
575         return -1;
576     }
577 
578     std::vector<uint32_t>::iterator it = find (infoLayer.begin(), infoLayer.end(), info->layer);
579     if (it == infoLayer.end()) {
580         return -1;
581     }
582 
583     it = find (infoSampleRate.begin(), infoSampleRate.end(), info->hz);
584     if (it == infoSampleRate.end()) {
585         return -1;
586     }
587 
588     it = find (infoBitrateKbps.begin(), infoBitrateKbps.end(), info->bitrate_kbps);
589     if (it == infoBitrateKbps.end()) {
590         return -1;
591     }
592 
593     return 0;
594 }
595 
AudioDemuxerMp3IterateCallbackForProbe(void * userData,const uint8_t * frame,int frameSize,Mp3DemuxerFrameInfo * info)596 int AudioDemuxerMp3IterateCallbackForProbe(void *userData, const uint8_t *frame, int frameSize,
597                                            Mp3DemuxerFrameInfo *info)
598 {
599     int sampleCount;
600     Minimp3WrapperMp3decFrameInfo frameInfo;
601     AudioDemuxerMp3Attr *mp3Demuxer = static_cast<AudioDemuxerMp3Attr *>(userData);
602     AudioDemuxerRst *rst  = mp3Demuxer->rst;
603     rst->frameBitrateKbps = info->bitrate_kbps;
604     rst->frameChannels    = info->channels;
605     rst->frameSampleRate  = info->hz;
606     rst->audioLayer       = info->layer;
607     rst->samplesPerFrame  = info->samples_per_frame;
608     sampleCount = Minimp3WrapperMp3decDecodeFrame(&mp3Demuxer->mp3DemuxerHandle, frame, frameSize,
609                                                   mp3Demuxer->probePcmBuf, &frameInfo);
610     if (sampleCount <= 0 && AudioDemuxerMp3ProbeDecodeCheck(info) != 0) {
611         return -1;
612     }
613     return 1;
614 }
615 
AudioDemuxerMp3Probe(AudioDemuxerMp3Attr * mp3DemuxerAttr,uint8_t * inputBuffer,uint32_t inputLength,AudioDemuxerRst * mp3DemuxerRst)616 Status AudioDemuxerMp3Probe(AudioDemuxerMp3Attr* mp3DemuxerAttr, uint8_t* inputBuffer, uint32_t inputLength,
617                             AudioDemuxerRst* mp3DemuxerRst)
618 {
619     FALSE_RETURN_V_MSG_W(inputBuffer != nullptr && inputLength >= 0, Status::ERROR_INVALID_PARAMETER, "invalid parameter");
620     if (inputLength == 0) {
621         return Status::ERROR_NOT_ENOUGH_DATA;
622     }
623     int ret = -1;
624     if (mp3DemuxerAttr->id3v2SkipFlag == 0) {
625         if (mp3DemuxerAttr->id3v2Offset == 0) {
626             if (inputLength < ID3_DETECT_SIZE) {
627                 mp3DemuxerRst->usedInputLength = 0;
628                 return Status::ERROR_NOT_ENOUGH_DATA;
629             } else {
630                 mp3DemuxerAttr->id3v2Size = AudioDemuxerMp3GetId3v2Size(inputBuffer, inputLength);
631                 mp3DemuxerAttr->id3v2Offset = mp3DemuxerAttr->id3v2Size;
632             }
633         }
634 
635         if (mp3DemuxerAttr->id3v2Offset) {
636             MEDIA_LOG_D("mp3 id3v2Offset = " PUBLIC_LOG_U32 ", input data inputLength " PUBLIC_LOG_U32,
637                         mp3DemuxerAttr->id3v2Offset, inputLength);
638             if (inputLength >= mp3DemuxerAttr->id3v2Offset) {
639                 mp3DemuxerRst->usedInputLength = mp3DemuxerAttr->id3v2Offset;
640                 mp3DemuxerAttr->id3v2SkipFlag  = 1;
641                 inputLength -= mp3DemuxerAttr->id3v2Offset;
642                 inputBuffer += mp3DemuxerAttr->id3v2Offset;
643                 mp3DemuxerAttr->id3v2Offset = 0;
644             } else {
645                 mp3DemuxerRst->usedInputLength = inputLength;
646                 mp3DemuxerAttr->id3v2Offset = mp3DemuxerAttr->id3v2Offset - inputLength;
647                 return Status::ERROR_NOT_ENOUGH_DATA;
648             }
649         }
650     }
651     mp3DemuxerAttr->rst = mp3DemuxerRst;
652     mp3DemuxerAttr->internalRemainLen = inputLength;
653     ret = Minimp3WrapperMp3decIterateBuf(inputBuffer, inputLength, AudioDemuxerMp3IterateCallbackForProbe,
654                                          mp3DemuxerAttr);
655     if (ret != 1) {
656         if (mp3DemuxerAttr->id3v2SkipFlag) {
657             return Status::ERROR_NOT_ENOUGH_DATA;
658         }
659         return Status::ERROR_UNSUPPORTED_FORMAT;
660     }
661     if (mp3DemuxerRst->frameBitrateKbps != 0) {
662         durationMs = static_cast<uint64_t>(fileSize * 8 / mp3DemuxerRst->frameBitrateKbps); // 8
663     }
664     MEDIA_LOG_I("bitrate_kbps = " PUBLIC_LOG_U32 " info->channels = " PUBLIC_LOG_U8 " info->hz = "
665                 PUBLIC_LOG_U32, mp3DemuxerRst->frameBitrateKbps, mp3DemuxerRst->frameChannels,
666                 mp3DemuxerRst->frameSampleRate);
667     return Status::OK;
668 }
669 
Sniff(const std::string & name,std::shared_ptr<DataSource> dataSource)670 int Sniff(const std::string& name, std::shared_ptr<DataSource> dataSource)
671 {
672     MEDIA_LOG_I("Sniff in");
673     Status status;
674     auto buffer = std::make_shared<Buffer>();
675     auto bufData = buffer->AllocMemory(nullptr, PROBE_READ_LENGTH);
676     int processLoop = 1;
677     uint8_t *inputDataPtr = nullptr;
678     int offset = 0;
679     int readSize = PROBE_READ_LENGTH;
680     uint64_t sourceSize = 0;
681     dataSource->GetSize(sourceSize);
682     while (processLoop) {
683         if (sourceSize < PROBE_READ_LENGTH && sourceSize != 0) {
684             readSize = sourceSize;
685         }
686         status = dataSource->ReadAt(offset, buffer, static_cast<size_t>(readSize));
687         if (status != Status::OK) {
688             MEDIA_LOG_E("Sniff Read Data Error");
689             return 0;
690         }
691         inputDataPtr = const_cast<uint8_t *>(bufData->GetReadOnlyData());
692 
693         status = AudioDemuxerMp3Probe(&mp3ProbeAttr, inputDataPtr, bufData->GetSize(), &mp3ProbeRst);
694         switch (status) {
695             case Status::ERROR_NOT_ENOUGH_DATA:
696                 OSAL::SleepFor(100); // 100
697                 offset += mp3ProbeRst.usedInputLength;
698                 MEDIA_LOG_D("offset " PUBLIC_LOG_D32, offset);
699                 processLoop = 1;
700                 break;
701             case Status::OK:
702                 processLoop = 0;
703                 break;
704             case Status::ERROR_UNSUPPORTED_FORMAT:
705                 return 0;
706             case Status::ERROR_UNKNOWN:
707             default:
708                 MEDIA_LOG_I("AUDIO_DEMUXER_PREPARE_UNMATCHED_FORMAT " PUBLIC_LOG_D32, status);
709                 return 0;
710         }
711     }
712     return MAX_RANK;
713 }
714 
RegisterPlugin(const std::shared_ptr<Register> & reg)715 Status RegisterPlugin(const std::shared_ptr<Register>& reg)
716 {
717     MEDIA_LOG_I("RegisterPlugin called.");
718     if (!reg) {
719         MEDIA_LOG_I("RegisterPlugin failed due to nullptr pointer for reg.");
720         return Status::ERROR_INVALID_PARAMETER;
721     }
722 
723     std::string pluginName = "Minimp3DemuxerPlugin";
724     DemuxerPluginDef regInfo;
725     regInfo.name = pluginName;
726     regInfo.description = "adapter for minimp3 demuxer plugin";
727     regInfo.rank = MAX_RANK;
728     regInfo.creator = [](const std::string &name) -> std::shared_ptr<DemuxerPlugin> {
729         return std::make_shared<Minimp3DemuxerPlugin>(name);
730     };
731     regInfo.sniffer = Sniff;
732     auto rtv = reg->AddPlugin(regInfo);
733     if (rtv != Status::OK) {
734         MEDIA_LOG_I("RegisterPlugin AddPlugin failed with return " PUBLIC_LOG_D32, static_cast<int>(rtv));
735     }
736     return Status::OK;
737 }
738 }
739 
__anon7c563a3b0402null740 PLUGIN_DEFINITION(Minimp3Demuxer, LicenseType::CC0, RegisterPlugin, [] {});
741 } // namespace Minimp3
742 } // namespace Plugin
743 } // namespace Media
744 } // namespace OHOS
745