1 /*
2 * Copyright (c) 2024-2024 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 #define HST_LOG_TAG "DashMediaDownloader"
16
17 #include <algorithm>
18 #include "dash_media_downloader.h"
19 #include "securec.h"
20 #include "plugin/plugin_time.h"
21 #include "osal/task/task.h"
22 #include "utils/time_utils.h"
23 #include "utils/bitrate_process_utils.h"
24 #include "format.h"
25
26 namespace OHOS {
27 namespace Media {
28 namespace Plugins {
29 namespace HttpPlugin {
30
31 constexpr double BUFFER_LOW_LIMIT = 0.3;
32 constexpr double BYTE_TO_BIT = 8.0;
33 constexpr size_t RETRY_TIMES = 15000;
34 constexpr unsigned int SLEEP_TIME = 1;
35
DashMediaDownloader()36 DashMediaDownloader::DashMediaDownloader() noexcept
37 {
38 mpdDownloader_ = std::make_shared<DashMpdDownloader>();
39 mpdDownloader_->SetMpdCallback(this);
40 }
41
~DashMediaDownloader()42 DashMediaDownloader::~DashMediaDownloader()
43 {
44 if (mpdDownloader_ != nullptr) {
45 mpdDownloader_->Close(false);
46 }
47 segmentDownloaders_.clear();
48 }
49
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader)50 bool DashMediaDownloader::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader)
51 {
52 mpdDownloader_->Open(url);
53 return true;
54 }
55
Close(bool isAsync)56 void DashMediaDownloader::Close(bool isAsync)
57 {
58 mpdDownloader_->Close(isAsync);
59 for (unsigned int index = 0; index < segmentDownloaders_.size(); index++) {
60 segmentDownloaders_[index]->Close(isAsync, true);
61 }
62 }
63
Pause()64 void DashMediaDownloader::Pause()
65 {
66 for (unsigned int index = 0; index < segmentDownloaders_.size(); index++) {
67 segmentDownloaders_[index]->Pause();
68 }
69 }
70
Resume()71 void DashMediaDownloader::Resume()
72 {
73 for (unsigned int index = 0; index < segmentDownloaders_.size(); index++) {
74 segmentDownloaders_[index]->Resume();
75 }
76 }
77
Read(unsigned char * buff,ReadDataInfo & readDataInfo)78 Status DashMediaDownloader::Read(unsigned char* buff, ReadDataInfo& readDataInfo)
79 {
80 FALSE_RETURN_V(buff != nullptr, Status::END_OF_STREAM);
81 if (segmentDownloaders_.empty()) {
82 MEDIA_LOG_W("dash read, segmentDownloaders size is 0");
83 return Status::END_OF_STREAM;
84 }
85
86 if (downloadErrorState_) {
87 if (callback_ != nullptr) {
88 MEDIA_LOG_I("Read Client Error, OnEvent");
89 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "read"});
90 }
91 for (auto &segmentDownloader : segmentDownloaders_) {
92 segmentDownloader->Close(false, true);
93 }
94 return Status::ERROR_AGAIN;
95 }
96
97 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloader(readDataInfo.streamId_);
98 if (segmentDownloader == nullptr) {
99 MEDIA_LOG_E("GetSegmentDownloader failed when Read, streamId " PUBLIC_LOG_D32, readDataInfo.streamId_);
100 return Status::END_OF_STREAM;
101 }
102
103 DashReadRet ret = segmentDownloader->Read(buff, readDataInfo, isInterruptNeeded_);
104 MEDIA_LOG_D("Read:streamId " PUBLIC_LOG_D32 " readRet:" PUBLIC_LOG_D32, readDataInfo.streamId_, ret);
105 if (ret == DASH_READ_END) {
106 MEDIA_LOG_I("Read:streamId " PUBLIC_LOG_D32 " segment all finished end", readDataInfo.streamId_);
107 readDataInfo.isEos_ = true;
108 if (callback_ != nullptr) {
109 callback_->OnEvent({PluginEventType::BUFFERING_END, {BufferingInfoType::BUFFERING_END}, "end"});
110 }
111 return Status::END_OF_STREAM;
112 } else if (ret == DASH_READ_AGAIN) {
113 return Status::ERROR_AGAIN;
114 } else if (ret == DASH_READ_FAILED || ret == DASH_READ_INTERRUPT) {
115 return Status::END_OF_STREAM;
116 }
117 return Status::OK;
118 }
119
GetSegmentDownloader(int32_t streamId)120 std::shared_ptr<DashSegmentDownloader> DashMediaDownloader::GetSegmentDownloader(int32_t streamId)
121 {
122 std::shared_ptr<DashSegmentDownloader> segmentDownloader = nullptr;
123 std::shared_ptr<DashStreamDescription> streamDescription = mpdDownloader_->GetStreamByStreamId(streamId);
124 if (streamDescription == nullptr) {
125 MEDIA_LOG_E("stream " PUBLIC_LOG_D32 " not exist", streamId);
126 return segmentDownloader;
127 }
128 return GetSegmentDownloaderByType(streamDescription->type_);
129 }
130
GetSegmentDownloaderByType(MediaAVCodec::MediaType type) const131 std::shared_ptr<DashSegmentDownloader> DashMediaDownloader::GetSegmentDownloaderByType(
132 MediaAVCodec::MediaType type) const
133 {
134 std::shared_ptr<DashSegmentDownloader> segmentDownloader = nullptr;
135 auto iter = std::find_if(segmentDownloaders_.begin(), segmentDownloaders_.end(),
136 [&](const std::shared_ptr<DashSegmentDownloader> &downloader) {
137 return downloader->GetStreamType() == type;
138 });
139 if (iter != segmentDownloaders_.end()) {
140 segmentDownloader = *iter;
141 }
142 return segmentDownloader;
143 }
144
UpdateDownloadFinished(int streamId)145 void DashMediaDownloader::UpdateDownloadFinished(int streamId)
146 {
147 MEDIA_LOG_I("UpdateDownloadFinished: " PUBLIC_LOG_D32, streamId);
148 std::shared_ptr<DashStreamDescription> streamDesc = mpdDownloader_->GetStreamByStreamId(streamId);
149 if (streamDesc == nullptr) {
150 MEDIA_LOG_E("UpdateDownloadFinished get stream null id: " PUBLIC_LOG_D32, streamId);
151 return;
152 }
153
154 if (streamDesc->type_ == MediaAVCodec::MediaType::MEDIA_TYPE_VID) {
155 VideoSegmentDownloadFinished(streamId);
156 return;
157 }
158
159 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloader(streamId);
160 if (segmentDownloader == nullptr) {
161 MEDIA_LOG_E("GetSegmentDownloader failed when UpdateDownloadFinished, streamId " PUBLIC_LOG_D32, streamId);
162 return;
163 }
164
165 std::shared_ptr<DashSegment> seg;
166 DashMpdGetRet getRet = mpdDownloader_->GetNextSegmentByStreamId(streamId, seg);
167 MEDIA_LOG_I("GetNextSegmentByStreamId " PUBLIC_LOG_D32 ", ret=" PUBLIC_LOG_D32, streamId, getRet);
168 if (seg != nullptr) {
169 segmentDownloader->Open(seg);
170 } else if (getRet == DASH_MPD_GET_FINISH) {
171 segmentDownloader->SetAllSegmentFinished();
172 }
173 }
174
SeekToTime(int64_t seekTime,SeekMode mode)175 bool DashMediaDownloader::SeekToTime(int64_t seekTime, SeekMode mode)
176 {
177 MEDIA_LOG_I("DashMediaDownloader SeekToTime: " PUBLIC_LOG_D64, seekTime);
178 SeekToTs(seekTime);
179 return true;
180 }
181
GetContentLength() const182 size_t DashMediaDownloader::GetContentLength() const
183 {
184 return 0;
185 }
186
GetDuration() const187 int64_t DashMediaDownloader::GetDuration() const
188 {
189 MEDIA_LOG_I("DashMediaDownloader GetDuration " PUBLIC_LOG_D64, mpdDownloader_->GetDuration());
190 return mpdDownloader_->GetDuration();
191 }
192
GetSeekable() const193 Seekable DashMediaDownloader::GetSeekable() const
194 {
195 MEDIA_LOG_I("DashMediaDownloader GetSeekable begin");
196 Seekable value = mpdDownloader_->GetSeekable();
197 if (value == Seekable::INVALID) {
198 return value;
199 }
200
201 size_t times = 0;
202 bool status = false;
203 while (!status && times < RETRY_TIMES && !isInterruptNeeded_) {
204 for (auto downloader : segmentDownloaders_) {
205 status = downloader->GetStartedStatus();
206 if (!status) {
207 break;
208 }
209 }
210 OSAL::SleepFor(SLEEP_TIME);
211 times++;
212 }
213
214 if (times >= RETRY_TIMES || isInterruptNeeded_) {
215 MEDIA_LOG_I("DashMediaDownloader GetSeekable INVALID");
216 return Seekable::INVALID;
217 }
218
219 MEDIA_LOG_I("DashMediaDownloader GetSeekable end");
220 return value;
221 }
222
SetCallback(Callback * cb)223 void DashMediaDownloader::SetCallback(Callback* cb)
224 {
225 callback_ = cb;
226 }
227
GetStartedStatus()228 bool DashMediaDownloader::GetStartedStatus()
229 {
230 return true;
231 }
232
SetStatusCallback(StatusCallbackFunc cb)233 void DashMediaDownloader::SetStatusCallback(StatusCallbackFunc cb)
234 {
235 statusCallback_ = cb;
236 mpdDownloader_->SetStatusCallback(cb);
237 }
238
GetBitRates()239 std::vector<uint32_t> DashMediaDownloader::GetBitRates()
240 {
241 return mpdDownloader_->GetBitRates();
242 }
243
SelectBitRate(uint32_t bitrate)244 bool DashMediaDownloader::SelectBitRate(uint32_t bitrate)
245 {
246 std::lock_guard<std::mutex> sidxLock(parseSidxMutex_);
247 MEDIA_LOG_I("Dash SelectBitRate bitrate:" PUBLIC_LOG_U32, bitrate);
248 {
249 isAutoSelectBitrate_ = false;
250
251 std::lock_guard<std::mutex> lock(switchMutex_);
252 // The bit rate is being switched. Wait until the sidx download and parsing are complete.
253 if (bitrateParam_.waitSidxFinish_ ||
254 trackParam_.waitSidxFinish_) {
255 // Save the target stream information and update the downloaded stream information
256 // when the callback indicating that the sidx parsing is complete is received.
257 MEDIA_LOG_I("wait last switch bitrate or track:" PUBLIC_LOG_U32 " sidx parse finish, switch type:"
258 PUBLIC_LOG_D32, bitrateParam_.bitrate_, (int) bitrateParam_.type_);
259 preparedAction_.preparedBitrateParam_.bitrate_ = bitrate;
260 preparedAction_.preparedBitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_SMOOTH;
261 return true;
262 }
263
264 bitrateParam_.bitrate_ = bitrate;
265 bitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_SMOOTH;
266 bitrateParam_.waitSidxFinish_ = true;
267 }
268
269 int64_t remainLastNumberSeq = -1;
270 bool bufferCleanFlag = true;
271 CleanVideoSegmentBuffer(bufferCleanFlag, remainLastNumberSeq);
272
273 return SelectBitrateInternal(bufferCleanFlag, remainLastNumberSeq);
274 }
275
SelectStream(int32_t streamId)276 Status DashMediaDownloader::SelectStream(int32_t streamId)
277 {
278 MEDIA_LOG_I("Dash SelectStream streamId:" PUBLIC_LOG_D32, streamId);
279 std::shared_ptr<DashStreamDescription> streamDesc = mpdDownloader_->GetStreamByStreamId(streamId);
280 if (streamDesc == nullptr) {
281 MEDIA_LOG_W("Dash SelectStream can not find streamId");
282 return Status::ERROR_INVALID_PARAMETER;
283 }
284
285 if (streamDesc->type_ == MediaAVCodec::MediaType::MEDIA_TYPE_AUD) {
286 return SelectAudio(streamDesc);
287 } else if (streamDesc->type_ == MediaAVCodec::MediaType::MEDIA_TYPE_SUBTITLE) {
288 return SelectSubtitle(streamDesc);
289 } else {
290 SelectBitRate(streamDesc->bandwidth_);
291 return Status::OK;
292 }
293 }
294
SeekToTs(int64_t seekTime)295 void DashMediaDownloader::SeekToTs(int64_t seekTime)
296 {
297 int64_t seekTimeMs;
298 std::lock_guard<std::mutex> lock(parseSidxMutex_);
299 {
300 if (seekTime < 0 || seekTime > mpdDownloader_->GetDuration()) {
301 return;
302 }
303 seekTimeMs = seekTime / MS_2_NS;
304 if (preparedAction_.seekPosition_ != -1 ||
305 bitrateParam_.waitSidxFinish_ ||
306 trackParam_.waitSidxFinish_) {
307 preparedAction_.seekPosition_ = seekTimeMs;
308 MEDIA_LOG_I("SeekToTs:" PUBLIC_LOG_D64 ", wait sidx finish, bitrate:" PUBLIC_LOG_U32 ", type:"
309 PUBLIC_LOG_D32, preparedAction_.seekPosition_, bitrateParam_.bitrate_, (int) bitrateParam_.type_);
310
311 for (auto &segmentDownloader : segmentDownloaders_) {
312 MEDIA_LOG_I("Dash clean streamId: " PUBLIC_LOG_D32, segmentDownloader->GetStreamId());
313 int64_t remainLastNumberSeq = -1;
314 segmentDownloader->CleanSegmentBuffer(true, remainLastNumberSeq);
315 }
316
317 return;
318 }
319 }
320
321 SeekInternal(seekTimeMs);
322 }
323
SetIsTriggerAutoMode(bool isAuto)324 void DashMediaDownloader::SetIsTriggerAutoMode(bool isAuto)
325 {
326 isAutoSelectBitrate_ = isAuto;
327 }
328
SetDownloadErrorState()329 void DashMediaDownloader::SetDownloadErrorState()
330 {
331 MEDIA_LOG_I("Dash SetDownloadErrorState");
332 if (callback_) {
333 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "download"});
334 }
335 downloadErrorState_ = true;
336 }
337
SetPlayStrategy(const std::shared_ptr<PlayStrategy> & playStrategy)338 void DashMediaDownloader::SetPlayStrategy(const std::shared_ptr<PlayStrategy>& playStrategy)
339 {
340 if (playStrategy != nullptr) {
341 mpdDownloader_->SetHdrStart(playStrategy->preferHDR);
342 mpdDownloader_->SetInitResolution(playStrategy->width, playStrategy->height);
343 mpdDownloader_->SetDefaultLang(playStrategy->audioLanguage, MediaAVCodec::MediaType::MEDIA_TYPE_AUD);
344 mpdDownloader_->SetDefaultLang(playStrategy->subtitleLanguage, MediaAVCodec::MediaType::MEDIA_TYPE_SUBTITLE);
345 expectDuration_ = static_cast<uint64_t>(playStrategy->duration);
346 }
347 }
348
GetStreamInfo(std::vector<StreamInfo> & streams)349 Status DashMediaDownloader::GetStreamInfo(std::vector<StreamInfo>& streams)
350 {
351 GetSeekable();
352 return mpdDownloader_->GetStreamInfo(streams);
353 }
354
OnMpdInfoUpdate(DashMpdEvent mpdEvent)355 void DashMediaDownloader::OnMpdInfoUpdate(DashMpdEvent mpdEvent)
356 {
357 switch (mpdEvent) {
358 case DASH_MPD_EVENT_STREAM_INIT:
359 ReceiveMpdStreamInitEvent();
360 break;
361 case DASH_MPD_EVENT_PARSE_OK:
362 ReceiveMpdParseOkEvent();
363 break;
364 default:
365 break;
366 }
367 }
368
ReceiveMpdStreamInitEvent()369 void DashMediaDownloader::ReceiveMpdStreamInitEvent()
370 {
371 MEDIA_LOG_I("Dash ReceiveMpdStreamInitEvent");
372 std::vector<StreamInfo> streams;
373 mpdDownloader_->GetStreamInfo(streams);
374 std::shared_ptr<DashStreamDescription> streamDesc = nullptr;
375 for (unsigned int index = 0; index < streams.size(); index++) {
376 streamDesc = mpdDownloader_->GetStreamByStreamId(streams[index].streamId);
377 if (streamDesc != nullptr && streamDesc->inUse_) {
378 std::shared_ptr<DashSegment> seg = nullptr;
379 if (breakpoint_ > 0) {
380 mpdDownloader_->GetBreakPointSegment(streamDesc->streamId_, breakpoint_, seg);
381 } else {
382 mpdDownloader_->GetNextSegmentByStreamId(streamDesc->streamId_, seg);
383 }
384
385 if (seg == nullptr) {
386 MEDIA_LOG_W("Dash get segment null in streamId " PUBLIC_LOG_D32, streamDesc->streamId_);
387 continue;
388 }
389
390 OpenInitSegment(streamDesc, seg);
391 }
392 }
393 }
394
OpenInitSegment(const std::shared_ptr<DashStreamDescription> & streamDesc,const std::shared_ptr<DashSegment> & seg)395 void DashMediaDownloader::OpenInitSegment(
396 const std::shared_ptr<DashStreamDescription> &streamDesc, const std::shared_ptr<DashSegment> &seg)
397 {
398 std::shared_ptr<DashSegmentDownloader> downloader = std::make_shared<DashSegmentDownloader>(
399 callback_, streamDesc->streamId_, streamDesc->type_, expectDuration_);
400 if (statusCallback_ != nullptr) {
401 downloader->SetStatusCallback(statusCallback_);
402 }
403 auto doneCallback = [this] (int streamId) {
404 UpdateDownloadFinished(streamId);
405 };
406 downloader->SetDownloadDoneCallback(doneCallback);
407 segmentDownloaders_.push_back(downloader);
408 std::shared_ptr<DashInitSegment> initSeg = mpdDownloader_->GetInitSegmentByStreamId(
409 streamDesc->streamId_);
410 if (initSeg != nullptr) {
411 downloader->SetInitSegment(initSeg);
412 }
413 downloader->Open(seg);
414 MEDIA_LOG_I("dash first get segment in streamId " PUBLIC_LOG_D32 ", type "
415 PUBLIC_LOG_D32, streamDesc->streamId_, streamDesc->type_);
416 }
417
ReceiveMpdParseOkEvent()418 void DashMediaDownloader::ReceiveMpdParseOkEvent()
419 {
420 MEDIA_LOG_I("Dash ReceiveMpdParseOkEvent");
421 int streamId = -1;
422 {
423 std::lock_guard<std::mutex> lock(parseSidxMutex_);
424 if (bitrateParam_.waitSidxFinish_ ||
425 trackParam_.waitSidxFinish_) {
426 UpdateSegmentIndexAfterSidxParseOk();
427
428 if (DoPreparedAction(streamId)) {
429 MEDIA_LOG_I("Dash DoPreparedAction, no need download segment");
430 return;
431 }
432 } else {
433 MEDIA_LOG_I("switch type: " PUBLIC_LOG_D32 " or waitSidxFinish: "
434 PUBLIC_LOG_D32 " is error ", bitrateParam_.waitSidxFinish_, bitrateParam_.type_);
435 return;
436 }
437 }
438
439 GetSegmentToDownload(streamId, true);
440 }
441
VideoSegmentDownloadFinished(int streamId)442 void DashMediaDownloader::VideoSegmentDownloadFinished(int streamId)
443 {
444 MEDIA_LOG_I("VideoSegmentDownloadFinished streamId:" PUBLIC_LOG_D32 ", type:"
445 PUBLIC_LOG_U32, streamId, bitrateParam_.type_);
446 int downloadStreamId = streamId;
447 {
448 std::lock_guard<std::mutex> lock(switchMutex_);
449 if (bitrateParam_.type_ != DASH_MPD_SWITCH_TYPE_NONE) {
450 // no need to auto switch
451 if (bitrateParam_.waitSegmentFinish_) {
452 bitrateParam_.waitSegmentFinish_ = false;
453 } else {
454 MEDIA_LOG_I("old segment download finish, should get next segment in select bitrate");
455 return;
456 }
457
458 if (bitrateParam_.waitSidxFinish_) {
459 MEDIA_LOG_I("wait sidx download finish, should not get next segment");
460 return;
461 }
462
463 downloadStreamId = bitrateParam_.streamId_;
464 ResetBitrateParam();
465 } else {
466 // auto switch
467 bool switchFlag = true;
468 if (callback_ != nullptr) {
469 switchFlag = callback_->CanAutoSelectBitRate();
470 }
471 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloaderByType(
472 MediaAVCodec::MediaType::MEDIA_TYPE_VID);
473 if (segmentDownloader != nullptr && !segmentDownloader->IsAllSegmentFinished() &&
474 switchFlag && isAutoSelectBitrate_) {
475 bool flag = CheckAutoSelectBitrate(streamId);
476 if (callback_ != nullptr) {
477 callback_->SetSelectBitRateFlag(flag, bitrateParam_.bitrate_);
478 }
479 if (flag) {
480 // switch success
481 return;
482 }
483 }
484 }
485 }
486
487 GetSegmentToDownload(downloadStreamId, downloadStreamId != streamId);
488 }
489
GetSegmentToDownload(int downloadStreamId,bool streamSwitchFlag)490 void DashMediaDownloader::GetSegmentToDownload(int downloadStreamId, bool streamSwitchFlag)
491 {
492 MEDIA_LOG_I("GetSegmentToDownload streamId: " PUBLIC_LOG_D32 ", streamSwitchFlag: "
493 PUBLIC_LOG_D32, downloadStreamId, streamSwitchFlag);
494 // segment list is ok and no segment is downloading in segmentDownloader, so get next segment to download
495 std::shared_ptr<DashSegment> segment = nullptr;
496 DashMpdGetRet ret = mpdDownloader_->GetNextSegmentByStreamId(downloadStreamId, segment);
497 if (ret == DASH_MPD_GET_ERROR) {
498 return;
499 }
500
501 std::shared_ptr<DashStreamDescription> stream = mpdDownloader_->GetStreamByStreamId(downloadStreamId);
502 if (stream == nullptr) {
503 MEDIA_LOG_E("GetSegmentToDownload streamId: " PUBLIC_LOG_D32 " get stream is null", downloadStreamId);
504 return;
505 }
506
507 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloaderByType(stream->type_);
508 if (segmentDownloader == nullptr) {
509 return;
510 }
511
512 if (streamSwitchFlag) {
513 MEDIA_LOG_I("switch stream update streamId from " PUBLIC_LOG_D32 " to "
514 PUBLIC_LOG_D32, segmentDownloader->GetStreamId(), downloadStreamId);
515 segmentDownloader->UpdateStreamId(downloadStreamId);
516
517 std::shared_ptr<DashInitSegment> initSeg = mpdDownloader_->GetInitSegmentByStreamId(downloadStreamId);
518 if (initSeg != nullptr) {
519 segmentDownloader->SetInitSegment(initSeg);
520 }
521 }
522
523 if (segment != nullptr) {
524 segmentDownloader->Open(segment);
525 } else if (ret == DASH_MPD_GET_FINISH) {
526 segmentDownloader->SetAllSegmentFinished();
527 }
528 }
529
CleanVideoSegmentBuffer(bool & bufferCleanFlag,int64_t & remainLastNumberSeq)530 void DashMediaDownloader::CleanVideoSegmentBuffer(bool &bufferCleanFlag, int64_t &remainLastNumberSeq)
531 {
532 std::shared_ptr<DashSegmentDownloader> segmentDownloader;
533 auto iter = std::find_if(segmentDownloaders_.begin(), segmentDownloaders_.end(),
534 [&](const std::shared_ptr<DashSegmentDownloader> &downloader) {
535 return downloader->GetStreamType() == MediaAVCodec::MEDIA_TYPE_VID;
536 });
537 if (iter != segmentDownloaders_.end()) {
538 segmentDownloader = *iter;
539 }
540
541 if (segmentDownloader == nullptr) {
542 MEDIA_LOG_W("Dash not start, can not SelectBitRate.");
543 return;
544 }
545
546 remainLastNumberSeq = -1;
547 bufferCleanFlag = true;
548 // 1. clean segment buffer, get switch segment sequence. segment is in downloading or no segment buffer
549 if (!segmentDownloader->CleanSegmentBuffer(false, remainLastNumberSeq) &&
550 !segmentDownloader->IsSegmentFinish()) {
551 MEDIA_LOG_I("Dash SelectBitRate no need clean buffer, wait current segment download finish");
552 bufferCleanFlag = false;
553 }
554 }
555
SelectBitrateInternal(bool bufferCleanFlag,int64_t remainLastNumberSeq)556 bool DashMediaDownloader::SelectBitrateInternal(bool bufferCleanFlag, int64_t remainLastNumberSeq)
557 {
558 std::lock_guard<std::mutex> lock(switchMutex_);
559 MEDIA_LOG_I("Dash SelectBitrateInternal remainLastNumberSeq:" PUBLIC_LOG_D64, remainLastNumberSeq);
560
561 // 2. switch to destination bitrate
562 bitrateParam_.position_ = remainLastNumberSeq; // update by segment sequence, -1 means no segment downloading
563
564 if (!bufferCleanFlag) {
565 bitrateParam_.waitSegmentFinish_ = true;
566 } else {
567 bitrateParam_.waitSegmentFinish_ = false;
568 }
569
570 DashMpdGetRet ret = mpdDownloader_->GetNextVideoStream(bitrateParam_, bitrateParam_.streamId_);
571 if (ret == DASH_MPD_GET_ERROR) {
572 MEDIA_LOG_W("Dash SelectBitRate Stream:" PUBLIC_LOG_D32 " GetNextVideoStream failed.", bitrateParam_.streamId_);
573 return false;
574 }
575
576 if (ret == DASH_MPD_GET_UNDONE) {
577 bitrateParam_.waitSidxFinish_ = true;
578 MEDIA_LOG_I("Dash SelectBitRate wait sidx finish");
579 return true;
580 } else {
581 bitrateParam_.waitSidxFinish_ = false;
582 }
583
584 if (bitrateParam_.waitSegmentFinish_) {
585 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloaderByType(
586 MediaAVCodec::MediaType::MEDIA_TYPE_VID);
587 if (segmentDownloader == nullptr) {
588 MEDIA_LOG_W("SelectBitrateInternal can not get segmentDownloader.");
589 return false;
590 }
591
592 if (!segmentDownloader->IsSegmentFinish()) {
593 return true;
594 }
595
596 // old segment download finish, should get next segment
597 bitrateParam_.waitSegmentFinish_ = false;
598 }
599
600 // 3. get dest segment and download
601 bitrateParam_.bitrate_ = 0;
602 bitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_NONE;
603 GetSegmentToDownload(bitrateParam_.streamId_, true);
604 return true;
605 }
606
CheckAutoSelectBitrate(int streamId)607 bool DashMediaDownloader::CheckAutoSelectBitrate(int streamId)
608 {
609 MEDIA_LOG_I("AutoSelectBitrate streamId: " PUBLIC_LOG_D32, streamId);
610 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloaderByType(
611 MediaAVCodec::MediaType::MEDIA_TYPE_VID);
612 if (segmentDownloader == nullptr) {
613 MEDIA_LOG_W("AutoSelectBitrate can not get segmentDownloader.");
614 return false;
615 }
616 uint32_t desBitrate = GetNextBitrate(segmentDownloader);
617 if (desBitrate == 0) {
618 return false;
619 }
620 return AutoSelectBitrateInternal(desBitrate);
621 }
622
GetNextBitrate(std::shared_ptr<DashSegmentDownloader> segmentDownloader)623 uint32_t DashMediaDownloader::GetNextBitrate(std::shared_ptr<DashSegmentDownloader> segmentDownloader)
624 {
625 std::shared_ptr<DashStreamDescription> stream = mpdDownloader_->GetUsingStreamByType(
626 MediaAVCodec::MediaType::MEDIA_TYPE_VID);
627 if (stream == nullptr) {
628 return 0;
629 }
630
631 if (stream->videoType_ != DASH_VIDEO_TYPE_SDR) {
632 MEDIA_LOG_I("hdr stream no need to switch auto");
633 return 0;
634 }
635
636 std::vector<uint32_t> bitRates = mpdDownloader_->GetBitRatesByHdr(stream->videoType_ != DASH_VIDEO_TYPE_SDR);
637 if (bitRates.size() == 0) {
638 return 0;
639 }
640 uint32_t curBitrate = stream->bandwidth_;
641 uint64_t downloadSpeed = static_cast<uint64_t>(segmentDownloader->GetDownloadSpeed());
642 if (downloadSpeed == 0) {
643 return 0;
644 }
645 uint32_t desBitrate = GetDesBitrate(bitRates, downloadSpeed);
646 if (curBitrate == desBitrate) {
647 return 0;
648 }
649 uint32_t bufferLowSize =
650 static_cast<uint32_t>(static_cast<double>(curBitrate) / BYTE_TO_BIT * BUFFER_LOW_LIMIT);
651 // switch to high bitrate,if buffersize less than lowsize, do not switch
652 if (curBitrate < desBitrate && segmentDownloader->GetBufferSize() < bufferLowSize) {
653 MEDIA_LOG_I("AutoSelectBitrate curBitrate " PUBLIC_LOG_D32 ", desBitRate " PUBLIC_LOG_D32
654 ", bufferLowSize " PUBLIC_LOG_D32, curBitrate, desBitrate, bufferLowSize);
655 return 0;
656 }
657 // high size: buffersize * 0.8
658 uint32_t bufferHighSize = segmentDownloader->GetRingBufferCapacity() * BUFFER_LIMIT_FACT;
659 // switch to low bitrate, if buffersize more than highsize, do not switch
660 if (curBitrate > desBitrate && segmentDownloader->GetBufferSize() > bufferHighSize) {
661 MEDIA_LOG_I("AutoSelectBitrate curBitrate " PUBLIC_LOG_D32 ", desBitRate " PUBLIC_LOG_D32
662 ", bufferHighSize " PUBLIC_LOG_D32, curBitrate, desBitrate, bufferHighSize);
663 return 0;
664 }
665 return desBitrate;
666 }
667
AutoSelectBitrateInternal(uint32_t bitrate)668 bool DashMediaDownloader::AutoSelectBitrateInternal(uint32_t bitrate)
669 {
670 bitrateParam_.position_ = -1;
671 bitrateParam_.bitrate_ = bitrate;
672 bitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_AUTO;
673 if (mpdDownloader_ == nullptr) {
674 return false;
675 }
676 DashMpdGetRet ret = mpdDownloader_->GetNextVideoStream(bitrateParam_, bitrateParam_.streamId_);
677 if (ret == DASH_MPD_GET_ERROR) {
678 return false;
679 }
680 if (ret == DASH_MPD_GET_UNDONE) {
681 bitrateParam_.waitSidxFinish_ = true;
682 return true;
683 }
684 bitrateParam_.bitrate_ = bitrate;
685 bitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_NONE;
686 GetSegmentToDownload(bitrateParam_.streamId_, true);
687 return true;
688 }
689
IsSeekingInSwitch()690 bool DashMediaDownloader::IsSeekingInSwitch()
691 {
692 std::lock_guard<std::mutex> lock(switchMutex_);
693 bool isSwitching = false;
694 if (bitrateParam_.type_ != DASH_MPD_SWITCH_TYPE_NONE) {
695 MEDIA_LOG_I("IsSeekingInSwitch streamId:" PUBLIC_LOG_D32 ", switching bitrate:"
696 PUBLIC_LOG_U32 ", type:" PUBLIC_LOG_D32, bitrateParam_.streamId_, bitrateParam_.bitrate_,
697 (int) bitrateParam_.type_);
698 int streamId = bitrateParam_.streamId_;
699 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloaderByType(
700 MediaAVCodec::MediaType::MEDIA_TYPE_VID);
701 if (segmentDownloader != nullptr && segmentDownloader->GetStreamId() != streamId) {
702 segmentDownloader->UpdateStreamId(streamId);
703 }
704
705 ResetBitrateParam();
706 isSwitching = true;
707 }
708
709 if (trackParam_.waitSidxFinish_) {
710 MEDIA_LOG_I("IsSeekingInSwitch track streamId:" PUBLIC_LOG_D32 ", waitSidxFinish_:"
711 PUBLIC_LOG_D32, trackParam_.streamId_, trackParam_.waitSidxFinish_);
712 int streamId = trackParam_.streamId_;
713 std::shared_ptr<DashStreamDescription> streamDesc = mpdDownloader_->GetStreamByStreamId(streamId);
714 if (streamDesc != nullptr) {
715 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloaderByType(streamDesc->type_);
716 if (segmentDownloader != nullptr && segmentDownloader->GetStreamId() != streamId) {
717 segmentDownloader->UpdateStreamId(streamId);
718 }
719 ResetTrackParam();
720 isSwitching = true;
721 }
722 }
723
724 return isSwitching;
725 }
726
HandleSeekReady(int32_t streamType,int32_t streamId,int32_t isEos)727 void DashMediaDownloader::HandleSeekReady(int32_t streamType, int32_t streamId, int32_t isEos)
728 {
729 Format seekReadyInfo {};
730 seekReadyInfo.PutIntValue("currentStreamType", streamType);
731 seekReadyInfo.PutIntValue("currentStreamId", streamId);
732 seekReadyInfo.PutIntValue("isEOS", isEos);
733 MEDIA_LOG_D("StreamType: " PUBLIC_LOG_D32 " StreamId: " PUBLIC_LOG_D32 " isEOS: " PUBLIC_LOG_D32,
734 streamType, streamId, isEos);
735 if (callback_ != nullptr) {
736 MEDIA_LOG_D("Onevent dash seek ready");
737 callback_->OnEvent({PluginEventType::DASH_SEEK_READY, seekReadyInfo, "dash_seek_ready"});
738 }
739 }
740
SeekInternal(int64_t seekTimeMs)741 void DashMediaDownloader::SeekInternal(int64_t seekTimeMs)
742 {
743 bool isSwitching = IsSeekingInSwitch();
744
745 for (auto &segmentDownloader : segmentDownloaders_) {
746 std::shared_ptr<DashSegment> segment;
747 int32_t streamId = static_cast<int32_t>(segmentDownloader->GetStreamId());
748 mpdDownloader_->SeekToTs(segmentDownloader->GetStreamId(), seekTimeMs, segment);
749 if (segment == nullptr) {
750 MEDIA_LOG_I("Dash SeekToTs end streamId " PUBLIC_LOG_D32 ", type " PUBLIC_LOG_D32,
751 segmentDownloader->GetStreamId(), segmentDownloader->GetStreamType());
752 int64_t remainLastNumberSeq = -1;
753 segmentDownloader->CleanSegmentBuffer(true, remainLastNumberSeq);
754 segmentDownloader->SetAllSegmentFinished();
755 HandleSeekReady(static_cast<int32_t>(segmentDownloader->GetStreamType()), streamId, 1);
756 continue;
757 }
758
759 MEDIA_LOG_D("Dash SeekToTs segment " PUBLIC_LOG_D64 ", duration:"
760 PUBLIC_LOG_U32, segment->numberSeq_, segment->duration_);
761 std::shared_ptr<DashInitSegment> initSeg = mpdDownloader_->GetInitSegmentByStreamId(
762 segmentDownloader->GetStreamId());
763 if (!isSwitching && segmentDownloader->SeekToTime(segment, streamId)) {
764 MEDIA_LOG_I("Dash SeekToTs of buffered streamId " PUBLIC_LOG_D32 ", type " PUBLIC_LOG_D32,
765 segmentDownloader->GetStreamId(), segmentDownloader->GetStreamType());
766 segmentDownloader->SetInitSegment(initSeg, true);
767 } else {
768 int64_t remainLastNumberSeq = -1;
769 segmentDownloader->CleanSegmentBuffer(true, remainLastNumberSeq);
770 mpdDownloader_->SetCurrentNumberSeqByStreamId(segmentDownloader->GetStreamId(), segment->numberSeq_);
771 segmentDownloader->SetInitSegment(initSeg, true);
772 segmentDownloader->Open(segment);
773 }
774 HandleSeekReady(static_cast<int32_t>(segmentDownloader->GetStreamType()), streamId, 0);
775 }
776 }
777
SelectAudio(const std::shared_ptr<DashStreamDescription> & streamDesc)778 Status DashMediaDownloader::SelectAudio(const std::shared_ptr<DashStreamDescription> &streamDesc)
779 {
780 std::lock_guard<std::mutex> lock(parseSidxMutex_);
781 // stream track is being switched. Wait until the sidx download and parsing are complete.
782 if (bitrateParam_.waitSidxFinish_ ||
783 trackParam_.waitSidxFinish_) {
784 MEDIA_LOG_I("last bitrate switch: " PUBLIC_LOG_D32 " last track switch:"
785 PUBLIC_LOG_D32, bitrateParam_.waitSidxFinish_, trackParam_.waitSidxFinish_);
786 preparedAction_.preparedAudioParam_.streamId_ = streamDesc->streamId_;
787 return Status::OK;
788 }
789 return SelectAudioInternal(streamDesc);
790 }
791
SelectAudioInternal(const std::shared_ptr<DashStreamDescription> & streamDesc)792 Status DashMediaDownloader::SelectAudioInternal(const std::shared_ptr<DashStreamDescription> &streamDesc)
793 {
794 MEDIA_LOG_I("SelectAudioInternal Stream:" PUBLIC_LOG_D32, streamDesc->streamId_);
795 std::shared_ptr<DashSegmentDownloader> downloader = GetSegmentDownloaderByType(streamDesc->type_);
796 if (downloader == nullptr) {
797 return Status::ERROR_UNKNOWN;
798 }
799
800 int64_t remainLastNumberSeq = -1;
801 bool isEnd = false;
802
803 // 1. clean segment buffer keep 1000 ms, get switch segment sequence and is segment receive finish flag.
804 downloader->CleanBufferByTime(remainLastNumberSeq, isEnd);
805
806 std::lock_guard<std::mutex> lock(switchMutex_);
807 // 2. switch to destination stream
808 trackParam_.isEnd_ = isEnd;
809 trackParam_.type_ = MediaAVCodec::MediaType::MEDIA_TYPE_AUD;
810 trackParam_.streamId_ = streamDesc->streamId_;
811 trackParam_.position_ = remainLastNumberSeq; // update by segment sequence, -1 means no segment downloading
812
813 DashMpdGetRet ret = mpdDownloader_->GetNextTrackStream(trackParam_);
814 if (ret == DASH_MPD_GET_ERROR) {
815 MEDIA_LOG_W("Dash SelectAudio Stream:" PUBLIC_LOG_D32 " failed.", trackParam_.streamId_);
816 return Status::ERROR_UNKNOWN;
817 }
818
819 if (ret == DASH_MPD_GET_UNDONE) {
820 trackParam_.waitSidxFinish_ = true;
821 MEDIA_LOG_I("Dash SelectAudio wait sidx finish");
822 return Status::OK;
823 }
824
825 // 3. get dest segment and download
826 GetSegmentToDownload(trackParam_.streamId_, true);
827 ResetTrackParam();
828 return Status::OK;
829 }
830
SelectSubtitle(const std::shared_ptr<DashStreamDescription> & streamDesc)831 Status DashMediaDownloader::SelectSubtitle(const std::shared_ptr<DashStreamDescription> &streamDesc)
832 {
833 std::lock_guard<std::mutex> lock(parseSidxMutex_);
834 // stream track is being switched. Wait until the sidx download and parsing are complete.
835 if (bitrateParam_.waitSidxFinish_ ||
836 trackParam_.waitSidxFinish_) {
837 MEDIA_LOG_I("last bitrate switch: " PUBLIC_LOG_D32 " last track switch:"
838 PUBLIC_LOG_D32, bitrateParam_.waitSidxFinish_, trackParam_.waitSidxFinish_);
839 preparedAction_.preparedSubtitleParam_.streamId_ = streamDesc->streamId_;
840 return Status::OK;
841 }
842 return SelectSubtitleInternal(streamDesc);
843 }
844
SelectSubtitleInternal(const std::shared_ptr<DashStreamDescription> & streamDesc)845 Status DashMediaDownloader::SelectSubtitleInternal(const std::shared_ptr<DashStreamDescription> &streamDesc)
846 {
847 MEDIA_LOG_I("SelectSubtitleInternal Stream:" PUBLIC_LOG_D32, streamDesc->streamId_);
848 std::shared_ptr<DashSegmentDownloader> downloader = GetSegmentDownloaderByType(streamDesc->type_);
849 if (downloader == nullptr) {
850 return Status::ERROR_UNKNOWN;
851 }
852
853 int64_t remainLastNumberSeq = -1;
854
855 // 1. clean all segment buffer, get switch segment sequence and is segment receive finish flag.
856 downloader->CleanSegmentBuffer(true, remainLastNumberSeq);
857
858 std::lock_guard<std::mutex> lock(switchMutex_);
859 // 2. switch to destination stream
860 trackParam_.isEnd_ = false;
861 trackParam_.type_ = MediaAVCodec::MediaType::MEDIA_TYPE_SUBTITLE;
862 trackParam_.streamId_ = streamDesc->streamId_;
863 trackParam_.position_ = remainLastNumberSeq; // update by segment sequence, -1 means no segment downloading
864
865 DashMpdGetRet ret = mpdDownloader_->GetNextTrackStream(trackParam_);
866 if (ret == DASH_MPD_GET_ERROR) {
867 MEDIA_LOG_W("Dash SelectSubtitle Stream:" PUBLIC_LOG_D32 " failed.", trackParam_.streamId_);
868 return Status::ERROR_UNKNOWN;
869 }
870
871 if (ret == DASH_MPD_GET_UNDONE) {
872 trackParam_.waitSidxFinish_ = true;
873 MEDIA_LOG_I("Dash SelectSubtitle wait sidx finish");
874 return Status::OK;
875 }
876
877 // 3. get dest segment and download
878 GetSegmentToDownload(trackParam_.streamId_, true);
879 ResetTrackParam();
880 return Status::OK;
881 }
882
DoPreparedSwitchBitrate(bool switchBitrateOk,bool & needDownload,int & streamId)883 bool DashMediaDownloader::DoPreparedSwitchBitrate(bool switchBitrateOk, bool &needDownload, int &streamId)
884 {
885 bool needSwitchBitrate = false;
886 {
887 std::lock_guard<std::mutex> lock(switchMutex_);
888 if (switchBitrateOk) {
889 if (!bitrateParam_.waitSegmentFinish_) {
890 ResetBitrateParam();
891 } else {
892 bitrateParam_.waitSidxFinish_ = false;
893 // wait segment download finish, no need to download video segment
894 MEDIA_LOG_I("SwitchBitrate sidx ok and need wait segment finish");
895 needDownload = false;
896 }
897 } else {
898 ResetTrackParam();
899 }
900
901 if (preparedAction_.preparedBitrateParam_.type_ != DASH_MPD_SWITCH_TYPE_NONE) {
902 ResetBitrateParam();
903 needSwitchBitrate = true;
904 bitrateParam_.bitrate_ = preparedAction_.preparedBitrateParam_.bitrate_;
905 bitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_SMOOTH;
906 // keep wait sidx finish flag, avoid to reset bitrateParam after video segment download finish
907 bitrateParam_.waitSidxFinish_ = true;
908 preparedAction_.preparedBitrateParam_.bitrate_ = 0;
909 preparedAction_.preparedBitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_NONE;
910 }
911 }
912
913 if (needSwitchBitrate) {
914 int64_t remainLastNumberSeq = -1;
915 bool bufferCleanFlag = true;
916 CleanVideoSegmentBuffer(bufferCleanFlag, remainLastNumberSeq);
917 MEDIA_LOG_I("PreparedSwitchBitrate: " PUBLIC_LOG_U32, bitrateParam_.bitrate_);
918 return SelectBitrateInternal(bufferCleanFlag, remainLastNumberSeq);
919 }
920
921 return false;
922 }
923
DoPreparedSwitchAudio(int & streamId)924 bool DashMediaDownloader::DoPreparedSwitchAudio(int &streamId)
925 {
926 if (preparedAction_.preparedAudioParam_.streamId_ != -1) {
927 ResetTrackParam();
928 std::shared_ptr<DashStreamDescription> streamDesc =
929 mpdDownloader_->GetStreamByStreamId(preparedAction_.preparedAudioParam_.streamId_);
930 MEDIA_LOG_I("PreparedSwitchAudio id:" PUBLIC_LOG_D32, preparedAction_.preparedAudioParam_.streamId_);
931 preparedAction_.preparedAudioParam_.streamId_ = -1;
932 if (streamDesc != nullptr && SelectAudioInternal(streamDesc) == Status::OK) {
933 return true;
934 }
935 }
936
937 return false;
938 }
939
DoPreparedSwitchSubtitle(int & streamId)940 bool DashMediaDownloader::DoPreparedSwitchSubtitle(int &streamId)
941 {
942 if (preparedAction_.preparedSubtitleParam_.streamId_ != -1) {
943 ResetTrackParam();
944 std::shared_ptr<DashStreamDescription> streamDesc =
945 mpdDownloader_->GetStreamByStreamId(preparedAction_.preparedSubtitleParam_.streamId_);
946 MEDIA_LOG_I("PreparedSwitchSubtitle id:" PUBLIC_LOG_D32, preparedAction_.preparedSubtitleParam_.streamId_);
947 preparedAction_.preparedSubtitleParam_.streamId_ = -1;
948
949 if (streamDesc != nullptr && SelectSubtitleInternal(streamDesc) == Status::OK) {
950 return true;
951 }
952 }
953
954 return false;
955 }
956
DoPreparedSwitchAction(bool switchBitrateOk,bool switchAudioOk,bool switchSubtitleOk,int & streamId)957 bool DashMediaDownloader::DoPreparedSwitchAction(bool switchBitrateOk,
958 bool switchAudioOk, bool switchSubtitleOk, int &streamId)
959 {
960 bool segmentNeedDownload = true;
961 // first should check switch bitrate
962 if (DoPreparedSwitchBitrate(switchBitrateOk, segmentNeedDownload, streamId)) {
963 // previous action is switch bitrate, no need to get segment when do prepare switch bitrate
964 segmentNeedDownload = !switchBitrateOk;
965 if (bitrateParam_.type_ != DASH_MPD_SWITCH_TYPE_NONE && bitrateParam_.waitSidxFinish_) {
966 MEDIA_LOG_I("DoPreparedAction switch bitrate wait sidx finish:" PUBLIC_LOG_U32, bitrateParam_.bitrate_);
967 return switchBitrateOk;
968 }
969 }
970
971 if (DoPreparedSwitchAudio(streamId)) {
972 // previous action is switch audio, no need to get segment when do prepare switch audio
973 segmentNeedDownload = switchAudioOk ? false : segmentNeedDownload;
974 if (trackParam_.waitSidxFinish_) {
975 MEDIA_LOG_I("DoPreparedAction switch audio wait sidx finish:" PUBLIC_LOG_D32, trackParam_.streamId_);
976 return switchAudioOk ? true : !segmentNeedDownload;
977 }
978 }
979
980 if (DoPreparedSwitchSubtitle(streamId)) {
981 // previous action is switch subtitle, no need to get segment when do prepare switch subtitle
982 segmentNeedDownload = switchSubtitleOk ? false : segmentNeedDownload;
983 if (trackParam_.waitSidxFinish_) {
984 MEDIA_LOG_I("DoPreparedAction switch subtitle wait sidx finish:" PUBLIC_LOG_D32, trackParam_.streamId_);
985 return switchSubtitleOk ? true : !segmentNeedDownload;
986 }
987 }
988
989 int64_t seekPosition = -1;
990 if (preparedAction_.seekPosition_ != -1) {
991 seekPosition = preparedAction_.seekPosition_;
992 preparedAction_.seekPosition_ = -1;
993 }
994
995 if (seekPosition > -1) {
996 SeekInternal(seekPosition); // seek after switch ok
997 return true;
998 }
999
1000 return !segmentNeedDownload;
1001 }
1002
DoPreparedAction(int & streamId)1003 bool DashMediaDownloader::DoPreparedAction(int &streamId)
1004 {
1005 bool switchBitrateOk = bitrateParam_.waitSidxFinish_;
1006 bool switchAudioOk = (trackParam_.waitSidxFinish_ && trackParam_.type_ == MediaAVCodec::MediaType::MEDIA_TYPE_AUD);
1007 bool switchSubtitleOk =
1008 (trackParam_.waitSidxFinish_ && trackParam_.type_ == MediaAVCodec::MediaType::MEDIA_TYPE_SUBTITLE);
1009
1010 streamId = switchBitrateOk ? bitrateParam_.streamId_ : trackParam_.streamId_;
1011 return DoPreparedSwitchAction(switchBitrateOk, switchAudioOk, switchSubtitleOk, streamId);
1012 }
1013
UpdateSegmentIndexAfterSidxParseOk()1014 void DashMediaDownloader::UpdateSegmentIndexAfterSidxParseOk()
1015 {
1016 std::lock_guard<std::mutex> lock(switchMutex_);
1017 if (bitrateParam_.waitSidxFinish_ && bitrateParam_.nextSegTime_ > 0) {
1018 mpdDownloader_->UpdateCurrentNumberSeqByTime(mpdDownloader_->GetStreamByStreamId(bitrateParam_.streamId_),
1019 bitrateParam_.nextSegTime_);
1020 bitrateParam_.nextSegTime_ = 0;
1021 } else if (trackParam_.waitSidxFinish_ && trackParam_.nextSegTime_ > 0) {
1022 mpdDownloader_->UpdateCurrentNumberSeqByTime(mpdDownloader_->GetStreamByStreamId(trackParam_.streamId_),
1023 trackParam_.nextSegTime_);
1024 trackParam_.nextSegTime_ = 0;
1025 }
1026 }
1027
ResetBitrateParam()1028 void DashMediaDownloader::ResetBitrateParam()
1029 {
1030 bitrateParam_.bitrate_ = 0;
1031 bitrateParam_.type_ = DASH_MPD_SWITCH_TYPE_NONE;
1032 bitrateParam_.streamId_ = -1;
1033 bitrateParam_.position_ = -1;
1034 bitrateParam_.nextSegTime_ = 0;
1035 bitrateParam_.waitSegmentFinish_ = false;
1036 bitrateParam_.waitSidxFinish_ = false;
1037 }
1038
ResetTrackParam()1039 void DashMediaDownloader::ResetTrackParam()
1040 {
1041 trackParam_.waitSidxFinish_ = false;
1042 trackParam_.isEnd_ = false;
1043 trackParam_.streamId_ = -1;
1044 trackParam_.position_ = -1;
1045 trackParam_.nextSegTime_ = 0;
1046 }
1047
OnDrmInfoChanged(const std::multimap<std::string,std::vector<uint8_t>> & drmInfos)1048 void DashMediaDownloader::OnDrmInfoChanged(const std::multimap<std::string, std::vector<uint8_t>>& drmInfos)
1049 {
1050 if (callback_ != nullptr) {
1051 callback_->OnEvent({PluginEventType::SOURCE_DRM_INFO_UPDATE, {drmInfos}, "drm_info_update"});
1052 }
1053 }
1054
SetInterruptState(bool isInterruptNeeded)1055 void DashMediaDownloader::SetInterruptState(bool isInterruptNeeded)
1056 {
1057 isInterruptNeeded_ = isInterruptNeeded;
1058 mpdDownloader_->SetInterruptState(isInterruptNeeded);
1059 for (unsigned int index = 0; index < segmentDownloaders_.size(); index++) {
1060 segmentDownloaders_[index]->SetInterruptState(isInterruptNeeded);
1061 }
1062 }
1063
SetCurrentBitRate(int32_t bitRate,int32_t streamID)1064 Status DashMediaDownloader::SetCurrentBitRate(int32_t bitRate, int32_t streamID)
1065 {
1066 MEDIA_LOG_I("SetCurrentBitRate stream: " PUBLIC_LOG_D32 " biteRate: " PUBLIC_LOG_D32, streamID, bitRate);
1067 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloader(streamID);
1068 if (segmentDownloader != nullptr) {
1069 segmentDownloader->SetCurrentBitRate(bitRate);
1070 }
1071 return Status::OK;
1072 }
1073
SetDemuxerState(int32_t streamId)1074 void DashMediaDownloader::SetDemuxerState(int32_t streamId)
1075 {
1076 MEDIA_LOG_I("SetDemuxerState streamId: " PUBLIC_LOG_D32, streamId);
1077 std::shared_ptr<DashSegmentDownloader> segmentDownloader = GetSegmentDownloader(streamId);
1078 if (segmentDownloader != nullptr) {
1079 segmentDownloader->SetDemuxerState();
1080 }
1081 }
1082
GetPlaybackInfo(PlaybackInfo & playbackInfo)1083 void DashMediaDownloader::GetPlaybackInfo(PlaybackInfo& playbackInfo)
1084 {
1085 if (segmentDownloaders_.empty()) {
1086 return ;
1087 }
1088 if (segmentDownloaders_[0] != nullptr) {
1089 segmentDownloaders_[0]->GetIp(playbackInfo.serverIpAddress);
1090 }
1091 bool DownloadFinishStateTmp = true;
1092 playbackInfo.averageDownloadRate = 0;
1093 for (size_t i = 0; i < segmentDownloaders_.size(); i++) {
1094 if (playbackInfo.averageDownloadRate < static_cast<int64_t>(segmentDownloaders_[i]->GetDownloadSpeed())) {
1095 playbackInfo.averageDownloadRate = static_cast<int64_t>(segmentDownloaders_[i]->GetDownloadSpeed());
1096 std::pair<int64_t, int64_t> recordData = segmentDownloaders_[i]->GetDownloadRecordData();
1097 playbackInfo.downloadRate = recordData.first;
1098 playbackInfo.bufferDuration = recordData.second;
1099 }
1100 DownloadFinishStateTmp = (DownloadFinishStateTmp && segmentDownloaders_[i]->GetDownloadFinishState());
1101 }
1102 playbackInfo.isDownloading = DownloadFinishStateTmp ? false : true;
1103 }
1104
GetBufferSize() const1105 size_t DashMediaDownloader::GetBufferSize() const
1106 {
1107 std::shared_ptr<DashSegmentDownloader> segmentDownloader =
1108 GetSegmentDownloaderByType(MediaAVCodec::MediaType::MEDIA_TYPE_VID);
1109 if (segmentDownloader == nullptr) {
1110 MEDIA_LOG_W("GetBufferSize can not get segmentDownloader.");
1111 return 0;
1112 }
1113 return segmentDownloader->GetBufferSize();
1114 }
1115
SetAppUid(int32_t appUid)1116 void DashMediaDownloader::SetAppUid(int32_t appUid)
1117 {
1118 for (size_t i = 0; i < segmentDownloaders_.size(); i++) {
1119 segmentDownloaders_[i]->SetAppUid(appUid);
1120 }
1121 }
1122
GetPlayable()1123 bool DashMediaDownloader::GetPlayable()
1124 {
1125 std::shared_ptr<DashSegmentDownloader> vidSegmentDownloader =
1126 GetSegmentDownloaderByType(MediaAVCodec::MediaType::MEDIA_TYPE_VID);
1127 std::shared_ptr<DashSegmentDownloader> audSegmentDownloader =
1128 GetSegmentDownloaderByType(MediaAVCodec::MediaType::MEDIA_TYPE_AUD);
1129 if (vidSegmentDownloader != nullptr && audSegmentDownloader != nullptr) {
1130 return !vidSegmentDownloader->GetBufferringStatus() && !audSegmentDownloader->GetBufferringStatus();
1131 } else if (vidSegmentDownloader != nullptr) {
1132 return !vidSegmentDownloader->GetBufferringStatus();
1133 } else if (audSegmentDownloader != nullptr) {
1134 return !audSegmentDownloader->GetBufferringStatus();
1135 } else {
1136 MEDIA_LOG_E("GetPlayable error.");
1137 return false;
1138 }
1139 }
1140
GetBufferingTimeOut()1141 bool DashMediaDownloader::GetBufferingTimeOut()
1142 {
1143 return false;
1144 }
1145
1146 }
1147 }
1148 }
1149 }
1150