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