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 MEDIA_LOG_I("demuexfilter Prepare success");
224 return ErrorCode::SUCCESS;
225 }
226
PushData(const std::string & inPort,const AVBufferPtr & buffer,int64_t offset)227 ErrorCode DemuxerFilter::PushData(const std::string& inPort, const AVBufferPtr& buffer, int64_t offset)
228 {
229 MEDIA_LOG_D("PushData for port: " PUBLIC_LOG_S, inPort.c_str());
230 if (buffer->flag & BUFFER_FLAG_EOS) {
231 dataPacker_->SetEos();
232 } else {
233 dataPacker_->PushData(std::move(buffer), offset);
234 }
235 return ErrorCode::SUCCESS;
236 }
237
Negotiate(const std::string & inPort,const std::shared_ptr<const Plugin::Capability> & upstreamCap,Plugin::Capability & negotiatedCap,const Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)238 bool DemuxerFilter::Negotiate(const std::string& inPort,
239 const std::shared_ptr<const Plugin::Capability>& upstreamCap,
240 Plugin::Capability& negotiatedCap,
241 const Plugin::Meta& upstreamParams,
242 Plugin::Meta& downstreamParams)
243 {
244 (void)inPort;
245 (void)upstreamCap;
246 (void)negotiatedCap;
247 (void)upstreamParams;
248 (void)downstreamParams;
249 return true;
250 }
251
Configure(const std::string & inPort,const std::shared_ptr<const Plugin::Meta> & upstreamMeta,Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)252 bool DemuxerFilter::Configure(const std::string& inPort, const std::shared_ptr<const Plugin::Meta>& upstreamMeta,
253 Plugin::Meta& upstreamParams, Plugin::Meta& downstreamParams)
254 {
255 (void)downstreamParams;
256 FALSE_LOG_MSG(upstreamMeta->Get<Plugin::Tag::MEDIA_FILE_SIZE>(mediaDataSize_), "Get media file size failed.");
257 FALSE_LOG_MSG(upstreamMeta->Get<Plugin::Tag::MEDIA_SEEKABLE>(seekable_), "Get MEDIA_SEEKABLE failed");
258 FALSE_LOG_MSG(upstreamMeta->Get<Plugin::Tag::MEDIA_FILE_URI>(uri_), "Get MEDIA_FILE_URI failed");
259 return true;
260 }
261
SeekTo(int64_t seekTime,Plugin::SeekMode mode,int64_t & realSeekTime)262 ErrorCode DemuxerFilter::SeekTo(int64_t seekTime, Plugin::SeekMode mode, int64_t& realSeekTime)
263 {
264 if (!plugin_) {
265 MEDIA_LOG_E("SeekTo failed due to no valid plugin");
266 return ErrorCode::ERROR_INVALID_OPERATION;
267 }
268 auto rtv = TranslatePluginStatus(plugin_->SeekTo(-1, seekTime, mode, realSeekTime));
269 if (rtv != ErrorCode::SUCCESS) {
270 MEDIA_LOG_E("SeekTo failed with return value: " PUBLIC_LOG_D32, static_cast<int>(rtv));
271 }
272 return rtv;
273 }
274
GetStreamMetaInfo() const275 std::vector<std::shared_ptr<Plugin::Meta>> DemuxerFilter::GetStreamMetaInfo() const
276 {
277 return mediaMetaData_.trackMetas;
278 }
279
GetGlobalMetaInfo() const280 std::shared_ptr<Plugin::Meta> DemuxerFilter::GetGlobalMetaInfo() const
281 {
282 return mediaMetaData_.globalMeta;
283 }
284
StopTask(bool force)285 void DemuxerFilter::StopTask(bool force)
286 {
287 if (force || pluginState_.load() != DemuxerState::DEMUXER_STATE_PARSE_FRAME) {
288 if (task_) {
289 task_->Stop();
290 }
291 }
292 }
293
Reset()294 void DemuxerFilter::Reset()
295 {
296 mediaMetaData_.globalMeta.reset();
297 mediaMetaData_.trackMetas.clear();
298 mediaMetaData_.trackInfos.clear();
299 }
300
InitTypeFinder()301 void DemuxerFilter::InitTypeFinder()
302 {
303 if (!typeFinder_) {
304 typeFinder_ = std::make_shared<TypeFinder>();
305 }
306 }
307
CreatePlugin(std::string pluginName)308 bool DemuxerFilter::CreatePlugin(std::string pluginName)
309 {
310 if (plugin_) {
311 plugin_->Deinit();
312 }
313 plugin_ = Plugin::PluginManager::Instance().CreateDemuxerPlugin(pluginName);
314 if (!plugin_ || plugin_->Init() != Plugin::Status::OK) {
315 MEDIA_LOG_E("CreatePlugin " PUBLIC_LOG_S " failed.", pluginName.c_str());
316 return false;
317 }
318 plugin_->SetCallback(this);
319 pluginAllocator_ = plugin_->GetAllocator();
320 pluginName_.swap(pluginName);
321 return true;
322 }
323
InitPlugin(std::string pluginName)324 bool DemuxerFilter::InitPlugin(std::string pluginName)
325 {
326 if (pluginName.empty()) {
327 return false;
328 }
329 if (pluginName_ != pluginName) {
330 FALSE_RETURN_V(CreatePlugin(std::move(pluginName)), false);
331 } else {
332 if (plugin_->Reset() != Plugin::Status::OK) {
333 FALSE_RETURN_V(CreatePlugin(std::move(pluginName)), false);
334 }
335 }
336 MEDIA_LOG_I("InitPlugin, " PUBLIC_LOG_S " used.", pluginName_.c_str());
337 (void)plugin_->SetDataSource(std::reinterpret_pointer_cast<Plugin::DataSourceHelper>(dataSource_));
338 pluginState_ = DemuxerState::DEMUXER_STATE_PARSE_HEADER;
339 return plugin_->Prepare() == Plugin::Status::OK;
340 }
341
ActivatePullMode()342 void DemuxerFilter::ActivatePullMode()
343 {
344 MEDIA_LOG_D("ActivatePullMode called");
345 InitTypeFinder();
346 checkRange_ = [this](uint64_t offset, uint32_t size) {
347 uint64_t curOffset = offset;
348 if (dataPacker_->IsDataAvailable(offset, size, curOffset)) {
349 return true;
350 }
351 MEDIA_LOG_DD("IsDataAvailable false, require offset " PUBLIC_LOG_D64 ", DataPacker data offset end - curOffset "
352 PUBLIC_LOG_D64, offset, curOffset);
353 AVBufferPtr bufferPtr = std::make_shared<AVBuffer>();
354 bufferPtr->AllocMemory(pluginAllocator_, size);
355 auto ret = inPorts_.front()->PullData(curOffset, size, bufferPtr);
356 if (ret == ErrorCode::SUCCESS) {
357 dataPacker_->PushData(std::move(bufferPtr), curOffset);
358 return true;
359 } else if (ret == ErrorCode::END_OF_STREAM) {
360 // hasDataToRead is ture if there is some data in data packer can be read.
361 bool hasDataToRead = offset < curOffset && (!dataPacker_->IsEmpty());
362 if (hasDataToRead) {
363 dataPacker_->SetEos();
364 } else {
365 dataPacker_->Flush();
366 }
367 return hasDataToRead;
368 } else {
369 MEDIA_LOG_E("PullData from source filter failed " PUBLIC_LOG_D32, ret);
370 }
371 return false;
372 };
373 peekRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
374 if (checkRange_(offset, size)) {
375 return dataPacker_->PeekRange(offset, size, bufferPtr);
376 }
377 return false;
378 };
379 getRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
380 if (checkRange_(offset, size)) {
381 auto ret = dataPacker_->GetRange(offset, size, bufferPtr);
382 return ret;
383 }
384 return false;
385 };
386 typeFinder_->Init(uri_, mediaDataSize_, checkRange_, peekRange_);
387 std::string type = typeFinder_->FindMediaType();
388 MEDIA_LOG_I("FindMediaType result : type : " PUBLIC_LOG_S ", uri_ : " PUBLIC_LOG_S ", mediaDataSize_ : "
389 PUBLIC_LOG_U64, type.c_str(), uri_.c_str(), mediaDataSize_);
390 MediaTypeFound(std::move(type));
391 }
392
ActivatePushMode()393 void DemuxerFilter::ActivatePushMode()
394 {
395 MEDIA_LOG_D("ActivatePushMode called");
396 InitTypeFinder();
397 checkRange_ = [this](uint64_t offset, uint32_t size) {
398 return !dataPacker_->IsEmpty(); // True if there is some data
399 };
400 peekRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
401 return dataPacker_->PeekRange(offset, size, bufferPtr);
402 };
403 getRange_ = [this](uint64_t offset, size_t size, AVBufferPtr& bufferPtr) -> bool {
404 // In push mode, ignore offset, always get data from the start of the data packer.
405 return dataPacker_->GetRange(size, bufferPtr);
406 };
407 typeFinder_->Init(uri_, mediaDataSize_, checkRange_, peekRange_);
408 typeFinder_->FindMediaTypeAsync([this](std::string pluginName) { MediaTypeFound(std::move(pluginName)); });
409 }
410
MediaTypeFound(std::string pluginName)411 void DemuxerFilter::MediaTypeFound(std::string pluginName)
412 {
413 if (InitPlugin(std::move(pluginName))) {
414 task_->Start();
415 } else {
416 MEDIA_LOG_E("MediaTypeFound init plugin error.");
417 OnEvent({name_, EventType::EVENT_ERROR, ErrorCode::ERROR_UNSUPPORTED_FORMAT});
418 }
419 }
420
InitMediaMetaData(const Plugin::MediaInfoHelper & mediaInfo)421 void DemuxerFilter::InitMediaMetaData(const Plugin::MediaInfoHelper& mediaInfo)
422 {
423 mediaMetaData_.globalMeta = std::make_shared<Plugin::Meta>(mediaInfo.globalMeta);
424 mediaMetaData_.trackMetas.clear();
425 int trackCnt = 0;
426 for (auto& trackMeta : mediaInfo.trackMeta) {
427 mediaMetaData_.trackMetas.push_back(std::make_shared<Plugin::Meta>(trackMeta));
428 if (!trackMeta.Empty()) {
429 ++trackCnt;
430 }
431 }
432 mediaMetaData_.trackInfos.reserve(trackCnt);
433 }
434
IsOffsetValid(int64_t offset) const435 bool DemuxerFilter::IsOffsetValid(int64_t offset) const
436 {
437 if (seekable_ == Plugin::Seekable::SEEKABLE) {
438 return mediaDataSize_ == 0 || offset <= static_cast<int64_t>(mediaDataSize_);
439 }
440 return true;
441 }
442
PrepareStreams(const Plugin::MediaInfoHelper & mediaInfo)443 bool DemuxerFilter::PrepareStreams(const Plugin::MediaInfoHelper& mediaInfo)
444 {
445 MEDIA_LOG_I("PrepareStreams called");
446 InitMediaMetaData(mediaInfo);
447 outPorts_.clear();
448 int streamCnt = mediaInfo.trackMeta.size();
449 PortInfo portInfo;
450 portInfo.type = PortType::OUT;
451 portInfo.ports.reserve(streamCnt);
452 int audioTrackCnt = 0;
453 for (int i = 0; i < streamCnt; ++i) {
454 if (mediaInfo.trackMeta[i].Empty()) {
455 MEDIA_LOG_E("PrepareStreams, unsupported stream with trackId = " PUBLIC_LOG_D32, i);
456 continue;
457 }
458 std::string mime;
459 uint32_t trackId = 0;
460 if (!mediaInfo.trackMeta[i].Get<Plugin::Tag::MIME>(mime) ||
461 !mediaInfo.trackMeta[i].Get<Plugin::Tag::TRACK_ID>(trackId)) {
462 MEDIA_LOG_E("PrepareStreams failed to extract mime or trackId.");
463 continue;
464 }
465 if (IsAudioMime(mime)) {
466 MEDIA_LOG_D("PrepareStreams, audio stream with trackId = " PUBLIC_LOG_U32 ".", trackId);
467 if (audioTrackCnt == 1) {
468 MEDIA_LOG_E("PrepareStreams, discard audio track: " PUBLIC_LOG_D32 ".", trackId);
469 continue;
470 }
471 ++audioTrackCnt;
472 }
473 auto port = std::make_shared<OutPort>(this, NamePort(mime));
474 MEDIA_LOG_I("PrepareStreams, trackId: " PUBLIC_LOG_D32 ", portName: " PUBLIC_LOG_S,
475 i, port->GetName().c_str());
476 outPorts_.push_back(port);
477 portInfo.ports.push_back({port->GetName(), IsRawAudio(mime)});
478 mediaMetaData_.trackInfos.emplace_back(trackId, std::move(port), true);
479 }
480 if (portInfo.ports.empty()) {
481 MEDIA_LOG_E("PrepareStreams failed due to no valid port.");
482 return false;
483 }
484 ErrorCode ret = ErrorCode::SUCCESS;
485 if (callback_) {
486 ret = callback_->OnCallback(FilterCallbackType::PORT_ADDED, static_cast<Filter*>(this), portInfo);
487 }
488 return ret == ErrorCode::SUCCESS;
489 }
490
ReadFrame(AVBuffer & buffer,uint32_t & trackId)491 ErrorCode DemuxerFilter::ReadFrame(AVBuffer& buffer, uint32_t& trackId)
492 {
493 MEDIA_LOG_DD("ReadFrame called");
494 ErrorCode result = ErrorCode::ERROR_UNKNOWN;
495 auto rtv = plugin_->ReadFrame(buffer, 0);
496 if (rtv == Plugin::Status::OK) {
497 trackId = buffer.trackID;
498 result = ErrorCode::SUCCESS;
499 }
500 MEDIA_LOG_DD("ReadFrame return with rtv = " PUBLIC_LOG_D32, static_cast<int32_t>(rtv));
501 return (rtv != Plugin::Status::END_OF_STREAM) ? result : ErrorCode::END_OF_STREAM;
502 }
503
GetTrackMeta(uint32_t trackId)504 std::shared_ptr<Plugin::Meta> DemuxerFilter::GetTrackMeta(uint32_t trackId)
505 {
506 uint32_t streamTrackId = 0;
507 for (auto meta : mediaMetaData_.trackMetas) {
508 auto ret = false;
509 FALSE_LOG_MSG(ret = meta->Get<Plugin::Tag::TRACK_ID>(streamTrackId), "Get TRACK_ID failed.");
510 if (ret && streamTrackId == trackId) {
511 return meta;
512 }
513 }
514 return nullptr;
515 }
516
SendEventEos()517 void DemuxerFilter::SendEventEos()
518 {
519 MEDIA_LOG_I("SendEventEos called");
520 AVBufferPtr bufferPtr = std::make_shared<AVBuffer>();
521 bufferPtr->flag = BUFFER_FLAG_EOS;
522 for (const auto& stream : mediaMetaData_.trackInfos) {
523 stream.port->PushData(bufferPtr, -1);
524 }
525 }
526
HandleFrame(const AVBufferPtr & bufferPtr,uint32_t trackId)527 void DemuxerFilter::HandleFrame(const AVBufferPtr& bufferPtr, uint32_t trackId)
528 {
529 for (auto& stream : mediaMetaData_.trackInfos) {
530 if (stream.trackId != trackId) {
531 continue;
532 }
533 stream.port->PushData(bufferPtr, -1);
534 break;
535 }
536 }
537
UpdateStreamMeta(std::shared_ptr<Plugin::Meta> & streamMeta,Plugin::Capability & negotiatedCap,Plugin::Meta & downstreamParams)538 void DemuxerFilter::UpdateStreamMeta(std::shared_ptr<Plugin::Meta>& streamMeta, Plugin::Capability& negotiatedCap,
539 Plugin::Meta& downstreamParams)
540 {
541 auto type = Plugin::MediaType::UNKNOWN;
542 FALSE_LOG(streamMeta->Get<Plugin::Tag::MEDIA_TYPE>(type));
543 if (type == Plugin::MediaType::AUDIO) {
544 uint32_t channels = 2;
545 uint32_t outputChannels = 2;
546 Plugin::AudioChannelLayout channelLayout = Plugin::AudioChannelLayout::STEREO;
547 Plugin::AudioChannelLayout outputChannelLayout = Plugin::AudioChannelLayout::STEREO;
548 FALSE_LOG(streamMeta->Get<Plugin::Tag::AUDIO_CHANNELS>(channels));
549 FALSE_LOG(streamMeta->Get<Plugin::Tag::AUDIO_CHANNEL_LAYOUT>(channelLayout));
550
551 FALSE_LOG(downstreamParams.Get<Tag::AUDIO_OUTPUT_CHANNELS>(outputChannels));
552 FALSE_LOG(downstreamParams.Get<Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(outputChannelLayout));
553 if (channels <= outputChannels) {
554 outputChannels = channels;
555 outputChannelLayout = channelLayout;
556 }
557 FALSE_LOG(streamMeta->Set<Plugin::Tag::AUDIO_OUTPUT_CHANNELS>(outputChannels));
558 FALSE_LOG(streamMeta->Set<Plugin::Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(outputChannelLayout));
559 } else if (type == Plugin::MediaType::VIDEO) {
560 if (negotiatedCap.keys.count(Capability::Key::VIDEO_BIT_STREAM_FORMAT)) {
561 auto vecVdBitStreamFormat = Plugin::AnyCast<std::vector<Plugin::VideoBitStreamFormat>>(
562 negotiatedCap.keys[Capability::Key::VIDEO_BIT_STREAM_FORMAT]);
563 if (!vecVdBitStreamFormat.empty()) {
564 (void)plugin_->SetParameter(Tag::VIDEO_BIT_STREAM_FORMAT, vecVdBitStreamFormat[0]);
565 }
566 }
567 }
568 }
569
NegotiateDownstream()570 void DemuxerFilter::NegotiateDownstream()
571 {
572 PROFILE_BEGIN("NegotiateDownstream profile begins.");
573 for (auto& stream : mediaMetaData_.trackInfos) {
574 if (stream.needNegoCaps) {
575 Capability caps;
576 MEDIA_LOG_I("demuxer negotiate with trackId: " PUBLIC_LOG_U32, stream.trackId);
577 auto streamMeta = GetTrackMeta(stream.trackId);
578 auto tmpCap = MetaToCapability(*streamMeta);
579 Plugin::Meta upstreamParams;
580 Plugin::Meta downstreamParams;
581 FALSE_LOG(upstreamParams.Set<Tag::MEDIA_SEEKABLE>(seekable_));
582 if (stream.port->Negotiate(tmpCap, caps, upstreamParams, downstreamParams)) {
583 UpdateStreamMeta(streamMeta, caps, downstreamParams);
584 if (stream.port->Configure(streamMeta, upstreamParams, downstreamParams)) {
585 stream.needNegoCaps = false;
586 }
587 } else {
588 task_->PauseAsync();
589 MEDIA_LOG_E("NegotiateDownstream failed error.");
590 OnEvent({name_, EventType::EVENT_ERROR, ErrorCode::ERROR_UNSUPPORTED_FORMAT});
591 }
592 }
593 }
594 PROFILE_END("NegotiateDownstream end.");
595 }
596
DemuxerLoop()597 void DemuxerFilter::DemuxerLoop()
598 {
599 if (pluginState_.load() == DemuxerState::DEMUXER_STATE_PARSE_FRAME) {
600 AVBufferPtr bufferPtr = std::make_shared<AVBuffer>();
601 uint32_t streamIndex = 0;
602 auto rtv = ReadFrame(*bufferPtr, streamIndex);
603 if (rtv == ErrorCode::SUCCESS) {
604 DUMP_BUFFER2LOG("Demuxer Output", bufferPtr, 0);
605 DUMP_BUFFER2FILE(DEMUXER_OUTPUT, bufferPtr);
606 HandleFrame(bufferPtr, streamIndex);
607 } else {
608 SendEventEos();
609 task_->PauseAsync();
610 if (rtv != ErrorCode::END_OF_STREAM) {
611 MEDIA_LOG_E("ReadFrame failed with rtv = " PUBLIC_LOG_D32, CppExt::to_underlying(rtv));
612 }
613 }
614 } else {
615 Plugin::MediaInfoHelper mediaInfo;
616 PROFILE_BEGIN();
617 if (plugin_->GetMediaInfo(mediaInfo) == Plugin::Status::OK && PrepareStreams(mediaInfo)) {
618 PROFILE_END("Succeed to extract mediainfo.");
619 NegotiateDownstream();
620 ReportVideoSize(mediaInfo);
621 pluginState_ = DemuxerState::DEMUXER_STATE_PARSE_FRAME;
622 state_ = FilterState::READY;
623 OnEvent({name_, EventType::EVENT_READY, {}});
624 } else {
625 task_->PauseAsync();
626 MEDIA_LOG_E("demuxer filter parse meta failed");
627 OnEvent({name_, EventType::EVENT_ERROR, ErrorCode::ERROR_UNKNOWN});
628 }
629 }
630 }
631
ReportVideoSize(const Plugin::MediaInfoHelper & mediaInfo)632 void DemuxerFilter::ReportVideoSize(const Plugin::MediaInfoHelper& mediaInfo)
633 {
634 std::string mime;
635 uint32_t width = 0;
636 uint32_t height = 0;
637 int streamCnt = mediaInfo.trackMeta.size();
638 for (int i = 0; i < streamCnt; ++i) {
639 if (!mediaInfo.trackMeta[i].Get<Plugin::Tag::MIME>(mime)) {
640 MEDIA_LOG_E("PrepareStreams failed to extract mime.");
641 continue;
642 }
643 if (IsVideoMime(mime)) {
644 FALSE_LOG(mediaInfo.trackMeta[i].Get<Plugin::Tag::VIDEO_WIDTH>(width));
645 FALSE_LOG(mediaInfo.trackMeta[i].Get<Plugin::Tag::VIDEO_HEIGHT>(height));
646 MEDIA_LOG_I("mime-width-height: " PUBLIC_LOG_S "-" PUBLIC_LOG_U32 "-" PUBLIC_LOG_U32,
647 mime.c_str(), width, height);
648 auto resolution = std::make_pair(static_cast<int32_t>(width), static_cast<int32_t>(height));
649 FilterBase::OnEvent({name_, EventType::EVENT_RESOLUTION_CHANGE, resolution});
650 break;
651 }
652 }
653 }
654 } // namespace Pipeline
655 } // namespace Media
656 } // namespace OHOS
657