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 "Minimp4DemuxerPlugin"
17 
18 #include "minimp4_demuxer_plugin.h"
19 #include <algorithm>
20 #include <cstdio>
21 #include <cstring>
22 #include <new>
23 
24 #include <securec.h>
25 #include "foundation/log.h"
26 #include "foundation/osal/utils/util.h"
27 #include "foundation/utils/constants.h"
28 #include "plugin/common/plugin_time.h"
29 
30 namespace OHOS {
31 namespace Media {
32 namespace Plugin {
33 namespace Minimp4 {
34 namespace {
35 std::vector<int> sampleRateVec {
36     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350
37 };
38 uint32_t g_durationMs = 0;
39 uint32_t g_fileSize = 0;
40 uint32_t g_readDataSize = 0;
41 constexpr int8_t ADTS_HEADER_SIZE = 7;
42 constexpr int8_t MP4_HEADER_OFFSET = 4;
43 constexpr int8_t RANK_MAX = 100;
44 constexpr unsigned int DEFAULT_AUDIO_SAMPLE_PER_FRAME = 1024;
45 constexpr unsigned int MEDIA_IO_SIZE = 16 * 1024;
46 int Sniff(const std::string &name, std::shared_ptr<DataSource> dataSource);
47 Status RegisterPlugins(const std::shared_ptr<Register> &reg);
48 }
49 
MiniMP4DemuxerPlugin(std::string name)50 MiniMP4DemuxerPlugin::MiniMP4DemuxerPlugin(std::string name)
51     : DemuxerPlugin(std::move(name)),
52       ioContext_(),
53       fileSize_(0),
54       inIoBuffer_(nullptr),
55       inIoBufferSize_(MEDIA_IO_SIZE),
56       ioDataRemainSize_(0),
57       sampleIndex_(0)
58 {
59     (void)memset_s(&miniMP4_, sizeof(MP4D_demux_t), 0, sizeof(MP4D_demux_t));
60     MEDIA_LOG_I("MiniMP4DemuxerPlugin, plugin name: " PUBLIC_LOG_S, pluginName_.c_str());
61 }
62 
~MiniMP4DemuxerPlugin()63 MiniMP4DemuxerPlugin::~MiniMP4DemuxerPlugin()
64 {
65     MEDIA_LOG_I("~MiniMP4DemuxerPlugin");
66 }
67 
SetDataSource(const std::shared_ptr<DataSource> & source)68 Status MiniMP4DemuxerPlugin::SetDataSource(const std::shared_ptr<DataSource> &source)
69 {
70     ioContext_.dataSource = source;
71     if (ioContext_.dataSource != nullptr) {
72         ioContext_.dataSource->GetSize(fileSize_);
73     }
74     g_fileSize = fileSize_;
75     MEDIA_LOG_I("FileSize_ " PUBLIC_LOG_U64, fileSize_);
76     return Status::OK;
77 }
78 
Init()79 Status MiniMP4DemuxerPlugin::Init()
80 {
81     MEDIA_LOG_I("Init called");
82     inIoBuffer_ = static_cast<uint8_t *>(malloc(inIoBufferSize_));
83     if (inIoBuffer_ == nullptr) {
84         MEDIA_LOG_E("inIoBuffer_ malloc failed");
85         return Status::ERROR_NO_MEMORY;
86     }
87     (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
88     return Status::OK;
89 }
90 
Deinit()91 Status MiniMP4DemuxerPlugin::Deinit()
92 {
93     if (inIoBuffer_) {
94         free(inIoBuffer_);
95         inIoBuffer_ = nullptr;
96     }
97     return Status::OK;
98 }
99 
Prepare()100 Status MiniMP4DemuxerPlugin::Prepare()
101 {
102     return Status::OK;
103 }
104 
Reset()105 Status MiniMP4DemuxerPlugin::Reset()
106 {
107     MEDIA_LOG_D("Reset in");
108     ioContext_.eos = false;
109     ioContext_.offset = 0;
110     ioContext_.dataSource.reset();
111     ioDataRemainSize_ = 0;
112     (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
113     return Status::OK;
114 }
115 
Stop()116 Status MiniMP4DemuxerPlugin::Stop()
117 {
118     return Status::OK;
119 }
120 
GetParameter(Tag tag,ValueType & value)121 Status MiniMP4DemuxerPlugin::GetParameter(Tag tag, ValueType &value)
122 {
123     (void)tag;
124     (void)value;
125     return Status::ERROR_UNIMPLEMENTED;
126 }
127 
SetParameter(Tag tag,const ValueType & value)128 Status MiniMP4DemuxerPlugin::SetParameter(Tag tag, const ValueType &value)
129 {
130     (void)tag;
131     (void)value;
132     return Status::ERROR_UNIMPLEMENTED;
133 }
134 
GetAllocator()135 std::shared_ptr<Allocator> MiniMP4DemuxerPlugin::GetAllocator()
136 {
137     return nullptr;
138 }
139 
SetCallback(Callback * cb)140 Status MiniMP4DemuxerPlugin::SetCallback(Callback* cb)
141 {
142     return Status::OK;
143 }
144 
GetTrackCount()145 size_t MiniMP4DemuxerPlugin::GetTrackCount()
146 {
147     size_t trackCnt = 0;
148     return trackCnt;
149 }
150 
SelectTrack(int32_t trackId)151 Status MiniMP4DemuxerPlugin::SelectTrack(int32_t trackId)
152 {
153     return Status::ERROR_UNIMPLEMENTED;
154 }
155 
UnselectTrack(int32_t trackId)156 Status MiniMP4DemuxerPlugin::UnselectTrack(int32_t trackId)
157 {
158     return Status::OK;
159 }
160 
GetSelectedTracks(std::vector<int32_t> & trackIds)161 Status MiniMP4DemuxerPlugin::GetSelectedTracks(std::vector<int32_t> &trackIds)
162 {
163     trackIds.clear();
164     trackIds.push_back(1);
165     return Status::OK;
166 }
167 
DoReadFromSource(uint32_t readSize)168 Status MiniMP4DemuxerPlugin::DoReadFromSource(uint32_t readSize)
169 {
170     if (readSize == 0) {
171         return Status::OK;
172     }
173     auto buffer  = std::make_shared<Buffer>();
174     auto bufData = buffer->AllocMemory(nullptr, readSize);
175     int retryTimes = 0;
176     MEDIA_LOG_D("readSize " PUBLIC_LOG_U32 " inIoBufferSize_ " PUBLIC_LOG_D32 "ioDataRemainSize_ "
177                 PUBLIC_LOG_U32 "", readSize, inIoBufferSize_, ioDataRemainSize_);
178     do {
179         auto result = ioContext_.dataSource->ReadAt(ioContext_.offset, buffer, static_cast<size_t>(readSize));
180         MEDIA_LOG_D("ioContext_.offset " PUBLIC_LOG_D32, static_cast<uint32_t>(ioContext_.offset));
181         if (result != Status::OK) {
182             MEDIA_LOG_W("read data from source warning " PUBLIC_LOG_D32, static_cast<int>(result));
183             return result;
184         }
185 
186         MEDIA_LOG_D("bufData->GetSize() " PUBLIC_LOG_ZU, bufData->GetSize());
187         if (bufData->GetSize() > 0) {
188             if (readSize >= bufData->GetSize()) {
189                 (void)memcpy_s(inIoBuffer_ + ioDataRemainSize_, readSize,
190                     const_cast<uint8_t *>(bufData->GetReadOnlyData()), bufData->GetSize());
191             } else {
192                 MEDIA_LOG_E("Error: readSize < bufData->GetSize()");
193                 return Status::ERROR_UNKNOWN;
194             }
195             ioContext_.offset += bufData->GetSize();
196             ioDataRemainSize_  += bufData->GetSize();
197         }
198         if (bufData->GetSize() == 0 && ioDataRemainSize_ == 0 && retryTimes < 200) { // 200
199             OHOS::Media::OSAL::SleepFor(30); // 30
200             retryTimes++;
201             continue;
202         }
203         if (retryTimes >= 200) { // 200
204             MEDIA_LOG_E("Warning: not end of file, but do not have enough data");
205             return Status::ERROR_NOT_ENOUGH_DATA;
206         }
207         break;
208     } while (true);
209     return Status::OK;
210 }
211 
GetDataFromSource()212 Status MiniMP4DemuxerPlugin::GetDataFromSource()
213 {
214     uint32_t ioNeedReadSize = inIoBufferSize_ - ioDataRemainSize_;
215     MEDIA_LOG_D("ioDataRemainSize_ " PUBLIC_LOG_D32 " ioNeedReadSize " PUBLIC_LOG_D32, ioDataRemainSize_,
216         ioNeedReadSize);
217     if (ioDataRemainSize_) {
218         // 将剩余数据移动到buffer的起始位置
219         auto ret = memmove_s(inIoBuffer_,
220                              ioDataRemainSize_,
221                              inIoBuffer_ + g_readDataSize,
222                              ioDataRemainSize_);
223         if (ret != 0) {
224             MEDIA_LOG_E("copy buffer error(" PUBLIC_LOG_D32 ")", ret);
225             return Status::ERROR_UNKNOWN;
226         }
227         ret = memset_s(inIoBuffer_ + ioDataRemainSize_, ioNeedReadSize, 0x00, ioNeedReadSize);
228         if (ret != 0) {
229             MEDIA_LOG_E("memset_s buffer error(" PUBLIC_LOG_D32 ")", ret);
230             return Status::ERROR_UNKNOWN;
231         }
232     }
233     if (ioContext_.offset >= fileSize_ && ioDataRemainSize_ == 0) {
234         ioContext_.eos = true;
235         return Status::END_OF_STREAM;
236     }
237     if (ioContext_.offset + ioNeedReadSize > fileSize_) {
238         ioNeedReadSize = fileSize_ - ioContext_.offset; // 在读取文件即将结束时,剩余数据不足,更新读取长度
239     }
240 
241     return DoReadFromSource(ioNeedReadSize);
242 }
243 
GetMediaInfo(MediaInfo & mediaInfo)244 Status MiniMP4DemuxerPlugin::GetMediaInfo(MediaInfo &mediaInfo)
245 {
246     if (fileSize_ == 0 || ioContext_.dataSource == nullptr) {
247         return Status::ERROR_UNKNOWN;
248     }
249 
250     if (MP4D_open(&miniMP4_, ReadCallback, reinterpret_cast<void *>(this), fileSize_) == 0) {
251         MEDIA_LOG_E("MP4D_open IS ERROR");
252         return Status::ERROR_MISMATCHED_TYPE;
253     }
254     if (AudioAdapterForDecoder() != Status::OK) {
255         return Status::ERROR_UNKNOWN;
256     }
257     mediaInfo.tracks.resize(1);
258     mediaInfo.tracks[0].Set<Tag::MEDIA_TYPE>(MediaType::AUDIO);
259     mediaInfo.tracks[0].Set<Tag::AUDIO_SAMPLE_RATE>(miniMP4_.track->SampleDescription.audio.samplerate_hz);
260     mediaInfo.tracks[0].Set<Tag::MEDIA_BITRATE>(miniMP4_.track->avg_bitrate_bps);
261     mediaInfo.tracks[0].Set<Tag::AUDIO_CHANNELS>(miniMP4_.track->SampleDescription.audio.channelcount);
262     mediaInfo.tracks[0].Set<Tag::TRACK_ID>(0);
263     mediaInfo.tracks[0].Set<Tag::MIME>(MEDIA_MIME_AUDIO_AAC);
264     mediaInfo.tracks[0].Set<Tag::AUDIO_MPEG_VERSION>(4); // 4
265     mediaInfo.tracks[0].Set<Tag::AUDIO_AAC_PROFILE>(AudioAacProfile::LC);
266     mediaInfo.tracks[0].Set<Tag::AUDIO_AAC_STREAM_FORMAT>(AudioAacStreamFormat::MP4ADTS);
267     mediaInfo.tracks[0].Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::S16);
268     mediaInfo.tracks[0].Set<Tag::AUDIO_SAMPLE_PER_FRAME>(DEFAULT_AUDIO_SAMPLE_PER_FRAME);
269     if (miniMP4_.track->SampleDescription.audio.channelcount == 1) {
270         mediaInfo.tracks[0].Set<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::MONO);
271     } else {
272         mediaInfo.tracks[0].Set<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::STEREO);
273     }
274 
275     unsigned int frameSize = 0;
276     unsigned int timeStamp = 0;
277     unsigned int duration = 0;
278     int64_t offset = MP4D_frame_offset(&miniMP4_, 0, 0, &frameSize, &timeStamp, &duration);
279     ioDataRemainSize_ = 0;
280     ioContext_.offset = offset;
281     MEDIA_LOG_D("samplerate_hz " PUBLIC_LOG_D32,
282         static_cast<uint32_t>(miniMP4_.track->SampleDescription.audio.samplerate_hz));
283     MEDIA_LOG_D("avg_bitrate_bps " PUBLIC_LOG_D32, static_cast<uint32_t>(miniMP4_.track->avg_bitrate_bps));
284     MEDIA_LOG_D("channel num " PUBLIC_LOG_D32,
285         static_cast<uint32_t>(miniMP4_.track->SampleDescription.audio.channelcount));
286     return Status::OK;
287 }
288 
289 
FillADTSHead(std::shared_ptr<Memory> & data,unsigned int frameSize)290 void MiniMP4DemuxerPlugin::FillADTSHead(std::shared_ptr<Memory> &data, unsigned int frameSize)
291 {
292     uint8_t adtsHeader[ADTS_HEADER_SIZE] = {0};
293     unsigned int channelConfig = miniMP4_.track->SampleDescription.audio.channelcount;
294     unsigned int packetLen = frameSize + 7;
295     unsigned int samplerateIndex = 0;
296     /* 按格式读取信息帧 */
297     uint8_t objectTypeIndication = miniMP4_.track->object_type_indication;
298     samplerateIndex = ((miniMP4_.track->dsi[0] & 0x7) << 1) + (miniMP4_.track->dsi[1] >> 7); // 1,7 按协议取信息帧
299     adtsHeader[0] = static_cast<uint8_t>(0xFF);
300     adtsHeader[1] = static_cast<uint8_t>(0xF1);
301     adtsHeader[2] = static_cast<uint8_t>(objectTypeIndication) + (samplerateIndex << 2) + (channelConfig >> 2); // 2
302     adtsHeader[3] = static_cast<uint8_t>(((channelConfig & 0x3) << 6) + (packetLen >> 11)); // 3,6,11 按协议取信息帧
303     adtsHeader[4] = static_cast<uint8_t>((packetLen & 0x7FF) >> 3); // 4, 3 按协议取信息帧
304     adtsHeader[5] = static_cast<uint8_t>(((packetLen & 0x7) << 5) + 0x1F); // 5 按协议取信息帧
305     adtsHeader[6] = static_cast<uint8_t>(0xFC); // 6 按协议取信息帧
306     data->Write(adtsHeader, ADTS_HEADER_SIZE, 0);
307 }
308 
ReadCallback(int64_t offset,void * buffer,size_t size,void * token)309 int MiniMP4DemuxerPlugin::ReadCallback(int64_t offset, void* buffer, size_t size, void* token)
310 {
311     MiniMP4DemuxerPlugin* mp4Demuxer = reinterpret_cast<MiniMP4DemuxerPlugin*>(token);
312     unsigned int tempFileSize = mp4Demuxer->GetFileSize();
313     if (offset >= tempFileSize) {
314         MEDIA_LOG_E("ReadCallback offset is bigger");
315         return -1;
316     }
317 
318     if ((offset + size) <= mp4Demuxer->ioContext_.offset) {
319         (void)memcpy_s(buffer, size, mp4Demuxer->inIoBuffer_ +
320             (mp4Demuxer->ioDataRemainSize_ - (mp4Demuxer->ioContext_.offset - offset)), size);
321         return 0;
322     }
323     while ((offset + size) > mp4Demuxer->ioContext_.offset) {
324         MEDIA_LOG_D("offset " PUBLIC_LOG_D32 " size " PUBLIC_LOG_ZU,
325             static_cast<uint32_t>(offset), static_cast<uint32_t>(size));
326         MEDIA_LOG_D("mp4Demuxer->ioContext_.offset " PUBLIC_LOG_D32,
327             static_cast<uint32_t>(mp4Demuxer->ioContext_.offset));
328         mp4Demuxer->ioDataRemainSize_ = 0;
329         mp4Demuxer->ioContext_.offset = offset;
330         Status status = Status::ERROR_UNKNOWN;
331         g_readDataSize = mp4Demuxer->inIoBufferSize_;
332         status = mp4Demuxer->GetDataFromSource();
333         if (status != Status::OK) {
334             return (int)status;
335         }
336     }
337 
338     (void)memcpy_s(buffer, size, mp4Demuxer->inIoBuffer_, size);
339 
340     return 0;
341 }
342 
ReadFrame(Buffer & outBuffer,int32_t timeOutMs)343 Status MiniMP4DemuxerPlugin::ReadFrame(Buffer &outBuffer, int32_t timeOutMs)
344 {
345     Status retResult = Status::OK;
346     std::shared_ptr<Memory> mp4FrameData;
347     if (sampleIndex_ >= miniMP4_.track->sample_count) {
348         (void)memset_s(inIoBuffer_, MEDIA_IO_SIZE, 0, MEDIA_IO_SIZE);
349         ioDataRemainSize_ = 0;
350         MEDIA_LOG_DD("sampleIndex_ " PUBLIC_LOG_D32, sampleIndex_);
351         MEDIA_LOG_DD("miniMP4_.track->sample_count " PUBLIC_LOG_D32, miniMP4_.track->sample_count);
352         return Status::END_OF_STREAM;
353     }
354     unsigned int frameSize = 0;
355     unsigned int timeStamp = 0;
356     unsigned int duration = 0;
357     uint64_t offset = MP4D_frame_offset(&miniMP4_, 0, sampleIndex_, &frameSize, &timeStamp, &duration);
358     if (offset > fileSize_) {
359         return Status::ERROR_UNKNOWN;
360     }
361     MEDIA_LOG_D("frameSize " PUBLIC_LOG_D32 " offset " PUBLIC_LOG_D32 " sampleIndex_ " PUBLIC_LOG_D32,
362         frameSize, static_cast<uint32_t>(offset), sampleIndex_);
363     if (outBuffer.IsEmpty()) {
364         mp4FrameData = outBuffer.AllocMemory(nullptr, frameSize + ADTS_HEADER_SIZE);
365     } else {
366         mp4FrameData = outBuffer.GetMemory();
367     }
368 
369     if (offset > ioContext_.offset) {
370         (void)memset_s(inIoBuffer_, MEDIA_IO_SIZE, 0, MEDIA_IO_SIZE);
371         ioDataRemainSize_ = 0;
372         ioContext_.offset = offset;
373     }
374     retResult = GetDataFromSource();
375     if (retResult != Status::OK) {
376         return retResult;
377     }
378     FillADTSHead(mp4FrameData, frameSize);
379     size_t writeSize = mp4FrameData->Write(inIoBuffer_, frameSize, ADTS_HEADER_SIZE);
380     sampleIndex_++;
381     MEDIA_LOG_D("writeSize " PUBLIC_LOG_ZU " mp4FrameData size " PUBLIC_LOG_ZU, writeSize, mp4FrameData->GetSize());
382     ioDataRemainSize_ -= frameSize;
383     g_readDataSize = frameSize;
384 
385     return Status::OK;
386 }
387 
SeekTo(int32_t trackId,int64_t seekTime,SeekMode mode,int64_t & realSeekTime)388 Status MiniMP4DemuxerPlugin::SeekTo(int32_t trackId, int64_t seekTime, SeekMode mode, int64_t& realSeekTime)
389 {
390     unsigned int frameSize = 0;
391     unsigned int timeStamp = 0;
392     unsigned int duration = 0;
393     uint64_t offsetStart = MP4D_frame_offset(&miniMP4_, 0, 0, &frameSize, &timeStamp, &duration);
394     uint64_t offsetEnd =
395         MP4D_frame_offset(&miniMP4_, 0, miniMP4_.track->sample_count - 1, &frameSize, &timeStamp, &duration);
396     uint64_t targetPos = (Plugin::HstTime2Ms(seekTime) * static_cast<int64_t>(miniMP4_.track->avg_bitrate_bps)) / 8 +
397         offsetStart;
398     if (targetPos >= offsetEnd) {
399         sampleIndex_ = miniMP4_.track->sample_count;
400         return Status::OK;
401     }
402     sampleIndex_ = 0;
403     uint64_t tempPos = 0;
404     while (sampleIndex_ < miniMP4_.track->sample_count) {
405         tempPos = MP4D_frame_offset(&miniMP4_, 0, sampleIndex_, &frameSize, &timeStamp, &duration);
406         if (tempPos < targetPos) {
407             sampleIndex_++;
408         } else {
409             break;
410         }
411     }
412     ioContext_.offset = tempPos;
413     ioDataRemainSize_ = 0;
414     MEDIA_LOG_D("ioContext_.offset " PUBLIC_LOG_D32, static_cast<uint32_t>(ioContext_.offset));
415     (void)memset_s(inIoBuffer_, inIoBufferSize_, 0x00, inIoBufferSize_);
416     realSeekTime = seekTime;
417     return Status::OK;
418 }
419 
GetFileSize()420 uint64_t MiniMP4DemuxerPlugin::GetFileSize()
421 {
422     return fileSize_;
423 }
424 
AudioAdapterForDecoder()425 Status MiniMP4DemuxerPlugin::AudioAdapterForDecoder()
426 {
427     if (miniMP4_.track == nullptr) {
428         return Status::ERROR_UNKNOWN;
429     }
430     /* 适配解码协议 */
431     size_t sampleRateIndex = (static_cast<unsigned int>(miniMP4_.track->dsi[0] & 0x7) << 1) +
432         (static_cast<unsigned int>(miniMP4_.track->dsi[1]) >> 7);
433 
434     if ((sampleRateVec.size() <= sampleRateIndex) || (miniMP4_.track->dsi_bytes >= 20)) { // 20 按协议适配解码器
435         return Status::ERROR_MISMATCHED_TYPE;
436     }
437     miniMP4_.track->SampleDescription.audio.samplerate_hz = sampleRateVec[sampleRateIndex];
438     miniMP4_.track->SampleDescription.audio.channelcount = (miniMP4_.track->dsi[1] & 0x7F) >> 3; // 3 按协议适配解码器
439     return Status::OK;
440 }
441 
442 namespace {
Sniff(const std::string & name,std::shared_ptr<DataSource> dataSource)443 int Sniff(const std::string &name, std::shared_ptr<DataSource> dataSource)
444 {
445     unsigned char m4aCheck[] = {'f', 't', 'y', 'p'};
446     auto buffer = std::make_shared<Buffer>();
447     auto bufData = buffer->AllocMemory(nullptr, sizeof(m4aCheck));
448     int retryTimes = 0;
449     do {
450         if (dataSource->ReadAt(MP4_HEADER_OFFSET, buffer, static_cast<size_t>(sizeof(m4aCheck))) != Status::OK) {
451             return 0;
452         }
453         if (bufData->GetSize() < sizeof(m4aCheck) && retryTimes < 50) { // 50
454             OSAL::SleepFor(100); // 100
455             retryTimes++;
456             continue;
457         }
458         if (memcmp(const_cast<uint8_t *>(bufData->GetReadOnlyData()), &m4aCheck, sizeof(m4aCheck)) != 0) {
459             MEDIA_LOG_E("memcmp m4aCheck is error");
460             return 0;
461         }
462         break;
463     } while (true);
464     return RANK_MAX;
465 }
466 
RegisterPlugins(const std::shared_ptr<Register> & reg)467 Status RegisterPlugins(const std::shared_ptr<Register> &reg)
468 {
469     MEDIA_LOG_D("RegisterPlugins called");
470     if (!reg) {
471         MEDIA_LOG_E("RegisterPlugins fail due to null pointer for reg");
472         return Status::ERROR_INVALID_PARAMETER;
473     }
474     std::string pluginName = "MiniMP4DemuxerPlugin";
475     DemuxerPluginDef regInfo;
476     regInfo.name = pluginName;
477     regInfo.description = "adapter for minimp4 demuxer plugin";
478     regInfo.rank = RANK_MAX;
479     regInfo.creator = [](const std::string &name) -> std::shared_ptr<DemuxerPlugin> {
480         return std::make_shared<MiniMP4DemuxerPlugin>(name);
481     };
482     regInfo.sniffer = Sniff;
483     auto ret = reg->AddPlugin(regInfo);
484     if (ret != Status::OK) {
485         MEDIA_LOG_E("RegisterPlugin AddPlugin failed with return " PUBLIC_LOG_D32, static_cast<int>(ret));
486     }
487     return Status::OK;
488 }
489 }
490 
__anon81fc4bff0402null491 PLUGIN_DEFINITION(MiniMP4Demuxer, LicenseType::CC0, RegisterPlugins, [] {});
492 } // namespace Minimp4
493 } // namespace Plugin
494 } // namespace Media
495 } // namespace OHOS