• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "DemuxerFilter"
17 
18 #include "pipeline/filters/demux/demuxer_filter.h"
19 #include <algorithm>
20 #include "foundation/cpp_ext/type_traits_ext.h"
21 #include "foundation/log.h"
22 #include "foundation/utils/constants.h"
23 #include "foundation/utils/dump_buffer.h"
24 #include "foundation/utils/steady_clock.h"
25 #include "pipeline/core/compatible_check.h"
26 #include "pipeline/factory/filter_factory.h"
27 #include "pipeline/filters/common/plugin_utils.h"
28 #include "plugin/common/plugin_time.h"
29 
30 namespace OHOS {
31 namespace Media {
32 namespace Pipeline {
33 static AutoRegisterFilter<DemuxerFilter> g_registerFilterHelper("builtin.player.demuxer");
34 
35 class DemuxerFilter::DataSourceImpl : public Plugin::DataSourceHelper {
36 public:
37     explicit DataSourceImpl(const DemuxerFilter& filter);
38     ~DataSourceImpl() override = default;
39     Plugin::Status ReadAt(int64_t offset, std::shared_ptr<Plugin::Buffer>& buffer, size_t expectedLen) override;
40     Plugin::Status GetSize(uint64_t& size) override;
41     Plugin::Seekable GetSeekable() override;
42 
43 private:
44     const DemuxerFilter& filter;
45 };
46 
DataSourceImpl(const DemuxerFilter & filter)47 DemuxerFilter::DataSourceImpl::DataSourceImpl(const DemuxerFilter& filter) : filter(filter)
48 {
49 }
50 
51 /**
52  * ReadAt Plugin::DataSource::ReadAt implementation.
53  * @param offset offset in media stream.
54  * @param buffer caller allocate real buffer.
55  * @param expectedLen buffer size wanted to read.
56  * @return read result.
57  */
ReadAt(int64_t offset,std::shared_ptr<Plugin::Buffer> & buffer,size_t expectedLen)58 Plugin::Status DemuxerFilter::DataSourceImpl::ReadAt(int64_t offset, std::shared_ptr<Plugin::Buffer>& buffer,
59                                                      size_t expectedLen)
60 {
61     if (!buffer || buffer->IsEmpty() || expectedLen == 0 || !filter.IsOffsetValid(offset)) {
62         MEDIA_LOG_E("ReadAt failed, buffer empty: " PUBLIC_LOG_D32 ", expectedLen: " PUBLIC_LOG_D32
63                     ", offset: " PUBLIC_LOG_D64, !buffer, static_cast<int>(expectedLen), offset);
64         return Plugin::Status::ERROR_UNKNOWN;
65     }
66     Plugin::Status rtv = Plugin::Status::OK;
67     switch (filter.pluginState_.load()) {
68         case DemuxerState::DEMUXER_STATE_NULL:
69             rtv = Plugin::Status::ERROR_WRONG_STATE;
70             MEDIA_LOG_E("ReadAt error due to DEMUXER_STATE_NULL");
71             break;
72         case DemuxerState::DEMUXER_STATE_PARSE_HEADER: {
73             if (filter.getRange_(static_cast<uint64_t>(offset), expectedLen, buffer)) {
74                 DUMP_BUFFER2FILE(DEMUXER_INPUT_PEEK, buffer);
75             } else {
76                 rtv = Plugin::Status::ERROR_NOT_ENOUGH_DATA;
77             }
78             break;
79         }
80         case DemuxerState::DEMUXER_STATE_PARSE_FRAME: {
81             if (filter.getRange_(static_cast<uint64_t>(offset), expectedLen, buffer)) {
82                 DUMP_BUFFER2LOG("Demuxer GetRange", buffer, offset);
83                 DUMP_BUFFER2FILE(DEMUXER_INPUT_GET, buffer);
84             } else {
85                 rtv = Plugin::Status::END_OF_STREAM;
86             }
87             break;
88         }
89         default:
90             break;
91     }
92     return rtv;
93 }
94 
GetSize(uint64_t & size)95 Plugin::Status DemuxerFilter::DataSourceImpl::GetSize(uint64_t& size)
96 {
97     size = filter.mediaDataSize_;
98     return (filter.mediaDataSize_ > 0) ? Plugin::Status::OK : Plugin::Status::ERROR_WRONG_STATE;
99 }
100 
GetSeekable()101 Plugin::Seekable DemuxerFilter::DataSourceImpl::GetSeekable()
102 {
103     return filter.seekable_;
104 }
105 
DemuxerFilter(std::string name)106 DemuxerFilter::DemuxerFilter(std::string name)
107     : FilterBase(std::move(name)),
108       seekable_(Plugin::Seekable::INVALID),
109       uri_(),
110       mediaDataSize_(0),
111       task_(nullptr),
112       typeFinder_(nullptr),
113       dataPacker_(nullptr),
114       pluginName_(),
115       plugin_(nullptr),
116       pluginState_(DemuxerState::DEMUXER_STATE_NULL),
117       pluginAllocator_(nullptr),
118       dataSource_(std::make_shared<DataSourceImpl>(*this)),
119       mediaMetaData_()
120 {
121     filterType_ = FilterType::DEMUXER;
122     dataPacker_ = std::make_shared<DataPacker>();
123     task_ = std::make_shared<OSAL::Task>("DemuxerFilter");
124     MEDIA_LOG_D("ctor called");
125 }
126 
~DemuxerFilter()127 DemuxerFilter::~DemuxerFilter()
128 {
129     MEDIA_LOG_I("dtor called");
130     StopTask(true);
131     if (plugin_) {
132         plugin_->Deinit();
133     }
134 }
135 
Init(EventReceiver * receiver,FilterCallback * callback)136 void DemuxerFilter::Init(EventReceiver* receiver, FilterCallback* callback)
137 {
138     this->eventReceiver_ = receiver;
139     this->callback_ = callback;
140     inPorts_.clear();
141     outPorts_.clear();
142     inPorts_.push_back(std::make_shared<Pipeline::InPort>(this, PORT_NAME_DEFAULT));
143     state_ = FilterState::INITIALIZED;
144 }
145 
Start()146 ErrorCode DemuxerFilter::Start()
147 {
148     MEDIA_LOG_I("Start called.");
149     if (task_) {
150         task_->Start();
151     }
152     return FilterBase::Start();
153 }
154 
Stop()155 ErrorCode DemuxerFilter::Stop()
156 {
157     MEDIA_LOG_I("Stop called.");
158     dataPacker_->Stop();
159     StopTask(true);
160     Reset();
161     if (!outPorts_.empty()) {
162         PortInfo portInfo;
163         portInfo.type = PortType::OUT;
164         portInfo.ports.reserve(outPorts_.size());
165         for (const auto& outPort : outPorts_) {
166             portInfo.ports.push_back({outPort->GetName(), false});
167         }
168         if (callback_) {
169             callback_->OnCallback(FilterCallbackType::PORT_REMOVE, static_cast<Filter*>(this), portInfo);
170         }
171     }
172     return FilterBase::Stop();
173 }
174 
Pause()175 ErrorCode DemuxerFilter::Pause()
176 {
177     MEDIA_LOG_I("Pause called");
178     return FilterBase::Pause();
179 }
180 
FlushStart()181 void DemuxerFilter::FlushStart()
182 {
183     MEDIA_LOG_I("FlushStart entered");
184     task_->Pause();
185     dataPacker_->Flush();
186 }
187 
FlushEnd()188 void DemuxerFilter::FlushEnd()
189 {
190     MEDIA_LOG_I("FlushEnd entered");
191     if (task_) {
192         task_->Start();
193     }
194 }
195 
SetParameter(int32_t key,const Plugin::Any & value)196 ErrorCode DemuxerFilter::SetParameter(int32_t key, const Plugin::Any& value)
197 {
198     FALSE_RETURN_V_MSG(plugin_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION, "plugin is nullptr");
199     return TranslatePluginStatus(plugin_->SetParameter(static_cast<Plugin::Tag>(key), value));
200 }
201 
GetParameter(int32_t key,Plugin::Any & value)202 ErrorCode DemuxerFilter::GetParameter(int32_t key, Plugin::Any& value)
203 {
204     FALSE_RETURN_V_MSG(plugin_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION, "plugin is nullptr");
205     return TranslatePluginStatus(plugin_->SetParameter(static_cast<Plugin::Tag>(key), value));
206 }
207 
Prepare()208 ErrorCode DemuxerFilter::Prepare()
209 {
210     MEDIA_LOG_I("Prepare called");
211     dataPacker_->Start();
212     pluginState_ = DemuxerState::DEMUXER_STATE_NULL;
213     task_->RegisterHandler([this] { DemuxerLoop(); });
214     Pipeline::WorkMode mode;
215     GetInPort(PORT_NAME_DEFAULT)->Activate({Pipeline::WorkMode::PULL, Pipeline::WorkMode::PUSH}, mode);
216     if (mode == Pipeline::WorkMode::PULL) {
217         dataPacker_->Flush();
218         ActivatePullMode();
219     } else {
220         ActivatePushMode();
221     }
222     state_ = FilterState::PREPARING;
223     return ErrorCode::SUCCESS;
224 }
225 
PushData(const std::string & inPort,const AVBufferPtr & buffer,int64_t offset)226 ErrorCode DemuxerFilter::PushData(const std::string& inPort, const AVBufferPtr& buffer, int64_t offset)
227 {
228     MEDIA_LOG_D("PushData for port: " PUBLIC_LOG_S, inPort.c_str());
229     if (buffer->flag & BUFFER_FLAG_EOS) {
230         dataPacker_->SetEos();
231     } else {
232         dataPacker_->PushData(std::move(buffer), offset);
233     }
234     return ErrorCode::SUCCESS;
235 }
236 
Negotiate(const std::string & inPort,const std::shared_ptr<const Plugin::Capability> & upstreamCap,Plugin::Capability & negotiatedCap,const Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)237 bool DemuxerFilter::Negotiate(const std::string& inPort,
238                               const std::shared_ptr<const Plugin::Capability>& upstreamCap,
239                               Plugin::Capability& negotiatedCap,
240                               const Plugin::Meta& upstreamParams,
241                               Plugin::Meta& downstreamParams)
242 {
243     (void)inPort;
244     (void)upstreamCap;
245     (void)negotiatedCap;
246     (void)upstreamParams;
247     (void)downstreamParams;
248     return true;
249 }
250 
Configure(const std::string & inPort,const std::shared_ptr<const Plugin::Meta> & upstreamMeta,Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)251 bool DemuxerFilter::Configure(const std::string& inPort, const std::shared_ptr<const Plugin::Meta>& upstreamMeta,
252                               Plugin::Meta& upstreamParams, Plugin::Meta& downstreamParams)
253 {
254     (void)downstreamParams;
255     FALSE_LOG_MSG(upstreamMeta->Get<Plugin::Tag::MEDIA_FILE_SIZE>(mediaDataSize_), "Get media file size  failed.");
256     FALSE_LOG_MSG(upstreamMeta->Get<Plugin::Tag::MEDIA_SEEKABLE>(seekable_), "Get MEDIA_SEEKABLE failed");
257     FALSE_LOG_MSG(upstreamMeta->Get<Plugin::Tag::MEDIA_FILE_URI>(uri_), "Get MEDIA_FILE_URI failed");
258     return true;
259 }
260 
SeekTo(int64_t seekTime,Plugin::SeekMode mode,int64_t & realSeekTime)261 ErrorCode DemuxerFilter::SeekTo(int64_t seekTime, Plugin::SeekMode mode, int64_t& realSeekTime)
262 {
263     if (!plugin_) {
264         MEDIA_LOG_E("SeekTo failed due to no valid plugin");
265         return ErrorCode::ERROR_INVALID_OPERATION;
266     }
267     auto rtv = TranslatePluginStatus(plugin_->SeekTo(-1, seekTime, mode, realSeekTime));
268     if (rtv != ErrorCode::SUCCESS) {
269         MEDIA_LOG_E("SeekTo failed with return value: " PUBLIC_LOG_D32, static_cast<int>(rtv));
270     }
271     return rtv;
272 }
273 
GetStreamMetaInfo() const274 std::vector<std::shared_ptr<Plugin::Meta>> DemuxerFilter::GetStreamMetaInfo() const
275 {
276     return mediaMetaData_.trackMetas;
277 }
278 
GetGlobalMetaInfo() const279 std::shared_ptr<Plugin::Meta> DemuxerFilter::GetGlobalMetaInfo() const
280 {
281     return mediaMetaData_.globalMeta;
282 }
283 
StopTask(bool force)284 void DemuxerFilter::StopTask(bool force)
285 {
286     if (force || pluginState_.load() != DemuxerState::DEMUXER_STATE_PARSE_FRAME) {
287         if (task_) {
288             task_->Stop();
289         }
290     }
291 }
292 
Reset()293 void DemuxerFilter::Reset()
294 {
295     mediaMetaData_.globalMeta.reset();
296     mediaMetaData_.trackMetas.clear();
297     mediaMetaData_.trackInfos.clear();
298 }
299 
InitTypeFinder()300 void DemuxerFilter::InitTypeFinder()
301 {
302     if (!typeFinder_) {
303         typeFinder_ = std::make_shared<TypeFinder>();
304     }
305 }
306 
CreatePlugin(std::string pluginName)307 bool DemuxerFilter::CreatePlugin(std::string pluginName)
308 {
309     if (plugin_) {
310         plugin_->Deinit();
311     }
312     plugin_ = Plugin::PluginManager::Instance().CreateDemuxerPlugin(pluginName);
313     if (!plugin_ || plugin_->Init() != Plugin::Status::OK) {
314         MEDIA_LOG_E("CreatePlugin " PUBLIC_LOG_S " failed.", pluginName.c_str());
315         return false;
316     }
317     plugin_->SetCallback(this);
318     pluginAllocator_ = plugin_->GetAllocator();
319     pluginName_.swap(pluginName);
320     return true;
321 }
322 
InitPlugin(std::string pluginName)323 bool DemuxerFilter::InitPlugin(std::string pluginName)
324 {
325     if (pluginName.empty()) {
326         return false;
327     }
328     if (pluginName_ != pluginName) {
329         FALSE_RETURN_V(CreatePlugin(std::move(pluginName)), false);
330     } else {
331         if (plugin_->Reset() != Plugin::Status::OK) {
332             FALSE_RETURN_V(CreatePlugin(std::move(pluginName)), false);
333         }
334     }
335     MEDIA_LOG_I("InitPlugin, " PUBLIC_LOG_S " used.", pluginName_.c_str());
336     (void)plugin_->SetDataSource(std::dynamic_pointer_cast<Plugin::DataSourceHelper>(dataSource_));
337     pluginState_ = DemuxerState::DEMUXER_STATE_PARSE_HEADER;
338     return plugin_->Prepare() == Plugin::Status::OK;
339 }
340 
ActivatePullMode()341 void DemuxerFilter::ActivatePullMode()
342 {
343     MEDIA_LOG_D("ActivatePullMode called");
344     InitTypeFinder();
345     checkRange_ = [this](uint64_t offset, uint32_t size) {
346         uint64_t curOffset = offset;
347         if (dataPacker_->IsDataAvailable(offset, size, curOffset)) {
348             return true;
349         }
350         MEDIA_LOG_DD("IsDataAvailable false, require offset " PUBLIC_LOG_D64 ", DataPacker data offset end - curOffset "
351                      PUBLIC_LOG_D64, offset, curOffset);
352         AVBufferPtr bufferPtr = std::make_shared<AVBuffer>();
353         bufferPtr->AllocMemory(pluginAllocator_, size);
354         auto ret = inPorts_.front()->PullData(curOffset, size, bufferPtr);
355         if (ret == ErrorCode::SUCCESS) {
356             dataPacker_->PushData(std::move(bufferPtr), curOffset);
357             return true;
358         } else if (ret == ErrorCode::END_OF_STREAM) {
359             // hasDataToRead is ture if there is some data in data packer can be read.
360             bool hasDataToRead = offset < curOffset && (!dataPacker_->IsEmpty());
361             if (hasDataToRead) {
362                 dataPacker_->SetEos();
363             } else {
364                 dataPacker_->Flush();
365             }
366             return hasDataToRead;
367         } else {
368             MEDIA_LOG_E("PullData from source filter failed " PUBLIC_LOG_D32, ret);
369         }
370         return false;
371     };
372     peekRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
373         if (checkRange_(offset, size)) {
374             return dataPacker_->PeekRange(offset, size, bufferPtr);
375         }
376         return false;
377     };
378     getRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
379         if (checkRange_(offset, size)) {
380             auto ret = dataPacker_->GetRange(offset, size, bufferPtr);
381             return ret;
382         }
383         return false;
384     };
385     typeFinder_->Init(uri_, mediaDataSize_, checkRange_, peekRange_);
386     std::string type = typeFinder_->FindMediaType();
387     MEDIA_LOG_I("FindMediaType result : type : " PUBLIC_LOG_S ", uri_ : " PUBLIC_LOG_S ", mediaDataSize_ : "
388         PUBLIC_LOG_U64, type.c_str(), uri_.c_str(), mediaDataSize_);
389     MediaTypeFound(std::move(type));
390 }
391 
ActivatePushMode()392 void DemuxerFilter::ActivatePushMode()
393 {
394     MEDIA_LOG_D("ActivatePushMode called");
395     InitTypeFinder();
396     checkRange_ = [this](uint64_t offset, uint32_t size) {
397         return !dataPacker_->IsEmpty(); // True if there is some data
398     };
399     peekRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
400         return dataPacker_->PeekRange(offset, size, bufferPtr);
401     };
402     getRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
403         // In push mode, ignore offset, always get data from the start of the data packer.
404         return dataPacker_->GetRange(size, bufferPtr);
405     };
406     typeFinder_->Init(uri_, mediaDataSize_, checkRange_, peekRange_);
407     typeFinder_->FindMediaTypeAsync([this](std::string pluginName) { MediaTypeFound(std::move(pluginName)); });
408 }
409 
MediaTypeFound(std::string pluginName)410 void DemuxerFilter::MediaTypeFound(std::string pluginName)
411 {
412     if (InitPlugin(std::move(pluginName))) {
413         task_->Start();
414     } else {
415         MEDIA_LOG_E("MediaTypeFound init plugin error.");
416         OnEvent({name_, EventType::EVENT_ERROR, ErrorCode::ERROR_UNSUPPORTED_FORMAT});
417     }
418 }
419 
InitMediaMetaData(const Plugin::MediaInfoHelper & mediaInfo)420 void DemuxerFilter::InitMediaMetaData(const Plugin::MediaInfoHelper& mediaInfo)
421 {
422     mediaMetaData_.globalMeta = std::make_shared<Plugin::Meta>(mediaInfo.globalMeta);
423     mediaMetaData_.trackMetas.clear();
424     int trackCnt = 0;
425     for (auto& trackMeta : mediaInfo.trackMeta) {
426         mediaMetaData_.trackMetas.push_back(std::make_shared<Plugin::Meta>(trackMeta));
427         if (!trackMeta.Empty()) {
428             ++trackCnt;
429         }
430     }
431     mediaMetaData_.trackInfos.reserve(trackCnt);
432 }
433 
IsOffsetValid(int64_t offset) const434 bool DemuxerFilter::IsOffsetValid(int64_t offset) const
435 {
436     if (seekable_ == Plugin::Seekable::SEEKABLE) {
437         return mediaDataSize_ == 0 || offset <= static_cast<int64_t>(mediaDataSize_);
438     }
439     return true;
440 }
441 
PrepareStreams(const Plugin::MediaInfoHelper & mediaInfo)442 bool DemuxerFilter::PrepareStreams(const Plugin::MediaInfoHelper& mediaInfo)
443 {
444     MEDIA_LOG_I("PrepareStreams called");
445     InitMediaMetaData(mediaInfo);
446     outPorts_.clear();
447     int streamCnt = mediaInfo.trackMeta.size();
448     PortInfo portInfo;
449     portInfo.type = PortType::OUT;
450     portInfo.ports.reserve(streamCnt);
451     int audioTrackCnt = 0;
452     for (int i = 0; i < streamCnt; ++i) {
453         if (mediaInfo.trackMeta[i].Empty()) {
454             MEDIA_LOG_E("PrepareStreams, unsupported stream with trackId = " PUBLIC_LOG_D32, i);
455             continue;
456         }
457         std::string mime;
458         uint32_t trackId = 0;
459         if (!mediaInfo.trackMeta[i].Get<Plugin::Tag::MIME>(mime) ||
460             !mediaInfo.trackMeta[i].Get<Plugin::Tag::TRACK_ID>(trackId)) {
461             MEDIA_LOG_E("PrepareStreams failed to extract mime or trackId.");
462             continue;
463         }
464         if (IsAudioMime(mime)) {
465             MEDIA_LOG_D("PrepareStreams, audio stream with trackId = " PUBLIC_LOG_U32 ".", trackId);
466             if (audioTrackCnt == 1) {
467                 MEDIA_LOG_E("PrepareStreams, discard audio track: " PUBLIC_LOG_D32 ".", trackId);
468                 continue;
469             }
470             ++audioTrackCnt;
471         }
472         auto port = std::make_shared<OutPort>(this, NamePort(mime));
473         MEDIA_LOG_I("PrepareStreams, trackId: " PUBLIC_LOG_D32 ", portName: " PUBLIC_LOG_S,
474                     i, port->GetName().c_str());
475         outPorts_.push_back(port);
476         portInfo.ports.push_back({port->GetName(), IsRawAudio(mime)});
477         mediaMetaData_.trackInfos.emplace_back(trackId, std::move(port), true);
478     }
479     if (portInfo.ports.empty()) {
480         MEDIA_LOG_E("PrepareStreams failed due to no valid port.");
481         return false;
482     }
483     ErrorCode ret = ErrorCode::SUCCESS;
484     if (callback_) {
485         ret = callback_->OnCallback(FilterCallbackType::PORT_ADDED, static_cast<Filter*>(this), portInfo);
486     }
487     return ret == ErrorCode::SUCCESS;
488 }
489 
ReadFrame(AVBuffer & buffer,uint32_t & trackId)490 ErrorCode DemuxerFilter::ReadFrame(AVBuffer& buffer, uint32_t& trackId)
491 {
492     MEDIA_LOG_DD("ReadFrame called");
493     ErrorCode result = ErrorCode::ERROR_UNKNOWN;
494     auto rtv = plugin_->ReadFrame(buffer, 0);
495     if (rtv == Plugin::Status::OK) {
496         trackId = buffer.trackID;
497         result = ErrorCode::SUCCESS;
498     }
499     MEDIA_LOG_DD("ReadFrame return with rtv = " PUBLIC_LOG_D32, static_cast<int32_t>(rtv));
500     return (rtv != Plugin::Status::END_OF_STREAM) ? result : ErrorCode::END_OF_STREAM;
501 }
502 
GetTrackMeta(uint32_t trackId)503 std::shared_ptr<Plugin::Meta> DemuxerFilter::GetTrackMeta(uint32_t trackId)
504 {
505     uint32_t streamTrackId = 0;
506     auto ret = false;
507     for (auto meta : mediaMetaData_.trackMetas) {
508         FALSE_LOG_MSG(ret = meta->Get<Plugin::Tag::TRACK_ID>(streamTrackId), "Get TRACK_ID failed.");
509         if (ret && streamTrackId == trackId) {
510             return meta;
511         }
512     }
513     return nullptr;
514 }
515 
SendEventEos()516 void DemuxerFilter::SendEventEos()
517 {
518     MEDIA_LOG_I("SendEventEos called");
519     AVBufferPtr bufferPtr = std::make_shared<AVBuffer>();
520     bufferPtr->flag = BUFFER_FLAG_EOS;
521     for (const auto& stream : mediaMetaData_.trackInfos) {
522         stream.port->PushData(bufferPtr, -1);
523     }
524 }
525 
HandleFrame(const AVBufferPtr & bufferPtr,uint32_t trackId)526 void DemuxerFilter::HandleFrame(const AVBufferPtr& bufferPtr, uint32_t trackId)
527 {
528     for (auto& stream : mediaMetaData_.trackInfos) {
529         if (stream.trackId != trackId) {
530             continue;
531         }
532         stream.port->PushData(bufferPtr, -1);
533         break;
534     }
535 }
536 
UpdateStreamMeta(std::shared_ptr<Plugin::Meta> & streamMeta,Plugin::Capability & negotiatedCap,Plugin::Meta & downstreamParams)537 void DemuxerFilter::UpdateStreamMeta(std::shared_ptr<Plugin::Meta>& streamMeta, Plugin::Capability& negotiatedCap,
538     Plugin::Meta& downstreamParams)
539 {
540     auto type = Plugin::MediaType::UNKNOWN;
541     FALSE_LOG(streamMeta->Get<Plugin::Tag::MEDIA_TYPE>(type));
542     if (type == Plugin::MediaType::AUDIO) {
543         uint32_t channels = 2;
544         uint32_t outputChannels = 2;
545         Plugin::AudioChannelLayout channelLayout = Plugin::AudioChannelLayout::STEREO;
546         Plugin::AudioChannelLayout outputChannelLayout = Plugin::AudioChannelLayout::STEREO;
547         FALSE_LOG(streamMeta->Get<Plugin::Tag::AUDIO_CHANNELS>(channels));
548         FALSE_LOG(streamMeta->Get<Plugin::Tag::AUDIO_CHANNEL_LAYOUT>(channelLayout));
549 
550         FALSE_LOG(downstreamParams.Get<Tag::AUDIO_OUTPUT_CHANNELS>(outputChannels));
551         FALSE_LOG(downstreamParams.Get<Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(outputChannelLayout));
552         if (channels <= outputChannels) {
553             outputChannels = channels;
554             outputChannelLayout = channelLayout;
555         }
556         FALSE_LOG(streamMeta->Set<Plugin::Tag::AUDIO_OUTPUT_CHANNELS>(outputChannels));
557         FALSE_LOG(streamMeta->Set<Plugin::Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(outputChannelLayout));
558     } else if (type == Plugin::MediaType::VIDEO) {
559         if (negotiatedCap.keys.count(Capability::Key::VIDEO_BIT_STREAM_FORMAT)) {
560             auto vecVdBitStreamFormat = Plugin::AnyCast<std::vector<Plugin::VideoBitStreamFormat>>(
561                 negotiatedCap.keys[Capability::Key::VIDEO_BIT_STREAM_FORMAT]);
562             if (!vecVdBitStreamFormat.empty()) {
563                 (void)plugin_->SetParameter(Tag::VIDEO_BIT_STREAM_FORMAT, vecVdBitStreamFormat[0]);
564             }
565         }
566     }
567 }
568 
NegotiateDownstream()569 void DemuxerFilter::NegotiateDownstream()
570 {
571     PROFILE_BEGIN("NegotiateDownstream profile begins.");
572     for (auto& stream : mediaMetaData_.trackInfos) {
573         if (stream.needNegoCaps) {
574             Capability caps;
575             MEDIA_LOG_I("demuxer negotiate with trackId: " PUBLIC_LOG_U32, stream.trackId);
576             auto streamMeta = GetTrackMeta(stream.trackId);
577             auto tmpCap = MetaToCapability(*streamMeta);
578             Plugin::Meta upstreamParams;
579             Plugin::Meta downstreamParams;
580             FALSE_LOG(upstreamParams.Set<Tag::MEDIA_SEEKABLE>(seekable_));
581             if (stream.port->Negotiate(tmpCap, caps, upstreamParams, downstreamParams)) {
582                 UpdateStreamMeta(streamMeta, caps, downstreamParams);
583                 if (stream.port->Configure(streamMeta, upstreamParams, downstreamParams)) {
584                     stream.needNegoCaps = false;
585                 }
586             } else {
587                 task_->PauseAsync();
588                 MEDIA_LOG_E("NegotiateDownstream failed error.");
589                 OnEvent({name_, EventType::EVENT_ERROR, ErrorCode::ERROR_UNSUPPORTED_FORMAT});
590             }
591         }
592     }
593     PROFILE_END("NegotiateDownstream end.");
594 }
595 
DemuxerLoop()596 void DemuxerFilter::DemuxerLoop()
597 {
598     if (pluginState_.load() == DemuxerState::DEMUXER_STATE_PARSE_FRAME) {
599         AVBufferPtr bufferPtr = std::make_shared<AVBuffer>();
600         uint32_t streamIndex = 0;
601         auto rtv = ReadFrame(*bufferPtr, streamIndex);
602         if (rtv == ErrorCode::SUCCESS) {
603             DUMP_BUFFER2LOG("Demuxer Output", bufferPtr, 0);
604             DUMP_BUFFER2FILE(DEMUXER_OUTPUT, bufferPtr);
605             HandleFrame(bufferPtr, streamIndex);
606         } else {
607             SendEventEos();
608             task_->PauseAsync();
609             if (rtv != ErrorCode::END_OF_STREAM) {
610                 MEDIA_LOG_E("ReadFrame failed with rtv = " PUBLIC_LOG_D32, CppExt::to_underlying(rtv));
611             }
612         }
613     } else {
614         Plugin::MediaInfoHelper mediaInfo;
615         PROFILE_BEGIN();
616         if (plugin_->GetMediaInfo(mediaInfo) == Plugin::Status::OK && PrepareStreams(mediaInfo)) {
617             PROFILE_END("Succeed to extract mediainfo.");
618             NegotiateDownstream();
619             ReportVideoSize(mediaInfo);
620             pluginState_ = DemuxerState::DEMUXER_STATE_PARSE_FRAME;
621             state_ = FilterState::READY;
622             OnEvent({name_, EventType::EVENT_READY, {}});
623         } else {
624             task_->PauseAsync();
625             MEDIA_LOG_E("demuxer filter parse meta failed");
626             OnEvent({name_, EventType::EVENT_ERROR, ErrorCode::ERROR_UNKNOWN});
627         }
628     }
629 }
630 
ReportVideoSize(const Plugin::MediaInfoHelper & mediaInfo)631 void DemuxerFilter::ReportVideoSize(const Plugin::MediaInfoHelper& mediaInfo)
632 {
633     std::string mime;
634     uint32_t width = 0;
635     uint32_t height = 0;
636     int streamCnt = mediaInfo.trackMeta.size();
637     for (int i = 0; i < streamCnt; ++i) {
638         if (!mediaInfo.trackMeta[i].Get<Plugin::Tag::MIME>(mime)) {
639             MEDIA_LOG_E("PrepareStreams failed to extract mime.");
640             continue;
641         }
642         if (IsVideoMime(mime)) {
643             FALSE_LOG(mediaInfo.trackMeta[i].Get<Plugin::Tag::VIDEO_WIDTH>(width));
644             FALSE_LOG(mediaInfo.trackMeta[i].Get<Plugin::Tag::VIDEO_HEIGHT>(height));
645             MEDIA_LOG_I("mime-width-height: " PUBLIC_LOG_S "-" PUBLIC_LOG_U32 "-" PUBLIC_LOG_U32,
646                         mime.c_str(), width, height);
647             auto resolution = std::make_pair(static_cast<int32_t>(width), static_cast<int32_t>(height));
648             FilterBase::OnEvent({name_, EventType::EVENT_RESOLUTION_CHANGE, resolution});
649             break;
650         }
651     }
652 }
653 } // namespace Pipeline
654 } // namespace Media
655 } // namespace OHOS
656