1 /*
2 * Copyright (c) 2023-2023 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 "MediaDemuxer"
17 #define MEDIA_ATOMIC_ABILITY
18
19 #include "media_demuxer.h"
20
21 #include <algorithm>
22 #include <map>
23 #include <memory>
24
25 #include "avcodec_common.h"
26 #include "avcodec_trace.h"
27 #include "cpp_ext/type_traits_ext.h"
28 #include "buffer/avallocator.h"
29 #include "common/event.h"
30 #include "common/log.h"
31 #include "hisysevent.h"
32 #include "meta/media_types.h"
33 #include "meta/meta.h"
34 #include "osal/utils/dump_buffer.h"
35 #include "plugin/plugin_buffer.h"
36 #include "plugin/plugin_info.h"
37 #include "plugin/plugin_time.h"
38 #include "source/source.h"
39 #include "stream_demuxer.h"
40 #include "media_core.h"
41 #include "osal/utils/dump_buffer.h"
42 #include "demuxer_plugin_manager.h"
43 #include "media_demuxer_pts_founctions.cpp"
44
45 namespace {
46 const std::string DUMP_PARAM = "a";
47 const std::string DUMP_DEMUXER_AUDIO_FILE_NAME = "player_demuxer_audio_output.es";
48 const std::string DUMP_DEMUXER_VIDEO_FILE_NAME = "player_demuxer_video_output.es";
49 static constexpr char PERFORMANCE_STATS[] = "PERFORMANCE";
50 } // namespace
51
52 namespace OHOS {
53 namespace Media {
54 namespace {
55 constexpr uint32_t REQUEST_BUFFER_TIMEOUT = 0; // Requesting buffer overtimes 0ms means no retry
56 constexpr int32_t START = 1;
57 constexpr int32_t PAUSE = 2;
58 constexpr uint32_t RETRY_DELAY_TIME_US = 100000; // 100ms, Delay time for RETRY if no buffer in avbufferqueue producer.
59 constexpr double DECODE_RATE_THRESHOLD = 0.05; // allow actual rate exceeding 5%
60 constexpr uint32_t REQUEST_FAILED_RETRY_TIMES = 12000; // Max times for RETRY if no buffer in avbufferqueue producer.
61 }
62
63 enum SceneCode : int32_t {
64 /**
65 * This option is used to mark parser ref for dragging play scene.
66 */
67 AV_META_SCENE_PARSE_REF_FOR_DRAGGING_PLAY = 3 // scene code of parser ref for dragging play is 3
68 };
69
70 class MediaDemuxer::AVBufferQueueProducerListener : public IRemoteStub<IProducerListener> {
71 public:
AVBufferQueueProducerListener(uint32_t trackId,std::shared_ptr<MediaDemuxer> demuxer,std::unique_ptr<Task> & notifyTask)72 explicit AVBufferQueueProducerListener(uint32_t trackId, std::shared_ptr<MediaDemuxer> demuxer,
73 std::unique_ptr<Task>& notifyTask) : trackId_(trackId), demuxer_(demuxer), notifyTask_(std::move(notifyTask)) {}
74
75 virtual ~AVBufferQueueProducerListener() = default;
OnRemoteRequest(uint32_t code,MessageParcel & arguments,MessageParcel & reply,MessageOption & option)76 int OnRemoteRequest(uint32_t code, MessageParcel& arguments, MessageParcel& reply, MessageOption& option) override
77 {
78 return IPCObjectStub::OnRemoteRequest(code, arguments, reply, option);
79 }
OnBufferAvailable()80 void OnBufferAvailable() override
81 {
82 MEDIA_LOG_D("Buffer available for track " PUBLIC_LOG_U32, trackId_);
83 if (notifyTask_ == nullptr) {
84 return;
85 }
86 notifyTask_->SubmitJobOnce([this] {
87 auto demuxer = demuxer_.lock();
88 if (demuxer) {
89 demuxer->OnBufferAvailable(trackId_);
90 }
91 });
92 }
93 private:
94 uint32_t trackId_{0};
95 std::weak_ptr<MediaDemuxer> demuxer_;
96 std::unique_ptr<Task> notifyTask_;
97 };
98
99 class MediaDemuxer::TrackWrapper {
100 public:
TrackWrapper(uint32_t trackId,sptr<IProducerListener> listener,std::shared_ptr<MediaDemuxer> demuxer)101 explicit TrackWrapper(uint32_t trackId, sptr<IProducerListener> listener, std::shared_ptr<MediaDemuxer> demuxer)
102 : trackId_(trackId), listener_(listener), demuxer_(demuxer) {}
GetProducerListener()103 sptr<IProducerListener> GetProducerListener()
104 {
105 return listener_;
106 }
SetNotifyFlag(bool isNotifyNeeded)107 void SetNotifyFlag(bool isNotifyNeeded)
108 {
109 isNotifyNeeded_ = isNotifyNeeded;
110 MEDIA_LOG_D("TrackId:" PUBLIC_LOG_U32 ", isNotifyNeeded:" PUBLIC_LOG_D32,
111 trackId_, isNotifyNeeded);
112 }
GetNotifyFlag()113 bool GetNotifyFlag()
114 {
115 return isNotifyNeeded_.load();
116 }
117 private:
118 std::atomic<bool> isNotifyNeeded_{false};
119 uint32_t trackId_{0};
120 sptr<IProducerListener> listener_ = nullptr;
121 std::weak_ptr<MediaDemuxer> demuxer_;
122 };
123
MediaDemuxer()124 MediaDemuxer::MediaDemuxer()
125 : seekable_(Plugins::Seekable::INVALID),
126 subSeekable_(Plugins::Seekable::INVALID),
127 uri_(),
128 mediaDataSize_(0),
129 subMediaDataSize_(0),
130 source_(std::make_shared<Source>()),
131 subtitleSource_(std::make_shared<Source>()),
132 mediaMetaData_(),
133 bufferQueueMap_(),
134 bufferMap_(),
135 eventReceiver_(),
136 streamDemuxer_(),
137 demuxerPluginManager_(std::make_shared<DemuxerPluginManager>())
138 {
139 MEDIA_LOG_D("In");
140 }
141
~MediaDemuxer()142 MediaDemuxer::~MediaDemuxer()
143 {
144 MEDIA_LOG_D("In");
145 ResetInner();
146 demuxerPluginManager_ = nullptr;
147 mediaSource_ = nullptr;
148 source_ = nullptr;
149 eventReceiver_ = nullptr;
150 eosMap_.clear();
151 requestBufferErrorCountMap_.clear();
152 streamDemuxer_ = nullptr;
153 localDrmInfos_.clear();
154
155 if (parserRefInfoTask_ != nullptr) {
156 parserRefInfoTask_->Stop();
157 parserRefInfoTask_ = nullptr;
158 }
159 }
160
GetCurFFmpegPlugin()161 std::shared_ptr<Plugins::DemuxerPlugin> MediaDemuxer::GetCurFFmpegPlugin()
162 {
163 int32_t tempTrackId = (videoTrackId_ != TRACK_ID_DUMMY ? static_cast<int32_t>(videoTrackId_) : -1);
164 tempTrackId = (tempTrackId == -1 ? static_cast<int32_t>(audioTrackId_) : tempTrackId);
165 int32_t streamID = demuxerPluginManager_->GetTmpStreamIDByTrackID(tempTrackId);
166 return demuxerPluginManager_->GetPluginByStreamID(streamID);
167 }
168
ReportSceneCodeForDemuxer(SceneCode scene)169 static void ReportSceneCodeForDemuxer(SceneCode scene)
170 {
171 if (scene != SceneCode::AV_META_SCENE_PARSE_REF_FOR_DRAGGING_PLAY) {
172 return;
173 }
174 MEDIA_LOG_I("Scene %{public}d", scene);
175 auto now =
176 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
177 int32_t ret = HiSysEventWrite(
178 PERFORMANCE_STATS, "CPU_SCENE_ENTRY", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PACKAGE_NAME",
179 "media_service", "SCENE_ID", std::to_string(scene).c_str(), "HAPPEN_TIME", now.count());
180 if (ret != MSERR_OK) {
181 MEDIA_LOG_W("Report failed");
182 }
183 }
184
StartReferenceParser(int64_t startTimeMs,bool isForward)185 Status MediaDemuxer::StartReferenceParser(int64_t startTimeMs, bool isForward)
186 {
187 FALSE_RETURN_V_MSG_E(startTimeMs >= 0, Status::ERROR_UNKNOWN,
188 "Start failed, startTimeMs: " PUBLIC_LOG_D64, startTimeMs);
189 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
190 FALSE_RETURN_V_MSG_E(videoTrackId_ != TRACK_ID_DUMMY, Status::ERROR_UNKNOWN, "Video track is nullptr");
191 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
192 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
193 FALSE_RETURN_V_MSG_E(videoPlugin != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
194 Status ret = videoPlugin->ParserRefUpdatePos(startTimeMs, isForward);
195 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "ParserRefUpdatePos failed");
196 if (isFirstParser_) {
197 isFirstParser_ = false;
198 if (source_->GetSeekable() != Plugins::Seekable::SEEKABLE) {
199 MEDIA_LOG_E("Unsupport online video");
200 return Status::ERROR_INVALID_OPERATION;
201 }
202 parserRefInfoTask_ = std::make_unique<Task>("ParserRefInfo", playerId_);
203 parserRefInfoTask_->RegisterJob([this] { return ParserRefInfo(); });
204 ReportSceneCodeForDemuxer(SceneCode::AV_META_SCENE_PARSE_REF_FOR_DRAGGING_PLAY);
205 parserRefInfoTask_->Start();
206 }
207 TryRecvParserTask();
208 return ret;
209 }
210
TryRecvParserTask()211 void MediaDemuxer::TryRecvParserTask()
212 {
213 if (isParserTaskEnd_ && parserRefInfoTask_ != nullptr) {
214 parserRefInfoTask_->Stop();
215 parserRefInfoTask_ = nullptr;
216 MEDIA_LOG_I("Success to recovery");
217 }
218 }
219
ParserRefInfo()220 int64_t MediaDemuxer::ParserRefInfo()
221 {
222 if (demuxerPluginManager_ == nullptr) {
223 MEDIA_LOG_D("Plugin manager is nullptr");
224 return 0;
225 }
226 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
227 if (videoPlugin == nullptr) {
228 MEDIA_LOG_D("Demuxer plugin is nullptr");
229 return 0;
230 }
231 Status ret = videoPlugin->ParserRefInfo();
232 if ((ret == Status::OK || ret == Status::ERROR_UNKNOWN) && parserRefInfoTask_ != nullptr) {
233 parserRefInfoTask_->Stop();
234 isParserTaskEnd_ = true;
235 MEDIA_LOG_I("Success to stop");
236 } else {
237 MEDIA_LOG_I("ret is " PUBLIC_LOG_D32, ret);
238 }
239 return 0;
240 }
241
GetFrameLayerInfo(std::shared_ptr<AVBuffer> videoSample,FrameLayerInfo & frameLayerInfo)242 Status MediaDemuxer::GetFrameLayerInfo(std::shared_ptr<AVBuffer> videoSample, FrameLayerInfo &frameLayerInfo)
243 {
244 FALSE_RETURN_V_MSG_E(videoSample != nullptr, Status::ERROR_NULL_POINTER, "videoSample is nullptr");
245 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
246 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
247 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
248 FALSE_RETURN_V_MSG_E(videoPlugin != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
249 TryRecvParserTask();
250 Status ret = videoPlugin->GetFrameLayerInfo(videoSample, frameLayerInfo);
251 if (ret == Status::ERROR_NULL_POINTER && parserRefInfoTask_ != nullptr) {
252 return Status::ERROR_AGAIN;
253 }
254 return ret;
255 }
256
GetFrameLayerInfo(uint32_t frameId,FrameLayerInfo & frameLayerInfo)257 Status MediaDemuxer::GetFrameLayerInfo(uint32_t frameId, FrameLayerInfo &frameLayerInfo)
258 {
259 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
260 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
261 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
262 FALSE_RETURN_V_MSG_E(videoPlugin != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
263 TryRecvParserTask();
264 Status ret = videoPlugin->GetFrameLayerInfo(frameId, frameLayerInfo);
265 if (ret == Status::ERROR_NULL_POINTER && parserRefInfoTask_ != nullptr) {
266 return Status::ERROR_AGAIN;
267 }
268 return ret;
269 }
270
GetGopLayerInfo(uint32_t gopId,GopLayerInfo & gopLayerInfo)271 Status MediaDemuxer::GetGopLayerInfo(uint32_t gopId, GopLayerInfo &gopLayerInfo)
272 {
273 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
274 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
275 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
276 FALSE_RETURN_V_MSG_E(videoPlugin != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
277 TryRecvParserTask();
278 Status ret = videoPlugin->GetGopLayerInfo(gopId, gopLayerInfo);
279 if (ret == Status::ERROR_NULL_POINTER && parserRefInfoTask_ != nullptr) {
280 return Status::ERROR_AGAIN;
281 }
282 return ret;
283 }
284
RegisterVideoStreamReadyCallback(const std::shared_ptr<VideoStreamReadyCallback> & callback)285 void MediaDemuxer::RegisterVideoStreamReadyCallback(const std::shared_ptr<VideoStreamReadyCallback> &callback)
286 {
287 std::unique_lock<std::mutex> draggingLock(draggingMutex_);
288 MEDIA_LOG_I("In");
289 VideoStreamReadyCallback_ = callback;
290 }
291
DeregisterVideoStreamReadyCallback()292 void MediaDemuxer::DeregisterVideoStreamReadyCallback()
293 {
294 std::unique_lock<std::mutex> draggingLock(draggingMutex_);
295 MEDIA_LOG_I("In");
296 VideoStreamReadyCallback_ = nullptr;
297 }
298
GetIFramePos(std::vector<uint32_t> & IFramePos)299 Status MediaDemuxer::GetIFramePos(std::vector<uint32_t> &IFramePos)
300 {
301 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
302 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
303 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
304 FALSE_RETURN_V_MSG_E(videoPlugin != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
305 TryRecvParserTask();
306 return videoPlugin->GetIFramePos(IFramePos);
307 }
308
Dts2FrameId(int64_t dts,uint32_t & frameId,bool offset)309 Status MediaDemuxer::Dts2FrameId(int64_t dts, uint32_t &frameId, bool offset)
310 {
311 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
312 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
313 std::shared_ptr<Plugins::DemuxerPlugin> videoPlugin = GetCurFFmpegPlugin();
314 FALSE_RETURN_V_MSG_E(videoPlugin != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
315 TryRecvParserTask();
316 return videoPlugin->Dts2FrameId(dts, frameId, offset);
317 }
318
OnBufferAvailable(uint32_t trackId)319 void MediaDemuxer::OnBufferAvailable(uint32_t trackId)
320 {
321 MEDIA_LOG_D("Buffer available track " PUBLIC_LOG_U32, trackId);
322 AccelerateTrackTask(trackId); // buffer is available trigger demuxer track working task to run immediately.
323 }
324
AccelerateTrackTask(uint32_t trackId)325 void MediaDemuxer::AccelerateTrackTask(uint32_t trackId)
326 {
327 AutoLock lock(mapMutex_);
328 if (isStopped_ || isThreadExit_) {
329 return;
330 }
331 auto track = trackMap_.find(trackId);
332 if (track == trackMap_.end() || !track->second->GetNotifyFlag()) {
333 return;
334 }
335 track->second->SetNotifyFlag(false);
336
337 auto task = taskMap_.find(trackId);
338 if (task == taskMap_.end()) {
339 return;
340 }
341 MEDIA_LOG_D("Accelerate track " PUBLIC_LOG_U32, trackId);
342 task->second->UpdateDelayTime();
343 }
344
SetTrackNotifyFlag(uint32_t trackId,bool isNotifyNeeded)345 void MediaDemuxer::SetTrackNotifyFlag(uint32_t trackId, bool isNotifyNeeded)
346 {
347 // This function is called in demuxer track working thread, and if track info exists it is valid.
348 auto track = trackMap_.find(trackId);
349 if (track != trackMap_.end()) {
350 track->second->SetNotifyFlag(isNotifyNeeded);
351 }
352 }
353
GetBitRates(std::vector<uint32_t> & bitRates)354 Status MediaDemuxer::GetBitRates(std::vector<uint32_t> &bitRates)
355 {
356 if (source_ == nullptr) {
357 MEDIA_LOG_E("Source is nullptr");
358 return Status::ERROR_INVALID_OPERATION;
359 }
360 return source_->GetBitRates(bitRates);
361 }
362
GetMediaKeySystemInfo(std::multimap<std::string,std::vector<uint8_t>> & infos)363 Status MediaDemuxer::GetMediaKeySystemInfo(std::multimap<std::string, std::vector<uint8_t>> &infos)
364 {
365 MEDIA_LOG_I("In");
366 std::shared_lock<std::shared_mutex> lock(drmMutex);
367 infos = localDrmInfos_;
368 return Status::OK;
369 }
370
GetDownloadInfo(DownloadInfo & downloadInfo)371 Status MediaDemuxer::GetDownloadInfo(DownloadInfo& downloadInfo)
372 {
373 if (source_ == nullptr) {
374 MEDIA_LOG_E("Source is nullptr");
375 return Status::ERROR_INVALID_OPERATION;
376 }
377 return source_->GetDownloadInfo(downloadInfo);
378 }
379
GetPlaybackInfo(PlaybackInfo & playbackInfo)380 Status MediaDemuxer::GetPlaybackInfo(PlaybackInfo& playbackInfo)
381 {
382 FALSE_RETURN_V_MSG(source_ != nullptr, Status::ERROR_INVALID_OPERATION, "Source is nullptr");
383 return source_->GetPlaybackInfo(playbackInfo);
384 }
385
SetDrmCallback(const std::shared_ptr<OHOS::MediaAVCodec::AVDemuxerCallback> & callback)386 void MediaDemuxer::SetDrmCallback(const std::shared_ptr<OHOS::MediaAVCodec::AVDemuxerCallback> &callback)
387 {
388 MEDIA_LOG_I("In");
389 drmCallback_ = callback;
390 bool isExisted = IsLocalDrmInfosExisted();
391 if (isExisted) {
392 MEDIA_LOG_D("Already received drminfo and report");
393 ReportDrmInfos(localDrmInfos_);
394 }
395 }
396
SetEventReceiver(const std::shared_ptr<Pipeline::EventReceiver> & receiver)397 void MediaDemuxer::SetEventReceiver(const std::shared_ptr<Pipeline::EventReceiver> &receiver)
398 {
399 eventReceiver_ = receiver;
400 }
401
SetPlayerId(const std::string & playerId)402 void MediaDemuxer::SetPlayerId(const std::string &playerId)
403 {
404 playerId_ = playerId;
405 }
406
SetDumpInfo(bool isDump,uint64_t instanceId)407 void MediaDemuxer::SetDumpInfo(bool isDump, uint64_t instanceId)
408 {
409 if (isDump && instanceId == 0) {
410 MEDIA_LOG_W("Can not dump with instanceId 0");
411 return;
412 }
413 dumpPrefix_ = std::to_string(instanceId);
414 isDump_ = isDump;
415 }
416
GetDuration(int64_t & durationMs)417 bool MediaDemuxer::GetDuration(int64_t& durationMs)
418 {
419 AutoLock lock(mapMutex_);
420 if (source_ == nullptr) {
421 durationMs = -1;
422 return false;
423 }
424 MediaAVCodec::AVCodecTrace trace("MediaDemuxer::GetDuration");
425 seekable_ = source_->GetSeekable();
426
427 FALSE_LOG(seekable_ != Seekable::INVALID);
428 if (source_->IsSeekToTimeSupported()) {
429 duration_ = source_->GetDuration();
430 if (duration_ != Plugins::HST_TIME_NONE) {
431 MEDIA_LOG_I("Hls: " PUBLIC_LOG_D64, duration_);
432 mediaMetaData_.globalMeta->Set<Tag::MEDIA_DURATION>(Plugins::HstTime2Us(duration_));
433 }
434 MEDIA_LOG_I("SeekToTime");
435 return mediaMetaData_.globalMeta->Get<Tag::MEDIA_DURATION>(durationMs);
436 }
437
438 // not hls and seekable
439 if (seekable_ == Plugins::Seekable::SEEKABLE) {
440 duration_ = source_->GetDuration();
441 if (duration_ != Plugins::HST_TIME_NONE) {
442 MEDIA_LOG_I("Not hls: " PUBLIC_LOG_D64, duration_);
443 mediaMetaData_.globalMeta->Set<Tag::MEDIA_DURATION>(Plugins::HstTime2Us(duration_));
444 }
445 MEDIA_LOG_I("Seekble");
446 return mediaMetaData_.globalMeta->Get<Tag::MEDIA_DURATION>(durationMs);
447 }
448 MEDIA_LOG_I("Other");
449 return mediaMetaData_.globalMeta->Get<Tag::MEDIA_DURATION>(durationMs);
450 }
451
GetDrmInfosUpdated(const std::multimap<std::string,std::vector<uint8_t>> & newInfos,std::multimap<std::string,std::vector<uint8_t>> & result)452 bool MediaDemuxer::GetDrmInfosUpdated(const std::multimap<std::string, std::vector<uint8_t>> &newInfos,
453 std::multimap<std::string, std::vector<uint8_t>> &result)
454 {
455 MEDIA_LOG_D("In");
456 std::unique_lock<std::shared_mutex> lock(drmMutex);
457 for (auto &newItem : newInfos) {
458 if (localDrmInfos_.find(newItem.first) == localDrmInfos_.end()) {
459 MEDIA_LOG_D("Uuid doesn't exist, update");
460 result.insert(newItem);
461 localDrmInfos_.insert(newItem);
462 continue;
463 }
464 auto pos = localDrmInfos_.equal_range(newItem.first);
465 bool isSame = false;
466 for (; pos.first != pos.second; ++pos.first) {
467 if (newItem.second == pos.first->second) {
468 MEDIA_LOG_D("Uuid exists and the pssh is same, not update");
469 isSame = true;
470 break;
471 }
472 }
473 if (!isSame) {
474 MEDIA_LOG_D("Uuid exists but pssh not same, update");
475 result.insert(newItem);
476 localDrmInfos_.insert(newItem);
477 }
478 }
479 return !result.empty();
480 }
481
IsLocalDrmInfosExisted()482 bool MediaDemuxer::IsLocalDrmInfosExisted()
483 {
484 std::shared_lock<std::shared_mutex> lock(drmMutex);
485 return !localDrmInfos_.empty();
486 }
487
ReportDrmInfos(const std::multimap<std::string,std::vector<uint8_t>> & info)488 Status MediaDemuxer::ReportDrmInfos(const std::multimap<std::string, std::vector<uint8_t>> &info)
489 {
490 MEDIA_LOG_I("In");
491 FALSE_RETURN_V_MSG_E(drmCallback_ != nullptr, Status::ERROR_INVALID_PARAMETER, "Drm callback is nullptr");
492 MEDIA_LOG_D("Filter will update drminfo");
493 drmCallback_->OnDrmInfoChanged(info);
494 return Status::OK;
495 }
496
ProcessDrmInfos()497 Status MediaDemuxer::ProcessDrmInfos()
498 {
499 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_NULL_POINTER, "Source is nullptr");
500 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
501 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = GetCurFFmpegPlugin();
502 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
503
504 std::multimap<std::string, std::vector<uint8_t>> drmInfo;
505 Status ret = pluginTemp->GetDrmInfo(drmInfo);
506 if (ret == Status::OK && !drmInfo.empty()) {
507 MEDIA_LOG_D("Get drminfo success");
508 std::multimap<std::string, std::vector<uint8_t>> infosUpdated;
509 bool isUpdated = GetDrmInfosUpdated(drmInfo, infosUpdated);
510 if (isUpdated) {
511 return ReportDrmInfos(infosUpdated);
512 } else {
513 MEDIA_LOG_D("Received drminfo but not update");
514 }
515 } else {
516 if (ret != Status::OK) {
517 MEDIA_LOG_D("Get drminfo failed, ret:" PUBLIC_LOG_D32, (int32_t)(ret));
518 }
519 }
520 return Status::OK;
521 }
522
AddDemuxerCopyTask(uint32_t trackId,TaskType type)523 Status MediaDemuxer::AddDemuxerCopyTask(uint32_t trackId, TaskType type)
524 {
525 std::string taskName = "Demux";
526 switch (type) {
527 case TaskType::VIDEO: {
528 taskName += "V";
529 break;
530 }
531 case TaskType::AUDIO: {
532 taskName += "A";
533 break;
534 }
535 case TaskType::SUBTITLE: {
536 taskName += "S";
537 break;
538 }
539 default: {
540 MEDIA_LOG_E("Add demuxer task failed, unknow task type:" PUBLIC_LOG_D32, type);
541 return Status::ERROR_UNKNOWN;
542 }
543 }
544
545 std::unique_ptr<Task> task = std::make_unique<Task>(taskName, playerId_, type);
546 if (task == nullptr) {
547 MEDIA_LOG_W("Create task failed, track:" PUBLIC_LOG_U32 ", type:" PUBLIC_LOG_D32,
548 trackId, type);
549 return Status::OK;
550 }
551 taskMap_[trackId] = std::move(task);
552 taskMap_[trackId]->RegisterJob([this, trackId] { return ReadLoop(trackId); });
553
554 // To wake up DEMUXER TRACK WORKING TASK immediately on input buffer available.
555 std::unique_ptr<Task> notifyTask =
556 std::make_unique<Task>(taskName + "N", playerId_, type, TaskPriority::NORMAL, false);
557 if (!notifyTask) {
558 MEDIA_LOG_W("Create notify task failed, track:" PUBLIC_LOG_U32 ", type:" PUBLIC_LOG_D32,
559 trackId, static_cast<uint32_t>(type));
560 return Status::OK;
561 }
562
563 sptr<IProducerListener> listener =
564 OHOS::sptr<AVBufferQueueProducerListener>::MakeSptr(trackId, shared_from_this(), notifyTask);
565 if (listener == nullptr) {
566 MEDIA_LOG_W("Create listener failed, track:" PUBLIC_LOG_U32 ", type:" PUBLIC_LOG_D32,
567 trackId, static_cast<uint32_t>(type));
568 return Status::OK;
569 }
570
571 trackMap_.emplace(trackId, std::make_shared<TrackWrapper>(trackId, listener, shared_from_this()));
572 return Status::OK;
573 }
574
InnerPrepare()575 Status MediaDemuxer::InnerPrepare()
576 {
577 Plugins::MediaInfo mediaInfo;
578 Status ret = demuxerPluginManager_->LoadCurrentAllPlugin(streamDemuxer_, mediaInfo);
579 if (ret == Status::OK) {
580 InitMediaMetaData(mediaInfo);
581 InitDefaultTrack(mediaInfo, videoTrackId_, audioTrackId_, subtitleTrackId_, videoMime_);
582 if (videoTrackId_ != TRACK_ID_DUMMY) {
583 AddDemuxerCopyTask(videoTrackId_, TaskType::VIDEO);
584 demuxerPluginManager_->UpdateTempTrackMapInfo(videoTrackId_, videoTrackId_, -1);
585 int32_t streamId = demuxerPluginManager_->GetTmpStreamIDByTrackID(videoTrackId_);
586 streamDemuxer_->SetNewVideoStreamID(streamId);
587 streamDemuxer_->SetChangeFlag(true);
588 streamDemuxer_->SetDemuxerState(streamId, DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME);
589 int64_t bitRate = 0;
590 mediaMetaData_.trackMetas[videoTrackId_]->GetData(Tag::MEDIA_BITRATE, bitRate);
591 source_->SetCurrentBitRate(bitRate, streamId);
592 targetBitRate_ = demuxerPluginManager_->GetCurrentBitRate();
593 }
594 if (audioTrackId_ != TRACK_ID_DUMMY) {
595 AddDemuxerCopyTask(audioTrackId_, TaskType::AUDIO);
596 demuxerPluginManager_->UpdateTempTrackMapInfo(audioTrackId_, audioTrackId_, -1);
597 int32_t streamId = demuxerPluginManager_->GetTmpStreamIDByTrackID(audioTrackId_);
598 streamDemuxer_->SetNewAudioStreamID(streamId);
599 streamDemuxer_->SetChangeFlag(true);
600 streamDemuxer_->SetDemuxerState(streamId, DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME);
601 int64_t bitRate = 0;
602 mediaMetaData_.trackMetas[audioTrackId_]->GetData(Tag::MEDIA_BITRATE, bitRate);
603 source_->SetCurrentBitRate(bitRate, streamId);
604 }
605 if (subtitleTrackId_ != TRACK_ID_DUMMY) {
606 AddDemuxerCopyTask(subtitleTrackId_, TaskType::SUBTITLE);
607 demuxerPluginManager_->UpdateTempTrackMapInfo(subtitleTrackId_, subtitleTrackId_, -1);
608 int32_t streamId = demuxerPluginManager_->GetTmpStreamIDByTrackID(subtitleTrackId_);
609 streamDemuxer_->SetNewSubtitleStreamID(streamId);
610 streamDemuxer_->SetChangeFlag(true);
611 streamDemuxer_->SetDemuxerState(streamId, DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME);
612 }
613 } else {
614 MEDIA_LOG_E("Parse meta failed, ret: " PUBLIC_LOG_D32, (int32_t)(ret));
615 }
616 return ret;
617 }
618
SetDataSource(const std::shared_ptr<MediaSource> & source)619 Status MediaDemuxer::SetDataSource(const std::shared_ptr<MediaSource> &source)
620 {
621 MediaAVCodec::AVCODEC_SYNC_TRACE;
622 MEDIA_LOG_I("In");
623 FALSE_RETURN_V_MSG_E(isThreadExit_, Status::ERROR_WRONG_STATE, "Process is running");
624 source_->SetCallback(this);
625 auto res = source_->SetSource(source);
626 FALSE_RETURN_V_MSG_E(res == Status::OK, res, "Plugin set source failed");
627
628 std::vector<StreamInfo> streams;
629 source_->GetStreamInfo(streams);
630 demuxerPluginManager_->InitDefaultPlay(streams);
631
632 streamDemuxer_ = std::make_shared<StreamDemuxer>();
633 streamDemuxer_->SetInterruptState(isInterruptNeeded_);
634 streamDemuxer_->SetSource(source_);
635 streamDemuxer_->Init(uri_);
636 streamDemuxer_->SetIsExtSubtitle(false);
637
638 res = InnerPrepare();
639
640 ProcessDrmInfos();
641 MEDIA_LOG_I("Out");
642 return res;
643 }
644
IsSubtitleMime(const std::string & mime)645 bool MediaDemuxer::IsSubtitleMime(const std::string& mime)
646 {
647 if (mime == "application/x-subrip" || mime == "text/vtt") {
648 return true;
649 }
650 return false;
651 }
652
SetSubtitleSource(const std::shared_ptr<MediaSource> & subSource)653 Status MediaDemuxer::SetSubtitleSource(const std::shared_ptr<MediaSource> &subSource)
654 {
655 MEDIA_LOG_I("In");
656 if (subtitleTrackId_ != TRACK_ID_DUMMY) {
657 MEDIA_LOG_W("Found subtitle track, not support ext");
658 return Status::OK;
659 }
660 subtitleSource_->SetCallback(this);
661 subtitleSource_->SetSource(subSource);
662 Status ret = subtitleSource_->GetSize(subMediaDataSize_);
663 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Get file size failed");
664 subSeekable_ = subtitleSource_->GetSeekable();
665
666 int32_t subtitleStreamID = demuxerPluginManager_->AddExternalSubtitle();
667 subStreamDemuxer_ = std::make_shared<StreamDemuxer>();
668 subStreamDemuxer_->SetInterruptState(isInterruptNeeded_);
669 subStreamDemuxer_->SetSource(subtitleSource_);
670 subStreamDemuxer_->Init(subSource->GetSourceUri());
671 subStreamDemuxer_->SetIsExtSubtitle(true);
672
673 MediaInfo mediaInfo;
674 ret = demuxerPluginManager_->LoadCurrentSubtitlePlugin(subStreamDemuxer_, mediaInfo);
675 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Parse meta failed, ret:" PUBLIC_LOG_D32, (int32_t)(ret));
676 InitMediaMetaData(mediaInfo); // update mediaMetaData_
677 for (uint32_t index = 0; index < mediaInfo.tracks.size(); index++) {
678 auto trackMeta = mediaInfo.tracks[index];
679 std::string mimeType;
680 std::string trackType;
681 trackMeta.Get<Tag::MIME_TYPE>(mimeType);
682 int32_t curStreamID = demuxerPluginManager_->GetStreamIDByTrackID(index);
683 if (trackMeta.Get<Tag::MIME_TYPE>(mimeType) && IsSubtitleMime(mimeType) && curStreamID == subtitleStreamID) {
684 MEDIA_LOG_I("STrack " PUBLIC_LOG_U32, index);
685 subtitleTrackId_ = index; // dash inner subtitle can be replace by out subtitle
686 break;
687 }
688 }
689
690 if (subtitleTrackId_ != TRACK_ID_DUMMY) {
691 AddDemuxerCopyTask(subtitleTrackId_, TaskType::SUBTITLE);
692 demuxerPluginManager_->UpdateTempTrackMapInfo(subtitleTrackId_, subtitleTrackId_, -1);
693 subStreamDemuxer_->SetNewSubtitleStreamID(subtitleStreamID);
694 subStreamDemuxer_->SetDemuxerState(subtitleStreamID, DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME);
695 }
696
697 MEDIA_LOG_I("Out, ext sub %{public}d", subtitleTrackId_);
698 return ret;
699 }
700
SetInterruptState(bool isInterruptNeeded)701 void MediaDemuxer::SetInterruptState(bool isInterruptNeeded)
702 {
703 isInterruptNeeded_ = isInterruptNeeded;
704 if (source_ != nullptr) {
705 source_->SetInterruptState(isInterruptNeeded);
706 }
707 if (streamDemuxer_ != nullptr) {
708 streamDemuxer_->SetInterruptState(isInterruptNeeded);
709 }
710 }
711
SetBundleName(const std::string & bundleName)712 void MediaDemuxer::SetBundleName(const std::string& bundleName)
713 {
714 if (source_ != nullptr) {
715 MEDIA_LOG_I("BundleName: " PUBLIC_LOG_S, bundleName.c_str());
716 bundleName_ = bundleName;
717 streamDemuxer_->SetBundleName(bundleName);
718 source_->SetBundleName(bundleName);
719 }
720 }
721
SetOutputBufferQueue(int32_t trackId,const sptr<AVBufferQueueProducer> & producer)722 Status MediaDemuxer::SetOutputBufferQueue(int32_t trackId, const sptr<AVBufferQueueProducer>& producer)
723 {
724 AutoLock lock(mapMutex_);
725 FALSE_RETURN_V_MSG_E(trackId >= 0 && (uint32_t)trackId < mediaMetaData_.trackMetas.size(),
726 Status::ERROR_INVALID_PARAMETER, "Invalid track");
727 useBufferQueue_ = true;
728 MEDIA_LOG_I("Set bufferQueue for track " PUBLIC_LOG_D32, trackId);
729 FALSE_RETURN_V_MSG_E(isThreadExit_, Status::ERROR_WRONG_STATE, "Process is running");
730 FALSE_RETURN_V_MSG_E(producer != nullptr, Status::ERROR_INVALID_PARAMETER, "BufferQueue is nullptr");
731 if (bufferQueueMap_.find(trackId) != bufferQueueMap_.end()) {
732 MEDIA_LOG_W("Has been set already");
733 }
734 Status ret = InnerSelectTrack(trackId);
735 if (ret == Status::OK) {
736 auto track = trackMap_.find(trackId);
737 if (track != trackMap_.end()) {
738 auto listener = track->second->GetProducerListener();
739 if (listener) {
740 MEDIA_LOG_W("Set listener");
741 producer->SetBufferAvailableListener(listener);
742 }
743 }
744 bufferQueueMap_.insert(std::pair<uint32_t, sptr<AVBufferQueueProducer>>(trackId, producer));
745 bufferMap_.insert(std::pair<uint32_t, std::shared_ptr<AVBuffer>>(trackId, nullptr));
746 MEDIA_LOG_I("Set bufferQueue successfully");
747 }
748 return ret;
749 }
750
OnDumpInfo(int32_t fd)751 void MediaDemuxer::OnDumpInfo(int32_t fd)
752 {
753 MEDIA_LOG_D("In");
754 if (fd < 0) {
755 MEDIA_LOG_E("Invalid fd");
756 return;
757 }
758 std::string dumpString;
759 dumpString += "MediaDemuxer buffer queue map size: " + std::to_string(bufferQueueMap_.size()) + "\n";
760 dumpString += "MediaDemuxer buffer map size: " + std::to_string(bufferMap_.size()) + "\n";
761 int ret = write(fd, dumpString.c_str(), dumpString.size());
762 if (ret < 0) {
763 MEDIA_LOG_E("MediaDemuxer::OnDumpInfo write failed");
764 return;
765 }
766 }
767
GetBufferQueueProducerMap()768 std::map<uint32_t, sptr<AVBufferQueueProducer>> MediaDemuxer::GetBufferQueueProducerMap()
769 {
770 return bufferQueueMap_;
771 }
772
InnerSelectTrack(int32_t trackId)773 Status MediaDemuxer::InnerSelectTrack(int32_t trackId)
774 {
775 eosMap_[trackId] = false;
776 requestBufferErrorCountMap_[trackId] = 0;
777 int32_t innerTrackID = trackId;
778 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = nullptr;
779 if (demuxerPluginManager_->IsDash() || demuxerPluginManager_->GetTmpStreamIDByTrackID(subtitleTrackId_) != -1) {
780 int32_t streamId = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
781 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(streamId);
782 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
783 innerTrackID = demuxerPluginManager_->GetTmpInnerTrackIDByTrackID(trackId);
784 } else {
785 int32_t streamId = demuxerPluginManager_->GetStreamIDByTrackID(trackId);
786 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(streamId);
787 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
788 }
789 return pluginTemp->SelectTrack(innerTrackID);
790 }
791
StartTask(int32_t trackId)792 Status MediaDemuxer::StartTask(int32_t trackId)
793 {
794 MEDIA_LOG_I("In, track " PUBLIC_LOG_D32, trackId);
795 std::string mimeType;
796 auto iter = taskMap_.find(trackId);
797 if (iter == taskMap_.end()) {
798 TrackType trackType = demuxerPluginManager_->GetTrackTypeByTrackID(trackId);
799 if (trackType == TrackType::TRACK_AUDIO) {
800 AddDemuxerCopyTask(trackId, TaskType::AUDIO);
801 } else if (trackType == TrackType::TRACK_VIDEO) {
802 AddDemuxerCopyTask(trackId, TaskType::VIDEO);
803 } else if (trackType == TrackType::TRACK_SUBTITLE) {
804 AddDemuxerCopyTask(trackId, TaskType::SUBTITLE);
805 }
806 if (taskMap_.find(trackId) != taskMap_.end() && taskMap_[trackId] != nullptr) {
807 taskMap_[trackId]->Start();
808 }
809 } else {
810 if (taskMap_[trackId] != nullptr && !taskMap_[trackId]->IsTaskRunning()) {
811 taskMap_[trackId]->Start();
812 }
813 }
814 return Status::OK;
815 }
816
HandleDashSelectTrack(int32_t trackId)817 Status MediaDemuxer::HandleDashSelectTrack(int32_t trackId)
818 {
819 MEDIA_LOG_I("In, track " PUBLIC_LOG_D32, trackId);
820 eosMap_[trackId] = false;
821 requestBufferErrorCountMap_[trackId] = 0;
822
823 int32_t targetStreamID = demuxerPluginManager_->GetStreamIDByTrackID(trackId);
824 if (targetStreamID == -1) {
825 MEDIA_LOG_E("Get stream failed");
826 return Status::ERROR_UNKNOWN;
827 }
828
829 int32_t curTrackId = -1;
830 TrackType trackType = demuxerPluginManager_->GetTrackTypeByTrackID(trackId);
831 if (trackType == TrackType::TRACK_AUDIO) {
832 curTrackId = static_cast<int32_t>(audioTrackId_);
833 } else if (trackType == TrackType::TRACK_VIDEO) {
834 curTrackId = static_cast<int32_t>(videoTrackId_);
835 } else if (trackType == TrackType::TRACK_SUBTITLE) {
836 curTrackId = static_cast<int32_t>(subtitleTrackId_);
837 } else { // invalid
838 MEDIA_LOG_E("Track type invalid");
839 return Status::ERROR_UNKNOWN;
840 }
841
842 if (curTrackId == trackId) {
843 MEDIA_LOG_W("Same track");
844 return Status::OK;
845 }
846
847 if (targetStreamID != demuxerPluginManager_->GetTmpStreamIDByTrackID(curTrackId)) {
848 MEDIA_LOG_I("Select stream");
849 selectTrackTrackID_ = static_cast<uint32_t>(trackId);
850 isSelectTrack_.store(true);
851 return source_->SelectStream(targetStreamID);
852 }
853
854 // same streamID
855 Status ret = DoSelectTrack(trackId, curTrackId);
856 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "DoSelectTrack track failed");
857 if (eventReceiver_ != nullptr) {
858 MEDIA_LOG_I("HandleDashSelectTrack report track change event");
859 if (trackType == TrackType::TRACK_AUDIO) {
860 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_AUDIO_TRACK_CHANGE, trackId});
861 audioTrackId_ = static_cast<uint32_t>(trackId);
862 } else if (trackType == TrackType::TRACK_VIDEO) {
863 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_VIDEO_TRACK_CHANGE, trackId});
864 videoTrackId_ = static_cast<uint32_t>(trackId);
865 } else if (trackType == TrackType::TRACK_SUBTITLE) {
866 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_SUBTITLE_TRACK_CHANGE, trackId});
867 subtitleTrackId_ = static_cast<uint32_t>(trackId);
868 } else {}
869 }
870
871 return Status::OK;
872 }
873
DoSelectTrack(int32_t trackId,int32_t curTrackId)874 Status MediaDemuxer::DoSelectTrack(int32_t trackId, int32_t curTrackId)
875 {
876 if (static_cast<uint32_t>(curTrackId) != TRACK_ID_DUMMY) {
877 if (taskMap_.find(curTrackId) != taskMap_.end() && taskMap_[curTrackId] != nullptr) {
878 taskMap_[curTrackId]->Stop();
879 }
880 Status ret = UnselectTrack(curTrackId);
881 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Unselect track failed");
882 bufferQueueMap_.insert(
883 std::pair<uint32_t, sptr<AVBufferQueueProducer>>(trackId, bufferQueueMap_[curTrackId]));
884 bufferMap_.insert(std::pair<uint32_t, std::shared_ptr<AVBuffer>>(trackId, bufferMap_[curTrackId]));
885 bufferQueueMap_.erase(curTrackId);
886 bufferMap_.erase(curTrackId);
887 demuxerPluginManager_->UpdateTempTrackMapInfo(trackId, trackId, -1);
888 return InnerSelectTrack(trackId);
889 }
890 return Status::ERROR_UNKNOWN;
891 }
892
HandleSelectTrack(int32_t trackId)893 Status MediaDemuxer::HandleSelectTrack(int32_t trackId)
894 {
895 int32_t curTrackId = -1;
896 TrackType trackType = demuxerPluginManager_->GetTrackTypeByTrackID(trackId);
897 if (trackType == TrackType::TRACK_AUDIO) {
898 MEDIA_LOG_I("Select audio [" PUBLIC_LOG_D32 "->" PUBLIC_LOG_D32 "]", audioTrackId_, trackId);
899 curTrackId = static_cast<int32_t>(audioTrackId_);
900 } else { // inner subtitle and video not support
901 MEDIA_LOG_W("Unsupport track " PUBLIC_LOG_D32, trackId);
902 return Status::ERROR_INVALID_PARAMETER;
903 }
904
905 if (curTrackId == trackId) {
906 return Status::OK;
907 }
908
909 Status ret = DoSelectTrack(trackId, curTrackId);
910 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "DoSelectTrack track failed");
911 if (eventReceiver_ != nullptr) {
912 MEDIA_LOG_I("HandleSelectTrack report track change event");
913 if (trackType == TrackType::TRACK_AUDIO) {
914 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_AUDIO_TRACK_CHANGE, trackId});
915 audioTrackId_ = static_cast<uint32_t>(trackId);
916 } else if (trackType == TrackType::TRACK_VIDEO) {
917 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_VIDEO_TRACK_CHANGE, trackId});
918 videoTrackId_ = static_cast<uint32_t>(trackId);
919 } else {}
920 }
921
922 return ret;
923 }
924
SelectTrack(int32_t trackId)925 Status MediaDemuxer::SelectTrack(int32_t trackId)
926 {
927 MediaAVCodec::AVCODEC_SYNC_TRACE;
928 MEDIA_LOG_D("Select " PUBLIC_LOG_D32, trackId);
929 FALSE_RETURN_V_MSG_E(trackId >= 0 && (uint32_t)trackId < mediaMetaData_.trackMetas.size(),
930 Status::ERROR_INVALID_PARAMETER, "Select track failed");
931 if (!useBufferQueue_) {
932 return InnerSelectTrack(trackId);
933 }
934 if (trackId == static_cast<int32_t>(videoTrackId_) || trackId == static_cast<int32_t>(audioTrackId_)
935 || trackId == static_cast<int32_t>(subtitleTrackId_)) {
936 MEDIA_LOG_W("same trackId, can not SelectTrack");
937 return Status::ERROR_WRONG_STATE;
938 }
939 if (demuxerPluginManager_->IsDash()) {
940 if (streamDemuxer_->CanDoChangeStream() == false) {
941 MEDIA_LOG_W("Wrong state: selecting");
942 return Status::ERROR_WRONG_STATE;
943 }
944 return HandleDashSelectTrack(trackId);
945 }
946 return HandleSelectTrack(trackId);
947 }
948
UnselectTrack(int32_t trackId)949 Status MediaDemuxer::UnselectTrack(int32_t trackId)
950 {
951 MediaAVCodec::AVCODEC_SYNC_TRACE;
952 MEDIA_LOG_D("Unselect " PUBLIC_LOG_D32, trackId);
953
954 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = nullptr;
955 int32_t innerTrackID = trackId;
956 if (demuxerPluginManager_->IsDash() || demuxerPluginManager_->GetTmpStreamIDByTrackID(subtitleTrackId_) != -1) {
957 int32_t streamId = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
958 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(streamId);
959 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
960 innerTrackID = demuxerPluginManager_->GetTmpInnerTrackIDByTrackID(trackId);
961 } else {
962 int32_t streamID = demuxerPluginManager_->GetStreamIDByTrackID(trackId);
963 if (streamID == -1) {
964 MEDIA_LOG_W("Invalid track " PUBLIC_LOG_D32, trackId);
965 return Status::OK;
966 }
967 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(streamID);
968 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
969 }
970 demuxerPluginManager_->DeleteTempTrackMapInfo(trackId);
971
972 return pluginTemp->UnselectTrack(innerTrackID);
973 }
974
HandleStopPlugin(int32_t trackId)975 void MediaDemuxer::HandleStopPlugin(int32_t trackId)
976 {
977 FALSE_RETURN(!subStreamDemuxer_ || trackId != static_cast<int32_t>(subtitleTrackId_));
978 if (static_cast<uint32_t>(trackId) != TRACK_ID_DUMMY) {
979 int32_t streamID = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
980 MEDIA_LOG_I("Stop stream " PUBLIC_LOG_D32, streamID);
981 demuxerPluginManager_->StopPlugin(streamID, streamDemuxer_);
982 }
983 }
984
HandleStartPlugin(int32_t trackId)985 void MediaDemuxer::HandleStartPlugin(int32_t trackId)
986 {
987 FALSE_RETURN(!subStreamDemuxer_ || trackId != static_cast<int32_t>(subtitleTrackId_));
988 if (static_cast<uint32_t>(trackId) != TRACK_ID_DUMMY) {
989 int32_t streamID = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
990 demuxerPluginManager_->StartPlugin(streamID, streamDemuxer_);
991 InnerSelectTrack(trackId);
992 }
993 }
994
SeekToTimePre()995 Status MediaDemuxer::SeekToTimePre()
996 {
997 if (demuxerPluginManager_->IsDash() == false) {
998 return Status::OK;
999 }
1000
1001 if (isSelectBitRate_) {
1002 HandleStopPlugin(audioTrackId_);
1003 HandleStopPlugin(subtitleTrackId_);
1004 } else if (isSelectTrack_ == true) {
1005 TrackType type = demuxerPluginManager_->GetTrackTypeByTrackID(selectTrackTrackID_);
1006 if (type == TrackType::TRACK_AUDIO) {
1007 HandleStopPlugin(videoTrackId_);
1008 HandleStopPlugin(subtitleTrackId_);
1009 } else if (type == TrackType::TRACK_VIDEO) {
1010 HandleStopPlugin(audioTrackId_);
1011 HandleStopPlugin(subtitleTrackId_);
1012 } else if (type == TrackType::TRACK_SUBTITLE) {
1013 HandleStopPlugin(videoTrackId_);
1014 HandleStopPlugin(audioTrackId_);
1015 } else {
1016 // invalid
1017 }
1018 } else {
1019 MEDIA_LOG_I("Stop plugin");
1020 HandleStopPlugin(videoTrackId_);
1021 HandleStopPlugin(audioTrackId_);
1022 HandleStopPlugin(subtitleTrackId_);
1023 streamDemuxer_->ResetAllCache();
1024 }
1025 return Status::OK;
1026 }
1027
1028
SeekToTimeAfter()1029 Status MediaDemuxer::SeekToTimeAfter()
1030 {
1031 if (demuxerPluginManager_->IsDash() == false) {
1032 return Status::OK;
1033 }
1034
1035 if (isSelectBitRate_) {
1036 HandleStartPlugin(audioTrackId_);
1037 HandleStartPlugin(subtitleTrackId_);
1038 } else if (isSelectTrack_ == true) {
1039 TrackType type = demuxerPluginManager_->GetTrackTypeByTrackID(selectTrackTrackID_);
1040 if (type == TrackType::TRACK_AUDIO) {
1041 HandleStartPlugin(videoTrackId_);
1042 HandleStartPlugin(subtitleTrackId_);
1043 if (shouldCheckAudioFramePts_) {
1044 shouldCheckAudioFramePts_ = false;
1045 }
1046 } else if (type == TrackType::TRACK_VIDEO) {
1047 HandleStartPlugin(audioTrackId_);
1048 HandleStartPlugin(subtitleTrackId_);
1049 } else if (type == TrackType::TRACK_SUBTITLE) {
1050 HandleStartPlugin(audioTrackId_);
1051 HandleStartPlugin(videoTrackId_);
1052 if (shouldCheckSubtitleFramePts_) {
1053 shouldCheckSubtitleFramePts_ = false;
1054 }
1055 } else {
1056 // invalid
1057 }
1058 } else {
1059 HandleStartPlugin(audioTrackId_);
1060 HandleStartPlugin(videoTrackId_);
1061 HandleStartPlugin(subtitleTrackId_);
1062 }
1063
1064 return Status::OK;
1065 }
1066
SeekTo(int64_t seekTime,Plugins::SeekMode mode,int64_t & realSeekTime)1067 Status MediaDemuxer::SeekTo(int64_t seekTime, Plugins::SeekMode mode, int64_t& realSeekTime)
1068 {
1069 MediaAVCodec::AVCODEC_SYNC_TRACE;
1070 Status ret;
1071 isSeekError_.store(false);
1072 if (source_ != nullptr && source_->IsSeekToTimeSupported()) {
1073 MEDIA_LOG_D("Source seek");
1074 SeekToTimePre();
1075 if (mode == SeekMode::SEEK_CLOSEST_INNER) {
1076 ret = source_->SeekToTime(seekTime, SeekMode::SEEK_PREVIOUS_SYNC);
1077 } else {
1078 ret = source_->SeekToTime(seekTime, SeekMode::SEEK_CLOSEST_SYNC);
1079 }
1080 if (subStreamDemuxer_) {
1081 demuxerPluginManager_->localSubtitleSeekTo(seekTime);
1082 }
1083 SeekToTimeAfter();
1084 Plugins::Ms2HstTime(seekTime, realSeekTime);
1085 } else {
1086 MEDIA_LOG_D("Demuxer seek");
1087 if (mode == SeekMode::SEEK_CLOSEST_INNER) {
1088 ret = demuxerPluginManager_->SeekTo(seekTime, SeekMode::SEEK_PREVIOUS_SYNC, realSeekTime);
1089 } else {
1090 ret = demuxerPluginManager_->SeekTo(seekTime, mode, realSeekTime);
1091 }
1092 }
1093 isSeeked_ = true;
1094 for (auto item : eosMap_) {
1095 eosMap_[item.first] = false;
1096 }
1097 for (auto item : requestBufferErrorCountMap_) {
1098 requestBufferErrorCountMap_[item.first] = 0;
1099 }
1100 if (ret != Status::OK) {
1101 isSeekError_.store(true);
1102 }
1103 isFirstFrameAfterSeek_.store(true);
1104 MEDIA_LOG_D("Out");
1105 return ret;
1106 }
1107
SelectBitRate(uint32_t bitRate)1108 Status MediaDemuxer::SelectBitRate(uint32_t bitRate)
1109 {
1110 FALSE_RETURN_V_MSG_E(source_ != nullptr, Status::ERROR_INVALID_PARAMETER, "Source is nullptr");
1111 MEDIA_LOG_I("In");
1112 if (demuxerPluginManager_->IsDash()) {
1113 if (streamDemuxer_->CanDoChangeStream() == false) {
1114 MEDIA_LOG_W("Wrong state: selecting");
1115 return Status::OK;
1116 }
1117 if (bitRate == demuxerPluginManager_->GetCurrentBitRate()) {
1118 MEDIA_LOG_W("Same bitrate");
1119 return Status::OK;
1120 }
1121 isSelectBitRate_.store(true);
1122 }
1123 streamDemuxer_->ResetAllCache();
1124 Status ret = source_->SelectBitRate(bitRate);
1125 if (ret != Status::OK) {
1126 MEDIA_LOG_E("Source select bitrate failed");
1127 if (demuxerPluginManager_->IsDash()) {
1128 isSelectBitRate_.store(false);
1129 }
1130 }
1131 targetBitRate_ = bitRate;
1132 MEDIA_LOG_I("Out");
1133 return ret;
1134 }
1135
GetStreamMetaInfo() const1136 std::vector<std::shared_ptr<Meta>> MediaDemuxer::GetStreamMetaInfo() const
1137 {
1138 MediaAVCodec::AVCODEC_SYNC_TRACE;
1139 return mediaMetaData_.trackMetas;
1140 }
1141
GetGlobalMetaInfo() const1142 std::shared_ptr<Meta> MediaDemuxer::GetGlobalMetaInfo() const
1143 {
1144 MediaAVCodec::AVCODEC_SYNC_TRACE;
1145 return mediaMetaData_.globalMeta;
1146 }
1147
GetUserMeta()1148 std::shared_ptr<Meta> MediaDemuxer::GetUserMeta()
1149 {
1150 MediaAVCodec::AVCODEC_SYNC_TRACE;
1151 return demuxerPluginManager_->GetUserMeta();
1152 }
1153
Flush()1154 Status MediaDemuxer::Flush()
1155 {
1156 MEDIA_LOG_I("In");
1157 if (streamDemuxer_) {
1158 streamDemuxer_->Flush();
1159 }
1160
1161 {
1162 AutoLock lock(mapMutex_);
1163 auto it = bufferQueueMap_.begin();
1164 while (it != bufferQueueMap_.end()) {
1165 uint32_t trackId = it->first;
1166 if (trackId != videoTrackId_) {
1167 bufferQueueMap_[trackId]->Clear();
1168 }
1169 it++;
1170 }
1171 }
1172
1173 if (demuxerPluginManager_) {
1174 // hls reset ffmpeg eos status
1175 if (source_ != nullptr && source_->IsSeekToTimeSupported()) {
1176 demuxerPluginManager_->SetResetEosStatus(true);
1177 }
1178 demuxerPluginManager_->Flush();
1179 }
1180
1181 InitPtsInfo();
1182 return Status::OK;
1183 }
1184
StopAllTask()1185 Status MediaDemuxer::StopAllTask()
1186 {
1187 MEDIA_LOG_I("In");
1188 isDemuxerLoopExecuting_ = false;
1189 if (streamDemuxer_ != nullptr) {
1190 streamDemuxer_->SetIsIgnoreParse(true);
1191 }
1192 if (source_ != nullptr) {
1193 source_->Stop();
1194 }
1195
1196 auto it = taskMap_.begin();
1197 while (it != taskMap_.end()) {
1198 if (it->second != nullptr) {
1199 it->second->Stop();
1200 it->second = nullptr;
1201 }
1202 it = taskMap_.erase(it);
1203 }
1204 isThreadExit_ = true;
1205 MEDIA_LOG_I("Out");
1206 return Status::OK;
1207 }
1208
PauseAllTask()1209 Status MediaDemuxer::PauseAllTask()
1210 {
1211 MEDIA_LOG_I("In");
1212 isDemuxerLoopExecuting_ = false;
1213 // To accelerate DemuxerLoop thread to run into PAUSED state
1214 for (auto &iter : taskMap_) {
1215 if (iter.second != nullptr) {
1216 iter.second->PauseAsync();
1217 }
1218 }
1219
1220 for (auto &iter : taskMap_) {
1221 if (iter.second != nullptr) {
1222 iter.second->Pause();
1223 }
1224 }
1225 MEDIA_LOG_I("Out");
1226 return Status::OK;
1227 }
1228
ResumeAllTask()1229 Status MediaDemuxer::ResumeAllTask()
1230 {
1231 MEDIA_LOG_I("In");
1232 isDemuxerLoopExecuting_ = true;
1233 streamDemuxer_->SetIsIgnoreParse(false);
1234
1235 auto it = bufferQueueMap_.begin();
1236 while (it != bufferQueueMap_.end()) {
1237 uint32_t trackId = it->first;
1238 if (taskMap_.find(trackId) != taskMap_.end() && taskMap_[trackId] != nullptr) {
1239 taskMap_[trackId]->Start();
1240 } else {
1241 MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " task is not exist", trackId);
1242 }
1243 it++;
1244 }
1245 MEDIA_LOG_I("Out");
1246 return Status::OK;
1247 }
1248
Pause()1249 Status MediaDemuxer::Pause()
1250 {
1251 MEDIA_LOG_I("In");
1252 isPaused_ = true;
1253 if (streamDemuxer_) {
1254 streamDemuxer_->SetIsIgnoreParse(true);
1255 streamDemuxer_->Pause();
1256 }
1257 if (source_) {
1258 source_->SetReadBlockingFlag(false); // Disable source read blocking to prevent pause all task blocking
1259 source_->Pause();
1260 }
1261 if (inPreroll_.load()) {
1262 if (CheckTrackEnabledById(videoTrackId_)) {
1263 taskMap_[videoTrackId_]->PauseAsync();
1264 taskMap_[videoTrackId_]->Pause();
1265 }
1266 } else {
1267 PauseAllTask();
1268 }
1269 if (source_ != nullptr) {
1270 source_->SetReadBlockingFlag(true); // Enable source read blocking to ensure get wanted data
1271 }
1272 return Status::OK;
1273 }
1274
PauseDragging()1275 Status MediaDemuxer::PauseDragging()
1276 {
1277 MEDIA_LOG_I("PauseDragging");
1278 isPaused_ = true;
1279 if (streamDemuxer_) {
1280 streamDemuxer_->SetIsIgnoreParse(true);
1281 streamDemuxer_->Pause();
1282 }
1283 if (source_) {
1284 source_->SetReadBlockingFlag(false); // Disable source read blocking to prevent pause all task blocking
1285 source_->Pause();
1286 }
1287 if (taskMap_.find(videoTrackId_) != taskMap_.end() && taskMap_[videoTrackId_] != nullptr) {
1288 taskMap_[videoTrackId_]->PauseAsync();
1289 taskMap_[videoTrackId_]->Pause();
1290 }
1291
1292 if (source_ != nullptr) {
1293 source_->SetReadBlockingFlag(true); // Enable source read blocking to ensure get wanted data
1294 }
1295 return Status::OK;
1296 }
1297
PauseAudioAlign()1298 Status MediaDemuxer::PauseAudioAlign()
1299 {
1300 MEDIA_LOG_I("PauseDragging");
1301 isPaused_ = true;
1302 if (streamDemuxer_) {
1303 streamDemuxer_->SetIsIgnoreParse(true);
1304 streamDemuxer_->Pause();
1305 }
1306 if (source_) {
1307 source_->SetReadBlockingFlag(false); // Disable source read blocking to prevent pause all task blocking
1308 source_->Pause();
1309 }
1310 if (taskMap_.find(audioTrackId_) != taskMap_.end() && taskMap_[audioTrackId_] != nullptr) {
1311 taskMap_[audioTrackId_]->PauseAsync();
1312 taskMap_[audioTrackId_]->Pause();
1313 }
1314
1315 if (source_ != nullptr) {
1316 source_->SetReadBlockingFlag(true); // Enable source read blocking to ensure get wanted data
1317 }
1318 return Status::OK;
1319 }
1320
PauseTaskByTrackId(int32_t trackId)1321 Status MediaDemuxer::PauseTaskByTrackId(int32_t trackId)
1322 {
1323 MEDIA_LOG_I("In, track %{public}d", trackId);
1324 FALSE_RETURN_V_MSG_E(trackId >= 0, Status::ERROR_INVALID_PARAMETER, "Invalid track");
1325
1326 // To accelerate DemuxerLoop thread to run into PAUSED state
1327 for (auto &iter : taskMap_) {
1328 if (iter.first == static_cast<uint32_t>(trackId) && iter.second != nullptr) {
1329 iter.second->PauseAsync();
1330 }
1331 }
1332
1333 for (auto &iter : taskMap_) {
1334 if (iter.first == static_cast<uint32_t>(trackId) && iter.second != nullptr) {
1335 iter.second->Pause();
1336 }
1337 }
1338 return Status::OK;
1339 }
1340
Resume()1341 Status MediaDemuxer::Resume()
1342 {
1343 MEDIA_LOG_I("In");
1344 if (streamDemuxer_) {
1345 streamDemuxer_->Resume();
1346 }
1347 if (source_) {
1348 source_->Resume();
1349 }
1350 if (inPreroll_.load()) {
1351 if (CheckTrackEnabledById(videoTrackId_)) {
1352 if (streamDemuxer_) {
1353 streamDemuxer_->SetIsIgnoreParse(false);
1354 }
1355 taskMap_[videoTrackId_]->Start();
1356 }
1357 } else {
1358 ResumeAllTask();
1359 }
1360 isPaused_ = false;
1361 return Status::OK;
1362 }
1363
ResumeDragging()1364 Status MediaDemuxer::ResumeDragging()
1365 {
1366 MEDIA_LOG_I("In");
1367 for (auto item : eosMap_) {
1368 eosMap_[item.first] = false;
1369 }
1370 if (streamDemuxer_) {
1371 streamDemuxer_->Resume();
1372 }
1373 if (source_) {
1374 source_->Resume();
1375 }
1376 if (taskMap_.find(videoTrackId_) != taskMap_.end() && taskMap_[videoTrackId_] != nullptr) {
1377 if (streamDemuxer_) {
1378 streamDemuxer_->SetIsIgnoreParse(false);
1379 }
1380 taskMap_[videoTrackId_]->Start();
1381 }
1382 isPaused_ = false;
1383 return Status::OK;
1384 }
1385
ResumeAudioAlign()1386 Status MediaDemuxer::ResumeAudioAlign()
1387 {
1388 MEDIA_LOG_I("Resume");
1389 if (streamDemuxer_) {
1390 streamDemuxer_->Resume();
1391 }
1392 if (source_) {
1393 source_->Resume();
1394 }
1395 if (taskMap_.find(audioTrackId_) != taskMap_.end() && taskMap_[audioTrackId_] != nullptr) {
1396 streamDemuxer_->SetIsIgnoreParse(false);
1397 taskMap_[audioTrackId_]->Start();
1398 }
1399 isPaused_ = false;
1400 return Status::OK;
1401 }
1402
ResetInner()1403 void MediaDemuxer::ResetInner()
1404 {
1405 std::map<uint32_t, std::shared_ptr<TrackWrapper>> trackMap;
1406 {
1407 AutoLock lock(mapMutex_);
1408 mediaMetaData_.globalMeta.reset();
1409 mediaMetaData_.trackMetas.clear();
1410 }
1411 Stop();
1412 {
1413 AutoLock lock(mapMutex_);
1414 std::swap(trackMap, trackMap_);
1415 bufferQueueMap_.clear();
1416 bufferMap_.clear();
1417 localDrmInfos_.clear();
1418 }
1419 // Should perform trackMap_ clear without holding mapMutex_ to avoid dead lock:
1420 // 1. TrackWrapper indirectly holds notifyTask which holds its jobMutex_ firstly when run, then requires mapMutex_.
1421 // 2. Release notifyTask also needs hold its jobMutex_ firstly.
1422 trackMap.clear();
1423 }
1424
Reset()1425 Status MediaDemuxer::Reset()
1426 {
1427 MediaAVCodec::AVCodecTrace trace("MediaDemuxer::Reset");
1428 FALSE_RETURN_V_MSG_E(useBufferQueue_, Status::ERROR_WRONG_STATE, "Not buffer queue mode");
1429 isDemuxerLoopExecuting_ = false;
1430 ResetInner();
1431 for (auto item : eosMap_) {
1432 eosMap_[item.first] = false;
1433 }
1434 for (auto item : requestBufferErrorCountMap_) {
1435 requestBufferErrorCountMap_[item.first] = 0;
1436 }
1437 videoStartTime_ = 0;
1438 streamDemuxer_->ResetAllCache();
1439 isSeekError_.store(false);
1440 return demuxerPluginManager_->Reset();
1441 }
1442
Start()1443 Status MediaDemuxer::Start()
1444 {
1445 MediaAVCodec::AVCodecTrace trace("MediaDemuxer::Start");
1446 MEDIA_LOG_I("In");
1447 FALSE_RETURN_V_MSG_E(useBufferQueue_, Status::ERROR_WRONG_STATE, "Not buffer queue mode");
1448 FALSE_RETURN_V_MSG_E(isThreadExit_, Status::OK, "Process has been started already");
1449 FALSE_RETURN_V_MSG_E(bufferQueueMap_.size() != 0, Status::OK, "No buffer queue");
1450 for (auto it = eosMap_.begin(); it != eosMap_.end(); it++) {
1451 it->second = false;
1452 }
1453 for (auto it = requestBufferErrorCountMap_.begin(); it != requestBufferErrorCountMap_.end(); it++) {
1454 it->second = 0;
1455 }
1456 InitPtsInfo();
1457 isThreadExit_ = false;
1458 isStopped_ = false;
1459 isDemuxerLoopExecuting_ = true;
1460 if (inPreroll_.load()) {
1461 if (CheckTrackEnabledById(videoTrackId_)) {
1462 taskMap_[videoTrackId_]->Start();
1463 }
1464 } else {
1465 auto it = bufferQueueMap_.begin();
1466 while (it != bufferQueueMap_.end()) {
1467 uint32_t trackId = it->first;
1468 if (taskMap_.find(trackId) != taskMap_.end() && taskMap_[trackId] != nullptr) {
1469 taskMap_[trackId]->Start();
1470 } else {
1471 MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " task is not exist", trackId);
1472 }
1473 it++;
1474 }
1475 }
1476 source_->Start();
1477 return demuxerPluginManager_->Start();
1478 }
1479
Preroll()1480 Status MediaDemuxer::Preroll()
1481 {
1482 std::lock_guard<std::mutex> lock(prerollMutex_);
1483 if (inPreroll_.load()) {
1484 return Status::OK;
1485 }
1486 if (!CheckTrackEnabledById(videoTrackId_)) {
1487 return Status::OK;
1488 }
1489 inPreroll_.store(true);
1490 MEDIA_LOG_D("Preroll enter.");
1491 Status ret = Status::OK;
1492 if (isStopped_.load()) {
1493 ret = Start();
1494 } else if (isPaused_.load()) {
1495 ret = Resume();
1496 }
1497 if (ret != Status::OK) {
1498 inPreroll_.store(false);
1499 MEDIA_LOG_E("Preroll failed, ret: %{public}d", ret);
1500 }
1501 return ret;
1502 }
1503
PausePreroll()1504 Status MediaDemuxer::PausePreroll()
1505 {
1506 std::lock_guard<std::mutex> lock(prerollMutex_);
1507 if (!inPreroll_.load()) {
1508 return Status::OK;
1509 }
1510 MEDIA_LOG_D("Preroll enter.");
1511 Status ret = Pause();
1512 inPreroll_.store(false);
1513 return ret;
1514 }
1515
Stop()1516 Status MediaDemuxer::Stop()
1517 {
1518 FALSE_RETURN_V_MSG_E(useBufferQueue_, Status::ERROR_WRONG_STATE, "Cannot reset track when not use buffer queue.");
1519 FALSE_RETURN_V_MSG_E(!isThreadExit_, Status::OK, "Thread exit");
1520 MediaAVCodec::AVCodecTrace trace("MediaDemuxer::Stop");
1521 MEDIA_LOG_I("In");
1522 {
1523 AutoLock lock(mapMutex_);
1524 FALSE_RETURN_V_MSG_E(!isStopped_, Status::OK, "Process has been stopped already, ignore");
1525 isStopped_ = true;
1526 StopAllTask();
1527 }
1528 streamDemuxer_->Stop();
1529 return demuxerPluginManager_->Stop();
1530 }
1531
HasVideo()1532 bool MediaDemuxer::HasVideo()
1533 {
1534 return videoTrackId_ != TRACK_ID_DUMMY;
1535 }
1536
InitMediaMetaData(const Plugins::MediaInfo & mediaInfo)1537 void MediaDemuxer::InitMediaMetaData(const Plugins::MediaInfo& mediaInfo)
1538 {
1539 AutoLock lock(mapMutex_);
1540 mediaMetaData_.globalMeta = std::make_shared<Meta>(mediaInfo.general);
1541 mediaMetaData_.trackMetas.clear();
1542 mediaMetaData_.trackMetas.reserve(mediaInfo.tracks.size());
1543 for (uint32_t index = 0; index < mediaInfo.tracks.size(); index++) {
1544 auto trackMeta = mediaInfo.tracks[index];
1545 mediaMetaData_.trackMetas.emplace_back(std::make_shared<Meta>(trackMeta));
1546 }
1547 }
1548
InitDefaultTrack(const Plugins::MediaInfo & mediaInfo,uint32_t & videoTrackId,uint32_t & audioTrackId,uint32_t & subtitleTrackId,std::string & videoMime)1549 void MediaDemuxer::InitDefaultTrack(const Plugins::MediaInfo& mediaInfo, uint32_t& videoTrackId,
1550 uint32_t& audioTrackId, uint32_t& subtitleTrackId, std::string& videoMime)
1551 {
1552 AutoLock lock(mapMutex_);
1553 std::string dafaultTrack = "[";
1554 for (uint32_t index = 0; index < mediaInfo.tracks.size(); index++) {
1555 if (demuxerPluginManager_->CheckTrackIsActive(index) == false) {
1556 continue;
1557 }
1558 auto trackMeta = mediaInfo.tracks[index];
1559 std::string mimeType;
1560 bool ret = trackMeta.Get<Tag::MIME_TYPE>(mimeType);
1561 if (ret && mimeType.find("video") == 0 &&
1562 !IsTrackDisabled(Plugins::MediaType::VIDEO)) {
1563 dafaultTrack += "/V:";
1564 dafaultTrack += std::to_string(index);
1565 videoMime = mimeType;
1566 if (videoTrackId == TRACK_ID_DUMMY) {
1567 videoTrackId = index;
1568 }
1569 if (!trackMeta.GetData(Tag::MEDIA_START_TIME, videoStartTime_)) {
1570 MEDIA_LOG_W("Get media start time failed");
1571 }
1572 } else if (ret && mimeType.find("audio") == 0 &&
1573 !IsTrackDisabled(Plugins::MediaType::AUDIO)) {
1574 dafaultTrack += "/A:";
1575 dafaultTrack += std::to_string(index);
1576 if (audioTrackId == TRACK_ID_DUMMY) {
1577 audioTrackId = index;
1578 }
1579 } else if (ret && IsSubtitleMime(mimeType) &&
1580 !IsTrackDisabled(Plugins::MediaType::SUBTITLE)) {
1581 dafaultTrack += "/S:";
1582 dafaultTrack += std::to_string(index);
1583 if (subtitleTrackId == TRACK_ID_DUMMY) {
1584 subtitleTrackId = index;
1585 }
1586 } else {}
1587 }
1588 dafaultTrack += "]";
1589 MEDIA_LOG_I(PUBLIC_LOG_S, dafaultTrack.c_str());
1590 }
1591
GetBufferFromUserQueue(uint32_t queueIndex,uint32_t size)1592 bool MediaDemuxer::GetBufferFromUserQueue(uint32_t queueIndex, uint32_t size)
1593 {
1594 MEDIA_LOG_D("In, queue: " PUBLIC_LOG_U32 ", size: " PUBLIC_LOG_U32, queueIndex, size);
1595 FALSE_RETURN_V_MSG_E(bufferQueueMap_.count(queueIndex) > 0 && bufferQueueMap_[queueIndex] != nullptr, false,
1596 "BufferQueue " PUBLIC_LOG_D32 " is nullptr", queueIndex);
1597
1598 AVBufferConfig avBufferConfig;
1599 avBufferConfig.capacity = static_cast<int32_t>(size);
1600 Status ret = bufferQueueMap_[queueIndex]->RequestBuffer(bufferMap_[queueIndex], avBufferConfig,
1601 REQUEST_BUFFER_TIMEOUT);
1602 if (ret != Status::OK) {
1603 requestBufferErrorCountMap_[queueIndex]++;
1604 if (requestBufferErrorCountMap_[queueIndex] % 5 == 0) { // log per 5 times fail
1605 MEDIA_LOG_W("Request buffer failed, queue: " PUBLIC_LOG_U32 ", ret:" PUBLIC_LOG_D32
1606 ", errorCnt:" PUBLIC_LOG_U32, queueIndex, (int32_t)(ret), requestBufferErrorCountMap_[queueIndex]);
1607 }
1608 if (requestBufferErrorCountMap_[queueIndex] >= REQUEST_FAILED_RETRY_TIMES) {
1609 MEDIA_LOG_E("Request failed too many times in 1min");
1610 }
1611 } else {
1612 requestBufferErrorCountMap_[queueIndex] = 0;
1613 }
1614 return ret == Status::OK;
1615 }
1616
HandleSelectTrackChangeStream(int32_t trackId,int32_t newStreamID,int32_t & newTrackId)1617 bool MediaDemuxer::HandleSelectTrackChangeStream(int32_t trackId, int32_t newStreamID, int32_t& newTrackId)
1618 {
1619 StreamType streamType = demuxerPluginManager_->GetStreamTypeByTrackID(selectTrackTrackID_);
1620 int32_t currentStreamID = demuxerPluginManager_->GetStreamIDByTrackID(trackId);
1621 int32_t currentTrackId = trackId;
1622 if (newStreamID == -1 || currentStreamID == newStreamID) {
1623 return false;
1624 }
1625 MEDIA_LOG_I("In");
1626 // stop plugin
1627 demuxerPluginManager_->StopPlugin(currentStreamID, streamDemuxer_);
1628
1629 // start plugin
1630 Status ret = demuxerPluginManager_->StartPlugin(newStreamID, streamDemuxer_);
1631 FALSE_RETURN_V_MSG_E(ret == Status::OK, false, "Start plugin failed");
1632
1633 // get new mediainfo
1634 Plugins::MediaInfo mediaInfo;
1635 demuxerPluginManager_->UpdateDefaultStreamID(mediaInfo, streamType, newStreamID);
1636 InitMediaMetaData(mediaInfo); // update mediaMetaData_
1637
1638 // get newStreamID
1639 int32_t newInnerTrackId;
1640 demuxerPluginManager_->GetTrackInfoByStreamID(newStreamID, newTrackId, newInnerTrackId);
1641
1642 // update track map
1643 demuxerPluginManager_->DeleteTempTrackMapInfo(currentTrackId);
1644 int32_t innerTrackID = demuxerPluginManager_->GetInnerTrackIDByTrackID(newTrackId);
1645 demuxerPluginManager_->UpdateTempTrackMapInfo(newTrackId, newTrackId, innerTrackID);
1646 MEDIA_LOG_I("Updata info");
1647
1648 InnerSelectTrack(newTrackId);
1649
1650 // update buffer queue
1651 bufferQueueMap_.insert(std::pair<uint32_t, sptr<AVBufferQueueProducer>>(newTrackId,
1652 bufferQueueMap_[currentTrackId]));
1653 bufferMap_.insert(std::pair<uint32_t, std::shared_ptr<AVBuffer>>(newTrackId,
1654 bufferMap_[currentTrackId]));
1655 bufferQueueMap_.erase(currentTrackId);
1656 bufferMap_.erase(currentTrackId);
1657
1658 MEDIA_LOG_I("Out");
1659 return true;
1660 }
1661
SelectTrackChangeStream(uint32_t trackId)1662 bool MediaDemuxer::SelectTrackChangeStream(uint32_t trackId)
1663 {
1664 MediaAVCodec::AVCodecTrace trace("MediaDemuxer::SelectTrackChangeStream");
1665 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, false, "Invalid param");
1666 TrackType type = demuxerPluginManager_->GetTrackTypeByTrackID(static_cast<int32_t>(trackId));
1667 int32_t newStreamID = -1;
1668 if (type == TRACK_AUDIO) {
1669 newStreamID = streamDemuxer_->GetNewAudioStreamID();
1670 } else if (type == TRACK_SUBTITLE) {
1671 newStreamID = streamDemuxer_->GetNewSubtitleStreamID();
1672 } else if (type == TRACK_VIDEO) {
1673 newStreamID = streamDemuxer_->GetNewVideoStreamID();
1674 } else {
1675 MEDIA_LOG_W("Invalid track " PUBLIC_LOG_U32, trackId);
1676 return false;
1677 }
1678
1679 int32_t newTrackId;
1680 bool ret = HandleSelectTrackChangeStream(trackId, newStreamID, newTrackId);
1681 if (ret && eventReceiver_ != nullptr) {
1682 MEDIA_LOG_I("TrackType: " PUBLIC_LOG_U32 ", TrackId " PUBLIC_LOG_D32 " >> " PUBLIC_LOG_D32,
1683 static_cast<uint32_t>(type), trackId, newTrackId);
1684 if (type == TrackType::TRACK_AUDIO) {
1685 audioTrackId_ = static_cast<uint32_t>(newTrackId);
1686 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_AUDIO_TRACK_CHANGE, newTrackId});
1687 shouldCheckAudioFramePts_ = true;
1688 } else if (type == TrackType::TRACK_VIDEO) {
1689 videoTrackId_ = static_cast<uint32_t>(newTrackId);
1690 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_VIDEO_TRACK_CHANGE, newTrackId});
1691 } else if (type == TrackType::TRACK_SUBTITLE) {
1692 subtitleTrackId_ = static_cast<uint32_t>(newTrackId);
1693 eventReceiver_->OnEvent({"media_demuxer", EventType::EVENT_SUBTITLE_TRACK_CHANGE, newTrackId});
1694 shouldCheckSubtitleFramePts_ = true;
1695 }
1696
1697 if (newTrackId == static_cast<int32_t>(selectTrackTrackID_)) {
1698 isSelectTrack_.store(false);
1699 }
1700
1701 if (taskMap_.find(trackId) != taskMap_.end() && taskMap_[trackId] != nullptr) {
1702 taskMap_[trackId]->StopAsync(); // stop self
1703 }
1704 return true;
1705 }
1706 return ret;
1707 }
1708
SelectBitRateChangeStream(uint32_t trackId)1709 bool MediaDemuxer::SelectBitRateChangeStream(uint32_t trackId)
1710 {
1711 int32_t currentStreamID = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
1712 int32_t newStreamID = streamDemuxer_->GetNewVideoStreamID();
1713 if (newStreamID >= 0 && currentStreamID != newStreamID) {
1714 MEDIA_LOG_I("In");
1715 demuxerPluginManager_->StopPlugin(currentStreamID, streamDemuxer_);
1716
1717 Status ret = demuxerPluginManager_->StartPlugin(newStreamID, streamDemuxer_);
1718 FALSE_RETURN_V_MSG_E(ret == Status::OK, false, "Start plugin failed");
1719
1720 Plugins::MediaInfo mediaInfo;
1721 demuxerPluginManager_->UpdateDefaultStreamID(mediaInfo, VIDEO, newStreamID);
1722 InitMediaMetaData(mediaInfo); // update mediaMetaData_
1723
1724 int32_t newInnerTrackId = -1;
1725 int32_t newTrackId = -1;
1726 demuxerPluginManager_->GetTrackInfoByStreamID(newStreamID, newTrackId, newInnerTrackId);
1727 demuxerPluginManager_->UpdateTempTrackMapInfo(videoTrackId_, newTrackId, newInnerTrackId);
1728
1729 MEDIA_LOG_I("Updata info");
1730 InnerSelectTrack(static_cast<int32_t>(trackId));
1731 MEDIA_LOG_I("Out");
1732 return true;
1733 }
1734 return false;
1735 }
DumpBufferToFile(uint32_t trackId,std::shared_ptr<AVBuffer> buffer)1736 void MediaDemuxer::DumpBufferToFile(uint32_t trackId, std::shared_ptr<AVBuffer> buffer)
1737 {
1738 std::string mimeType;
1739 if (isDump_) {
1740 if (mediaMetaData_.trackMetas[trackId]->Get<Tag::MIME_TYPE>(mimeType) && mimeType.find("audio") == 0) {
1741 DumpAVBufferToFile(DUMP_PARAM, dumpPrefix_ + DUMP_DEMUXER_AUDIO_FILE_NAME, buffer);
1742 }
1743 if (mediaMetaData_.trackMetas[trackId]->Get<Tag::MIME_TYPE>(mimeType) && mimeType.find("video") == 0) {
1744 DumpAVBufferToFile(DUMP_PARAM, dumpPrefix_ + DUMP_DEMUXER_VIDEO_FILE_NAME, buffer);
1745 }
1746 }
1747 }
1748
HandleReadSample(uint32_t trackId)1749 Status MediaDemuxer::HandleReadSample(uint32_t trackId)
1750 {
1751 Status ret = InnerReadSample(trackId, bufferMap_[trackId]);
1752 if (trackId == videoTrackId_) {
1753 std::unique_lock<std::mutex> draggingLock(draggingMutex_);
1754 if (VideoStreamReadyCallback_ != nullptr) {
1755 MEDIA_LOG_D("In");
1756 std::shared_ptr<VideoStreamReadyCallback> videoStreamReadyCallback = VideoStreamReadyCallback_;
1757 draggingLock.unlock();
1758 bool isDiscardable = videoStreamReadyCallback->IsVideoStreamDiscardable(bufferMap_[trackId]);
1759 bufferQueueMap_[trackId]->PushBuffer(bufferMap_[trackId], !isDiscardable);
1760 return Status::OK;
1761 }
1762 }
1763
1764 if (source_ != nullptr && source_->IsSeekToTimeSupported() && isSeeked_ && HasVideo()) {
1765 if (trackId == videoTrackId_ && isFirstFrameAfterSeek_.load()) {
1766 bool isSyncFrame = (bufferMap_[trackId]->flag_ & (uint32_t)(AVBufferFlag::SYNC_FRAME)) != 0;
1767 if (!isSyncFrame) {
1768 MEDIA_LOG_E("The first frame after seeking is not a sync frame");
1769 }
1770 isFirstFrameAfterSeek_.store(false);
1771 }
1772 MEDIA_LOG_I("Seeking, found idr frame track " PUBLIC_LOG_U32, trackId);
1773 isSeeked_ = false;
1774 }
1775 if (ret == Status::OK || ret == Status::END_OF_STREAM) {
1776 if (bufferMap_[trackId]->flag_ & (uint32_t)(AVBufferFlag::EOS)) {
1777 eosMap_[trackId] = true;
1778 if (taskMap_.find(trackId) != taskMap_.end() && taskMap_[trackId] != nullptr) {
1779 taskMap_[trackId]->StopAsync();
1780 }
1781 MEDIA_LOG_I("Track eos, track: " PUBLIC_LOG_U32 ", bufferId: " PUBLIC_LOG_U64
1782 ", pts: " PUBLIC_LOG_D64 ", flag: " PUBLIC_LOG_U32, trackId, bufferMap_[trackId]->GetUniqueId(),
1783 bufferMap_[trackId]->pts_, bufferMap_[trackId]->flag_);
1784 ret = bufferQueueMap_[trackId]->PushBuffer(bufferMap_[trackId], true);
1785 return Status::OK;
1786 }
1787 MEDIA_LOG_D("HandleReadSample PushBuffer, track: " PUBLIC_LOG_U32 ", bufferid: " PUBLIC_LOG_U64 ", pts: "
1788 PUBLIC_LOG_U64 ", flag: " PUBLIC_LOG_U32,
1789 trackId, bufferMap_[trackId]->GetUniqueId(), bufferMap_[trackId]->pts_, bufferMap_[trackId]->flag_);
1790 HandleAutoMaintainPts(trackId, bufferMap_[trackId]);
1791 bool isDroppable = IsBufferDroppable(bufferMap_[trackId], trackId);
1792 ret = bufferQueueMap_[trackId]->PushBuffer(bufferMap_[trackId], !isDroppable);
1793 } else {
1794 bufferQueueMap_[trackId]->PushBuffer(bufferMap_[trackId], false);
1795 MEDIA_LOG_E("Read failed, track " PUBLIC_LOG_U32 ", ret:" PUBLIC_LOG_D32, trackId, (int32_t)(ret));
1796 }
1797 return ret;
1798 }
1799
HandleDashChangeStream(uint32_t trackId)1800 bool MediaDemuxer::HandleDashChangeStream(uint32_t trackId)
1801 {
1802 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, false, "Plugin manager is nullptr");
1803 FALSE_RETURN_V_MSG_E(streamDemuxer_ != nullptr, false, "Stream is nullptr");
1804 if (demuxerPluginManager_->IsDash() == false) {
1805 return false;
1806 }
1807
1808 if (trackId == videoTrackId_ && demuxerPluginManager_->GetCurrentBitRate() != targetBitRate_) {
1809 auto result = SelectBitRateChangeStream(trackId);
1810 if (result) {
1811 streamDemuxer_->SetChangeFlag(true);
1812 if (targetBitRate_ == demuxerPluginManager_->GetCurrentBitRate()) {
1813 isSelectBitRate_.store(false);
1814 }
1815 return true;
1816 }
1817 } else if (isSelectTrack_) {
1818 auto result = SelectTrackChangeStream(trackId);
1819 if (result) {
1820 targetBitRate_ = demuxerPluginManager_->GetCurrentBitRate();
1821 streamDemuxer_->SetChangeFlag(true);
1822 return true;
1823 }
1824 }
1825
1826 return false;
1827 }
1828
CopyFrameToUserQueue(uint32_t trackId)1829 Status MediaDemuxer::CopyFrameToUserQueue(uint32_t trackId)
1830 {
1831 MediaAVCodec::AVCodecTrace trace("MediaDemuxer::CopyFrameToUserQueue");
1832 MEDIA_LOG_D("In, track:" PUBLIC_LOG_U32, trackId);
1833
1834 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = nullptr;
1835 int32_t innerTrackID = static_cast<int32_t>(trackId);
1836 int32_t id = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
1837 if (demuxerPluginManager_->IsDash() || demuxerPluginManager_->GetTmpStreamIDByTrackID(subtitleTrackId_) != -1) {
1838 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(id);
1839 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
1840 innerTrackID = demuxerPluginManager_->GetTmpInnerTrackIDByTrackID(trackId);
1841 } else {
1842 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(id);
1843 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
1844 }
1845
1846 int32_t size = 0;
1847 Status ret = pluginTemp->GetNextSampleSize(innerTrackID, size);
1848 FALSE_RETURN_V_MSG_E(ret != Status::ERROR_UNKNOWN, ret, "Get size failed for track " PUBLIC_LOG_U32, trackId);
1849 FALSE_RETURN_V_MSG_E(ret != Status::ERROR_AGAIN, ret,
1850 "Get size failed for track " PUBLIC_LOG_U32 ", retry", trackId);
1851 FALSE_RETURN_V_MSG_E(ret != Status::ERROR_NO_MEMORY, ret, "Get size failed for track " PUBLIC_LOG_U32, trackId);
1852 if (HandleDashChangeStream(trackId)) {
1853 MEDIA_LOG_I("HandleDashChangeStream success");
1854 return Status::OK;
1855 }
1856 SetTrackNotifyFlag(trackId, true);
1857 if (!GetBufferFromUserQueue(trackId, size)) {
1858 return Status::ERROR_INVALID_PARAMETER;
1859 }
1860 SetTrackNotifyFlag(trackId, false);
1861 ret = HandleReadSample(trackId);
1862 MEDIA_LOG_D("Out, track:" PUBLIC_LOG_U32, trackId);
1863 return ret;
1864 }
1865
InnerReadSample(uint32_t trackId,std::shared_ptr<AVBuffer> sample)1866 Status MediaDemuxer::InnerReadSample(uint32_t trackId, std::shared_ptr<AVBuffer> sample)
1867 {
1868 MEDIA_LOG_D("In, track " PUBLIC_LOG_U32, trackId);
1869 int32_t innerTrackID = static_cast<int32_t>(trackId);
1870 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = nullptr;
1871 if (demuxerPluginManager_->IsDash() || demuxerPluginManager_->GetTmpStreamIDByTrackID(subtitleTrackId_) != -1) {
1872 int32_t streamId = demuxerPluginManager_->GetTmpStreamIDByTrackID(trackId);
1873 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(streamId);
1874 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
1875 innerTrackID = demuxerPluginManager_->GetTmpInnerTrackIDByTrackID(trackId);
1876 } else {
1877 int32_t streamId = demuxerPluginManager_->GetStreamIDByTrackID(trackId);
1878 pluginTemp = demuxerPluginManager_->GetPluginByStreamID(streamId);
1879 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_INVALID_PARAMETER, "Demuxer plugin is nullptr");
1880 }
1881
1882 Status ret = pluginTemp->ReadSample(innerTrackID, sample);
1883 if (ret == Status::END_OF_STREAM) {
1884 MEDIA_LOG_I("Read eos for track " PUBLIC_LOG_U32, trackId);
1885 } else if (ret != Status::OK) {
1886 MEDIA_LOG_I("Read error for track " PUBLIC_LOG_U32 ", ret: " PUBLIC_LOG_D32, trackId, (int32_t)(ret));
1887 }
1888 MEDIA_LOG_D("Out, track " PUBLIC_LOG_U32, trackId);
1889 ProcessDrmInfos();
1890 return ret;
1891 }
1892
ReadLoop(uint32_t trackId)1893 int64_t MediaDemuxer::ReadLoop(uint32_t trackId)
1894 {
1895 if (streamDemuxer_->GetIsIgnoreParse() || isStopped_ || isPaused_ || isSeekError_) {
1896 MEDIA_LOG_D("ReadLoop pausing or error, track " PUBLIC_LOG_U32, trackId);
1897 return 6 * 1000; // sleep 6ms in pausing to avoid useless reading
1898 } else {
1899 Status ret = CopyFrameToUserQueue(trackId);
1900 // when read failed, or request always failed in 1min, send error event
1901 bool ignoreError = isStopped_ || isPaused_ || isInterruptNeeded_.load();
1902 if ((ret == Status::ERROR_UNKNOWN && !ignoreError) ||
1903 requestBufferErrorCountMap_[trackId] >= REQUEST_FAILED_RETRY_TIMES) {
1904 MEDIA_LOG_E("Invalid data source, can not get frame");
1905 if (eventReceiver_ != nullptr) {
1906 eventReceiver_->OnEvent({"demuxer_filter", EventType::EVENT_ERROR, MSERR_DATA_SOURCE_ERROR_UNKNOWN});
1907 } else {
1908 MEDIA_LOG_D("EventReceiver is nullptr");
1909 }
1910 }
1911 bool isNeedRetry = ret == Status::OK || ret == Status::ERROR_AGAIN;
1912 if (isNeedRetry) {
1913 return 0; // retry next frame
1914 } else if (ret == Status::ERROR_NO_MEMORY) {
1915 MEDIA_LOG_E("Cache data size is out of limit");
1916 if (eventReceiver_ != nullptr && !isOnEventNoMemory_.load()) {
1917 isOnEventNoMemory_.store(true);
1918 eventReceiver_->OnEvent({"demuxer_filter", EventType::EVENT_ERROR, MSERR_DEMUXER_BUFFER_NO_MEMORY});
1919 }
1920 return 0;
1921 } else {
1922 MEDIA_LOG_D("ReadLoop wait, track:" PUBLIC_LOG_U32 ", ret:" PUBLIC_LOG_D32,
1923 trackId, static_cast<int32_t>(ret));
1924 return RETRY_DELAY_TIME_US; // delay to retry if no frame
1925 }
1926 }
1927 }
1928
ReadSample(uint32_t trackId,std::shared_ptr<AVBuffer> sample)1929 Status MediaDemuxer::ReadSample(uint32_t trackId, std::shared_ptr<AVBuffer> sample)
1930 {
1931 MediaAVCodec::AVCODEC_SYNC_TRACE;
1932 FALSE_RETURN_V_MSG_E(!useBufferQueue_, Status::ERROR_WRONG_STATE, "Not buffer queue mode");
1933 MEDIA_LOG_D("In");
1934 FALSE_RETURN_V_MSG_E(eosMap_.count(trackId) > 0, Status::ERROR_INVALID_OPERATION, "Track has not been selected");
1935 FALSE_RETURN_V_MSG_E(sample != nullptr && sample->memory_!=nullptr, Status::ERROR_INVALID_PARAMETER,
1936 "AVBuffer is nullptr");
1937 if (eosMap_[trackId]) {
1938 MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " has reached eos", trackId);
1939 sample->flag_ = (uint32_t)(AVBufferFlag::EOS);
1940 sample->memory_->SetSize(0);
1941 return Status::END_OF_STREAM;
1942 }
1943 Status ret = InnerReadSample(trackId, sample);
1944 if (ret == Status::OK || ret == Status::END_OF_STREAM) {
1945 if (sample->flag_ & (uint32_t)(AVBufferFlag::EOS)) {
1946 eosMap_[trackId] = true;
1947 sample->memory_->SetSize(0);
1948 }
1949 if (sample->flag_ & (uint32_t)(AVBufferFlag::PARTIAL_FRAME)) {
1950 ret = Status::ERROR_NO_MEMORY;
1951 }
1952 }
1953 return ret;
1954 }
1955
HandleSourceDrmInfoEvent(const std::multimap<std::string,std::vector<uint8_t>> & info)1956 void MediaDemuxer::HandleSourceDrmInfoEvent(const std::multimap<std::string, std::vector<uint8_t>> &info)
1957 {
1958 MEDIA_LOG_I("In");
1959 std::multimap<std::string, std::vector<uint8_t>> infoUpdated;
1960 bool isUpdated = GetDrmInfosUpdated(info, infoUpdated);
1961 if (isUpdated) {
1962 ReportDrmInfos(infoUpdated);
1963 return;
1964 }
1965 MEDIA_LOG_D("Demuxer filter received source drminfos but not update");
1966 }
1967
OnEvent(const Plugins::PluginEvent & event)1968 void MediaDemuxer::OnEvent(const Plugins::PluginEvent &event)
1969 {
1970 MEDIA_LOG_D("In");
1971 if (eventReceiver_ == nullptr && event.type != PluginEventType::SOURCE_DRM_INFO_UPDATE) {
1972 MEDIA_LOG_D("EventReceiver is nullptr");
1973 return;
1974 }
1975 switch (event.type) {
1976 case PluginEventType::SOURCE_DRM_INFO_UPDATE: {
1977 MEDIA_LOG_D("OnEvent source drmInfo update");
1978 HandleSourceDrmInfoEvent(AnyCast<std::multimap<std::string, std::vector<uint8_t>>>(event.param));
1979 break;
1980 }
1981 case PluginEventType::CLIENT_ERROR:
1982 case PluginEventType::SERVER_ERROR: {
1983 MEDIA_LOG_E("error code " PUBLIC_LOG_D32, MSERR_EXT_IO);
1984 eventReceiver_->OnEvent({"demuxer_filter", EventType::EVENT_ERROR, MSERR_DATA_SOURCE_IO_ERROR});
1985 break;
1986 }
1987 case PluginEventType::BUFFERING_END: {
1988 MEDIA_LOG_D("OnEvent pause");
1989 eventReceiver_->OnEvent({"demuxer_filter", EventType::BUFFERING_END, PAUSE});
1990 break;
1991 }
1992 case PluginEventType::BUFFERING_START: {
1993 MEDIA_LOG_D("OnEvent start");
1994 eventReceiver_->OnEvent({"demuxer_filter", EventType::BUFFERING_START, START});
1995 break;
1996 }
1997 case PluginEventType::CACHED_DURATION: {
1998 MEDIA_LOG_D("OnEvent cached duration");
1999 eventReceiver_->OnEvent({"demuxer_filter", EventType::EVENT_CACHED_DURATION, event.param});
2000 break;
2001 }
2002 case PluginEventType::SOURCE_BITRATE_START: {
2003 MEDIA_LOG_D("OnEvent source bitrate start");
2004 eventReceiver_->OnEvent({"demuxer_filter", EventType::EVENT_SOURCE_BITRATE_START, event.param});
2005 break;
2006 }
2007 case PluginEventType::EVENT_BUFFER_PROGRESS: {
2008 MEDIA_LOG_D("OnEvent percent update");
2009 eventReceiver_->OnEvent({"demuxer_filter", EventType::EVENT_BUFFER_PROGRESS, event.param});
2010 break;
2011 }
2012 default:
2013 break;
2014 }
2015 }
2016
OptimizeDecodeSlow(bool isDecodeOptimizationEnabled)2017 Status MediaDemuxer::OptimizeDecodeSlow(bool isDecodeOptimizationEnabled)
2018 {
2019 MEDIA_LOG_I("In");
2020 isDecodeOptimizationEnabled_ = isDecodeOptimizationEnabled;
2021 return Status::OK;
2022 }
2023
SetDecoderFramerateUpperLimit(int32_t decoderFramerateUpperLimit,uint32_t trackId)2024 Status MediaDemuxer::SetDecoderFramerateUpperLimit(int32_t decoderFramerateUpperLimit,
2025 uint32_t trackId)
2026 {
2027 MEDIA_LOG_I("DecoderFramerateUpperLimit=" PUBLIC_LOG_D32 " trackId=" PUBLIC_LOG_D32,
2028 decoderFramerateUpperLimit, trackId);
2029 FALSE_RETURN_V(trackId == videoTrackId_, Status::OK);
2030 FALSE_RETURN_V_MSG_E(decoderFramerateUpperLimit > 0, Status::ERROR_INVALID_PARAMETER,
2031 "SetDecoderFramerateUpperLimit failed, decoderFramerateUpperLimit <= 0");
2032 decoderFramerateUpperLimit_.store(decoderFramerateUpperLimit);
2033 return Status::OK;
2034 }
2035
SetSpeed(float speed)2036 Status MediaDemuxer::SetSpeed(float speed)
2037 {
2038 MEDIA_LOG_I("Speed=" PUBLIC_LOG_F, speed);
2039 FALSE_RETURN_V_MSG_E(speed > 0, Status::ERROR_INVALID_PARAMETER, "Speed <= 0");
2040 speed_.store(speed);
2041 return Status::OK;
2042 }
2043
SetFrameRate(double framerate,uint32_t trackId)2044 Status MediaDemuxer::SetFrameRate(double framerate, uint32_t trackId)
2045 {
2046 MEDIA_LOG_I("Framerate=" PUBLIC_LOG_F " trackId=" PUBLIC_LOG_D32, framerate, trackId);
2047 FALSE_RETURN_V(trackId == videoTrackId_, Status::OK);
2048 FALSE_RETURN_V_MSG_E(framerate > 0, Status::ERROR_INVALID_PARAMETER, "Framerate <= 0");
2049 framerate_.store(framerate);
2050 return Status::OK;
2051 }
2052
CheckDropAudioFrame(std::shared_ptr<AVBuffer> sample,uint32_t trackId)2053 void MediaDemuxer::CheckDropAudioFrame(std::shared_ptr<AVBuffer> sample, uint32_t trackId)
2054 {
2055 if (trackId == audioTrackId_) {
2056 if (shouldCheckAudioFramePts_ == false) {
2057 lastAudioPts_ = sample->pts_;
2058 MEDIA_LOG_I("Set last audio pts " PUBLIC_LOG_D64, lastAudioPts_);
2059 return;
2060 }
2061 if (sample->pts_ < lastAudioPts_) {
2062 MEDIA_LOG_I("Drop audio buffer pts " PUBLIC_LOG_D64, sample->pts_);
2063 return;
2064 }
2065 if (shouldCheckAudioFramePts_) {
2066 shouldCheckAudioFramePts_ = false;
2067 }
2068 }
2069 if (trackId == subtitleTrackId_) {
2070 if (shouldCheckSubtitleFramePts_ == false) {
2071 lastSubtitlePts_ = sample->pts_;
2072 MEDIA_LOG_I("Set last subtitle pts " PUBLIC_LOG_D64, lastSubtitlePts_);
2073 return;
2074 }
2075 if (sample->pts_ < lastSubtitlePts_) {
2076 MEDIA_LOG_I("Drop subtitle buffer pts " PUBLIC_LOG_D64, sample->pts_);
2077 return;
2078 }
2079 if (shouldCheckSubtitleFramePts_) {
2080 shouldCheckSubtitleFramePts_ = false;
2081 }
2082 }
2083 }
2084
IsBufferDroppable(std::shared_ptr<AVBuffer> sample,uint32_t trackId)2085 bool MediaDemuxer::IsBufferDroppable(std::shared_ptr<AVBuffer> sample, uint32_t trackId)
2086 {
2087 DumpBufferToFile(trackId, sample);
2088
2089 if (demuxerPluginManager_->IsDash()) {
2090 CheckDropAudioFrame(sample, trackId);
2091 }
2092
2093 if (trackId != videoTrackId_) {
2094 return false;
2095 }
2096
2097 if (!isDecodeOptimizationEnabled_.load()) {
2098 return false;
2099 }
2100
2101 double targetRate = framerate_.load() * speed_.load();
2102 double actualRate = decoderFramerateUpperLimit_.load() * (1 + DECODE_RATE_THRESHOLD);
2103 if (targetRate <= actualRate) {
2104 return false;
2105 }
2106
2107 bool canDrop = false;
2108 bool ret = sample->meta_->GetData(Media::Tag::VIDEO_BUFFER_CAN_DROP, canDrop);
2109 if (!ret || !canDrop) {
2110 return false;
2111 }
2112
2113 MEDIA_LOG_D("Drop buffer, framerate=" PUBLIC_LOG_F " speed=" PUBLIC_LOG_F " decodeUpLimit="
2114 PUBLIC_LOG_D32 " pts=" PUBLIC_LOG_D64, framerate_.load(), speed_.load(),
2115 decoderFramerateUpperLimit_.load(), sample->pts_);
2116 return true;
2117 }
2118
DisableMediaTrack(Plugins::MediaType mediaType)2119 Status MediaDemuxer::DisableMediaTrack(Plugins::MediaType mediaType)
2120 {
2121 disabledMediaTracks_.emplace(mediaType);
2122 return Status::OK;
2123 }
2124
IsTrackDisabled(Plugins::MediaType mediaType)2125 bool MediaDemuxer::IsTrackDisabled(Plugins::MediaType mediaType)
2126 {
2127 return !disabledMediaTracks_.empty() && disabledMediaTracks_.find(mediaType) != disabledMediaTracks_.end();
2128 }
2129
CheckTrackEnabledById(uint32_t trackId)2130 bool MediaDemuxer::CheckTrackEnabledById(uint32_t trackId)
2131 {
2132 bool hasTrack = trackId != TRACK_ID_DUMMY;
2133 if (!hasTrack) {
2134 return false;
2135 }
2136 bool hasTask = taskMap_.find(trackId) != taskMap_.end() && taskMap_[trackId] != nullptr;
2137 if (!hasTask) {
2138 return false;
2139 }
2140 bool linkNode = bufferQueueMap_.find(trackId) != bufferQueueMap_.end()
2141 && bufferQueueMap_[trackId] != nullptr;
2142 return linkNode;
2143 }
2144
SetSelectBitRateFlag(bool flag,uint32_t desBitRate)2145 void MediaDemuxer::SetSelectBitRateFlag(bool flag, uint32_t desBitRate)
2146 {
2147 MEDIA_LOG_I("Flag=" PUBLIC_LOG_D32 " desBitRate=" PUBLIC_LOG_U32,
2148 static_cast<int32_t>(flag), desBitRate);
2149 isSelectBitRate_.store(flag);
2150 if (flag) {
2151 targetBitRate_ = desBitRate;
2152 }
2153 }
2154
CanAutoSelectBitRate()2155 bool MediaDemuxer::CanAutoSelectBitRate()
2156 {
2157 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, false, "Plugin manager is nullptr");
2158 // calculating auto selectbitrate time
2159 return !(isSelectBitRate_.load()) && !(isSelectTrack_.load())
2160 && (targetBitRate_ == demuxerPluginManager_->GetCurrentBitRate());
2161 }
2162
IsRenderNextVideoFrameSupported()2163 bool MediaDemuxer::IsRenderNextVideoFrameSupported()
2164 {
2165 bool isDataSrcLiveStream = source_ != nullptr && source_->IsNeedPreDownload() &&
2166 source_->GetSeekable() == Plugins::Seekable::UNSEEKABLE;
2167 return videoTrackId_ != TRACK_ID_DUMMY && !IsTrackDisabled(Plugins::MediaType::VIDEO) &&
2168 !isDataSrcLiveStream;
2169 }
2170
GetIndexByRelativePresentationTimeUs(const uint32_t trackIndex,const uint64_t relativePresentationTimeUs,uint32_t & index)2171 Status MediaDemuxer::GetIndexByRelativePresentationTimeUs(const uint32_t trackIndex,
2172 const uint64_t relativePresentationTimeUs, uint32_t &index)
2173 {
2174 MEDIA_LOG_D("In");
2175 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
2176 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = GetCurFFmpegPlugin();
2177 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
2178
2179 Status ret = pluginTemp->GetIndexByRelativePresentationTimeUs(trackIndex, relativePresentationTimeUs, index);
2180 if (ret != Status::OK) {
2181 MEDIA_LOG_E("Get index failed");
2182 }
2183 return ret;
2184 }
2185
GetRelativePresentationTimeUsByIndex(const uint32_t trackIndex,const uint32_t index,uint64_t & relativePresentationTimeUs)2186 Status MediaDemuxer::GetRelativePresentationTimeUsByIndex(const uint32_t trackIndex,
2187 const uint32_t index, uint64_t &relativePresentationTimeUs)
2188 {
2189 MEDIA_LOG_D("In");
2190 FALSE_RETURN_V_MSG_E(demuxerPluginManager_ != nullptr, Status::ERROR_NULL_POINTER, "Plugin manager is nullptr");
2191 std::shared_ptr<Plugins::DemuxerPlugin> pluginTemp = GetCurFFmpegPlugin();
2192 FALSE_RETURN_V_MSG_E(pluginTemp != nullptr, Status::ERROR_NULL_POINTER, "Demuxer plugin is nullptr");
2193
2194 Status ret = pluginTemp->GetRelativePresentationTimeUsByIndex(trackIndex, index, relativePresentationTimeUs);
2195 if (ret != Status::OK) {
2196 MEDIA_LOG_E("Get pts failed");
2197 }
2198 return ret;
2199 }
2200
ResumeDemuxerReadLoop()2201 Status MediaDemuxer::ResumeDemuxerReadLoop()
2202 {
2203 MEDIA_LOG_I("In");
2204 if (isDemuxerLoopExecuting_) {
2205 MEDIA_LOG_I("Has already resumed");
2206 return Status::OK;
2207 }
2208 isDemuxerLoopExecuting_ = true;
2209 return ResumeAllTask();
2210 }
2211
PauseDemuxerReadLoop()2212 Status MediaDemuxer::PauseDemuxerReadLoop()
2213 {
2214 MEDIA_LOG_I("In");
2215 if (!isDemuxerLoopExecuting_) {
2216 MEDIA_LOG_I("Has already paused");
2217 return Status::OK;
2218 }
2219 isDemuxerLoopExecuting_ = false;
2220 return PauseAllTask();
2221 }
2222
SetCacheLimit(uint32_t limitSize)2223 void MediaDemuxer::SetCacheLimit(uint32_t limitSize)
2224 {
2225 FALSE_RETURN_MSG(demuxerPluginManager_ != nullptr, "Plugin manager is nullptr");
2226 (void)demuxerPluginManager_->SetCacheLimit(limitSize);
2227 }
2228
IsVideoEos()2229 bool MediaDemuxer::IsVideoEos()
2230 {
2231 if (videoTrackId_ == TRACK_ID_DUMMY) {
2232 return true;
2233 }
2234 return eosMap_[videoTrackId_];
2235 }
2236
HasEosTrack()2237 bool MediaDemuxer::HasEosTrack()
2238 {
2239 for (auto it = eosMap_.begin(); it != eosMap_.end(); it++) {
2240 if (it->second) {
2241 return true;
2242 }
2243 }
2244 return false;
2245 }
2246
SetEnableOnlineFdCache(bool isEnableFdCache)2247 void MediaDemuxer::SetEnableOnlineFdCache(bool isEnableFdCache)
2248 {
2249 FALSE_RETURN(source_ != nullptr);
2250 source_->SetEnableOnlineFdCache(isEnableFdCache);
2251 }
2252
WaitForBufferingEnd()2253 void MediaDemuxer::WaitForBufferingEnd()
2254 {
2255 FALSE_RETURN_MSG(source_ != nullptr, "Source is nullptr");
2256 source_->WaitForBufferingEnd();
2257 }
2258 } // namespace Media
2259 } // namespace OHOS
2260