diff --git a/interfaces/inner_api/native/media_demuxer.h b/interfaces/inner_api/native/media_demuxer.h index c26033b480f87ada66c3a4b6e832efd15c7ae052..2cda7dde7d76400d320397c78fd4fdb3b76aeab3 100755 --- a/interfaces/inner_api/native/media_demuxer.h +++ b/interfaces/inner_api/native/media_demuxer.h @@ -185,6 +185,7 @@ private: int64_t ReadLoop(uint32_t trackId); Status CopyFrameToUserQueue(uint32_t trackId); bool GetBufferFromUserQueue(uint32_t queueIndex, uint32_t size = 0); + void InnerFixAbsolutePtsForPlayer(std::shared_ptr sample); Status InnerReadSample(uint32_t trackId, std::shared_ptr); Status InnerSelectTrack(int32_t trackId); Status HandleRead(uint32_t trackId); diff --git a/interfaces/inner_api/native/media_sync_manager.h b/interfaces/inner_api/native/media_sync_manager.h index a5a3ae5dda3fb31e714f2fc2226443efa3d9f488..25e0b8c5417ae91b83afcd3985d50cfad24653f3 100644 --- a/interfaces/inner_api/native/media_sync_manager.h +++ b/interfaces/inner_api/native/media_sync_manager.h @@ -102,6 +102,9 @@ public: int64_t GetSeekTime() override; void ResetTimeAnchorNoLock(); void SetMediaStartPts(int64_t startPts) override; + void ResetMediaStartPts() override; + int64_t GetMediaStartPts() override; + void SetLastAudioBufferDuration(int64_t durationUs) override; private: enum class State { RESUMED, @@ -157,6 +160,7 @@ private: std::vector prerolledSyncers_; int64_t delayTime_ {HST_TIME_NONE}; int64_t startPts_ {HST_TIME_NONE}; + std::atomic lastAudioBufferDuration_ {0}; std::atomic lastReportMediaTime_ {HST_TIME_NONE}; std::atomic frameAfterSeeked_ {false}; }; diff --git a/services/media_engine/modules/demuxer/media_demuxer.cpp b/services/media_engine/modules/demuxer/media_demuxer.cpp index 8069a576d2a61f167b7ba2cab5e0da00eb6b688f..8da20eb83d6860068edba18006b24279789d76e5 100755 --- a/services/media_engine/modules/demuxer/media_demuxer.cpp +++ b/services/media_engine/modules/demuxer/media_demuxer.cpp @@ -1656,10 +1656,17 @@ void MediaDemuxer::DumpBufferToFile(uint32_t trackId, std::shared_ptr } } +void MediaDemuxer::InnerFixAbsolutePtsForPlayer(std::shared_ptr sample) +{ + FALSE_RETURN(sample != nullptr); + sample->pts_ = sample->absPts_; +} + Status MediaDemuxer::HandleRead(uint32_t trackId) { Status ret = InnerReadSample(trackId, bufferMap_[trackId]); -if (trackId == videoTrackId_ && VideoStreamReadyCallback_ != nullptr) { + InnerFixAbsolutePtsForPlayer(bufferMap_[trackId]); + if (trackId == videoTrackId_ && VideoStreamReadyCallback_ != nullptr) { MEDIA_LOG_D("step into HandleRead"); bool isDiscardable = VideoStreamReadyCallback_->IsVideoStreamDiscardable(bufferMap_[trackId]); bufferQueueMap_[trackId]->PushBuffer(bufferMap_[trackId], !isDiscardable); diff --git a/services/media_engine/modules/sink/audio_sink.cpp b/services/media_engine/modules/sink/audio_sink.cpp index 0f766e61dfdf18201720864ec877c1b83e3c0c3a..ef33b279aefb100ea2d6358dc980131e77e0d44e 100644 --- a/services/media_engine/modules/sink/audio_sink.cpp +++ b/services/media_engine/modules/sink/audio_sink.cpp @@ -71,15 +71,6 @@ Status AudioSink::Init(std::shared_ptr& meta, const std::shared_ptrSetMediaStartPts(Plugins::HstTime2Us(startTime)); - } std::string mime; bool mimeGetRes = meta->Get(mime); if (mimeGetRes && mime == "audio/x-ape") { @@ -414,26 +405,23 @@ void AudioSink::DrainOutputBuffer() void AudioSink::ResetSyncInfo() { - auto syncCenter = syncCenter_.lock(); - if (syncCenter) { - syncCenter->Reset(); - } lastReportedClockTime_ = HST_TIME_NONE; forceUpdateTimeAnchorNextTime_ = false; - firstPts_ = HST_TIME_NONE; } int64_t AudioSink::DoSyncWrite(const std::shared_ptr& buffer) { bool render = true; // audio sink always report time anchor and do not drop int64_t nowCt = 0; - + auto syncCenter = syncCenter_.lock(); if (firstPts_ == HST_TIME_NONE) { - firstPts_ = buffer->pts_; + if (syncCenter && syncCenter->GetMediaStartPts() != HST_TIME_NONE) { + firstPts_ = syncCenter->GetMediaStartPts(); + } else { + firstPts_ = buffer->pts_; + } MEDIA_LOG_I("audio DoSyncWrite set firstPts = " PUBLIC_LOG_D64, firstPts_); } - - auto syncCenter = syncCenter_.lock(); if (syncCenter) { nowCt = syncCenter->GetClockTimeNow(); } @@ -461,6 +449,9 @@ int64_t AudioSink::DoSyncWrite(const std::shared_ptr& buf } else { latestBufferDuration_ = buffer->duration_ / speed_; } + if (syncCenter) { + syncCenter->SetLastAudioBufferDuration(latestBufferDuration_); + } return render ? 0 : -1; } diff --git a/services/media_engine/modules/sink/i_media_sync_center.h b/services/media_engine/modules/sink/i_media_sync_center.h index 50a6c4a22e410fa4db4988e28d817183c35803fd..142b017432c928d0db6c941c3961e8122fdffe78 100644 --- a/services/media_engine/modules/sink/i_media_sync_center.h +++ b/services/media_engine/modules/sink/i_media_sync_center.h @@ -94,6 +94,12 @@ struct IMediaSyncCenter { virtual float GetPlaybackRate() = 0; virtual void SetMediaStartPts(int64_t startPts) = 0; + + virtual void ResetMediaStartPts() = 0; + + virtual int64_t GetMediaStartPts() = 0; + + virtual void SetLastAudioBufferDuration(int64_t durationUs) = 0; }; } // namespace Pipeline } // namespace Media diff --git a/services/media_engine/modules/sink/media_sync_manager.cpp b/services/media_engine/modules/sink/media_sync_manager.cpp index bd9af080ee80ac70c81849c154354dc1d10a2b02..1d05aba5af2336501eb27b7d7e9d6ddbf568c234 100644 --- a/services/media_engine/modules/sink/media_sync_manager.cpp +++ b/services/media_engine/modules/sink/media_sync_manager.cpp @@ -386,8 +386,29 @@ int64_t MediaSyncManager::SimpleGetMediaTimeExactly(int64_t anchorClockTime, int return anchorMediaTime + (nowClockTime - anchorClockTime + delayTime) * static_cast(playRate) - delayTime; } +void MediaSyncManager::SetLastAudioBufferDuration(int64_t durationUs) +{ + if (durationUs > 0) { + lastAudioBufferDuration_ = durationUs; + } else { + lastAudioBufferDuration_ = 0; // If buffer duration is unavailable, treat it as 0. + } +} + int64_t MediaSyncManager::BoundMediaProgress(int64_t newMediaProgressTime) { + int64_t maxMediaProgress; + if (currentSyncerPriority_ == IMediaSynchronizer::AUDIO_SINK) { + maxMediaProgress = currentAnchorMediaTime_ + lastAudioBufferDuration_; + } else { + maxMediaProgress = currentAnchorMediaTime_; + } + if (newMediaProgressTime > maxMediaProgress) { + lastReportMediaTime_ = maxMediaProgress; // Avoid media progress go too far when data underrun. + MEDIA_LOG_W("Data underrun for %{public}" PRId64 " us, currentSyncerPriority_ is %{public}" PRId32, + newMediaProgressTime - maxMediaProgress, currentSyncerPriority_); + return lastReportMediaTime_; + } if ((newMediaProgressTime >= lastReportMediaTime_) || frameAfterSeeked_) { lastReportMediaTime_ = newMediaProgressTime; } else { @@ -499,7 +520,19 @@ bool MediaSyncManager::InSeeking() void MediaSyncManager::SetMediaStartPts(int64_t startPts) { - startPts_ = startPts; + if (startPts_ == HST_TIME_NONE || startPts < startPts_) { + startPts_ = startPts; + } +} + +void MediaSyncManager::ResetMediaStartPts() +{ + startPts_ = HST_TIME_NONE; +} + +int64_t MediaSyncManager::GetMediaStartPts() +{ + return startPts_; } void MediaSyncManager::ReportEos(IMediaSynchronizer* supplier) diff --git a/services/media_engine/modules/sink/video_sink.cpp b/services/media_engine/modules/sink/video_sink.cpp index 95e35a1c177c0667d031c93abfbf1884aafa82ba..2e24cb78722a8398ff6c04da7484f302d4034ff7 100644 --- a/services/media_engine/modules/sink/video_sink.cpp +++ b/services/media_engine/modules/sink/video_sink.cpp @@ -201,9 +201,14 @@ void VideoSink::SetEventReceiver(const std::shared_ptr &receiver) void VideoSink::SetFirstPts(int64_t pts) { + auto syncCenter = syncCenter_.lock(); if (firstPts_ == HST_TIME_NONE) { - firstPts_ = pts; - MEDIA_LOG_I_SHORT("video DoSyncWrite set firstPts = " PUBLIC_LOG_D64, firstPts_); + if (syncCenter && syncCenter->GetMediaStartPts() != HST_TIME_NONE) { + firstPts_ = syncCenter->GetMediaStartPts(); + } else { + firstPts_ = pts; + } + MEDIA_LOG_I("video DoSyncWrite set firstPts = " PUBLIC_LOG_D64, firstPts_); } }