Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Unified Diff: media/base/pipeline_impl.cc

Issue 2237243002: CL for perf tryjob on linux (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/base/renderer_client.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/pipeline_impl.cc
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index 38a835b17af3248a968cb8650ca0b88ea908389c..bb23fd26e1e515ffa5e3dc06116138d8258eac83 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -29,9 +29,21 @@
#include "media/base/timestamp_constants.h"
#include "media/base/video_decoder_config.h"
+namespace {
static const double kDefaultPlaybackRate = 0.0;
static const float kDefaultVolume = 1.0f;
+base::TimeDelta CurrentMediaTime(base::TimeDelta min_time,
+ base::TimeDelta max_time,
+ base::TimeTicks ref_time,
+ base::TimeTicks curr_time,
+ double playback_rate) {
+ DCHECK(!ref_time.is_null());
+ return std::min(min_time + (curr_time - ref_time) * playback_rate, max_time);
+}
+
+} // namespace
+
namespace media {
class PipelineImpl::RendererWrapper : public DemuxerHost,
@@ -51,7 +63,9 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time);
void SetPlaybackRate(double playback_rate);
void SetVolume(float volume);
- base::TimeDelta GetMediaTime() const;
+ void GetMediaTimeExtents(base::TimeDelta* time_min,
+ base::TimeDelta* time_max,
+ base::TimeTicks* time_reference) const;
Ranges<base::TimeDelta> GetBufferedTimeRanges() const;
bool DidLoadingProgress();
PipelineStatistics GetStatistics() const;
@@ -78,10 +92,6 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
// frequently than needed. Posting all those notifications to the main thread
// causes performance issues: crbug.com/619975.
struct SharedState {
- // TODO(scherkus): Enforce that Renderer is only called on a single thread,
- // even for accessing media time http://crbug.com/370634
- std::unique_ptr<Renderer> renderer;
-
// True when OnBufferedTimeRangesChanged() has been called more recently
// than DidLoadingProgress().
bool did_loading_progress = false;
@@ -92,9 +102,10 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
// Accumulated statistics reported by the renderer.
PipelineStatistics statistics;
- // The media timestamp to return while the pipeline is suspended.
- // Otherwise set to kNoTimestamp.
- base::TimeDelta suspend_timestamp = kNoTimestamp;
+ // Media time extents reported by the renderer.
+ base::TimeDelta media_time_min;
+ base::TimeDelta media_time_max;
+ base::TimeTicks media_time_reference;
};
// DemuxerHost implementaion.
@@ -113,6 +124,9 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
void OnWaitingForDecryptionKey() final;
void OnVideoNaturalSizeChange(const gfx::Size& size) final;
void OnVideoOpacityChange(bool opaque) final;
+ void OnTimeUpdate(base::TimeDelta curr_time,
+ base::TimeDelta max_time,
+ base::TimeTicks capture_time) final;
// TextRenderer tasks and notifications.
void OnTextRendererEnded();
@@ -133,7 +147,6 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
void CompleteSuspend(PipelineStatus status);
void InitializeDemuxer(const PipelineStatusCB& done_cb);
void InitializeRenderer(const PipelineStatusCB& done_cb);
- void DestroyRenderer();
void ReportMetadata();
const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
@@ -142,6 +155,7 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
base::WeakPtr<PipelineImpl> weak_pipeline_;
Demuxer* demuxer_;
+ std::unique_ptr<Renderer> renderer_;
std::unique_ptr<TextRenderer> text_renderer_;
double playback_rate_;
float volume_;
@@ -216,16 +230,13 @@ void PipelineImpl::RendererWrapper::Start(
SetState(kStarting);
DCHECK(!demuxer_);
- DCHECK(!shared_state_.renderer);
+ DCHECK(!renderer_);
DCHECK(!text_renderer_);
DCHECK(!renderer_ended_);
DCHECK(!text_renderer_ended_);
DCHECK(!weak_pipeline_);
demuxer_ = demuxer;
- {
- base::AutoLock auto_lock(shared_state_lock_);
- shared_state_.renderer = std::move(renderer);
- }
+ renderer_ = std::move(renderer);
text_renderer_ = std::move(text_renderer);
if (text_renderer_) {
text_renderer_->Initialize(
@@ -270,9 +281,8 @@ void PipelineImpl::RendererWrapper::Stop(const base::Closure& stop_cb) {
// tasks.
pending_callbacks_.reset();
- DestroyRenderer();
+ renderer_.reset();
text_renderer_.reset();
-
if (demuxer_) {
demuxer_->Stop();
demuxer_ = NULL;
@@ -300,8 +310,6 @@ void PipelineImpl::RendererWrapper::Seek(base::TimeDelta time) {
return;
}
- base::TimeDelta seek_timestamp = std::max(time, demuxer_->GetStartTime());
-
SetState(kSeeking);
renderer_ended_ = false;
text_renderer_ended_ = false;
@@ -317,9 +325,9 @@ void PipelineImpl::RendererWrapper::Seek(base::TimeDelta time) {
}
// Flush.
- DCHECK(shared_state_.renderer);
- bound_fns.Push(base::Bind(&Renderer::Flush,
- base::Unretained(shared_state_.renderer.get())));
+ DCHECK(renderer_);
+ bound_fns.Push(
+ base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
if (text_renderer_) {
bound_fns.Push(base::Bind(&TextRenderer::Flush,
@@ -327,13 +335,14 @@ void PipelineImpl::RendererWrapper::Seek(base::TimeDelta time) {
}
// Seek demuxer.
+ base::TimeDelta seek_time = std::max(time, demuxer_->GetStartTime());
bound_fns.Push(
- base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp));
+ base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_time));
// Run tasks.
pending_callbacks_ = SerialRunner::Run(
bound_fns,
- base::Bind(&RendererWrapper::CompleteSeek, weak_this_, seek_timestamp));
+ base::Bind(&RendererWrapper::CompleteSeek, weak_this_, seek_time));
}
void PipelineImpl::RendererWrapper::Suspend() {
@@ -346,18 +355,20 @@ void PipelineImpl::RendererWrapper::Suspend() {
OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
return;
}
- DCHECK(shared_state_.renderer);
+ DCHECK(renderer_);
DCHECK(!pending_callbacks_.get());
SetState(kSuspending);
// Freeze playback and record the media time before flushing. (Flushing clears
// the value.)
- shared_state_.renderer->SetPlaybackRate(0.0);
+ renderer_->SetPlaybackRate(0.0);
+ base::TimeDelta media_time = renderer_->GetMediaTime();
{
base::AutoLock auto_lock(shared_state_lock_);
- shared_state_.suspend_timestamp = shared_state_.renderer->GetMediaTime();
- DCHECK(shared_state_.suspend_timestamp != kNoTimestamp);
+ shared_state_.media_time_min = media_time;
+ shared_state_.media_time_max = media_time;
+ shared_state_.media_time_reference = base::TimeTicks();
}
// Queue the asynchronous actions required to stop playback.
@@ -368,8 +379,7 @@ void PipelineImpl::RendererWrapper::Suspend() {
base::Unretained(text_renderer_.get())));
}
- fns.Push(base::Bind(&Renderer::Flush,
- base::Unretained(shared_state_.renderer.get())));
+ fns.Push(base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
if (text_renderer_) {
fns.Push(base::Bind(&TextRenderer::Flush,
@@ -391,16 +401,12 @@ void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer,
OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
return;
}
- DCHECK(!shared_state_.renderer);
+ DCHECK(!renderer_);
DCHECK(!pending_callbacks_.get());
SetState(kResuming);
- {
- base::AutoLock auto_lock(shared_state_lock_);
- shared_state_.renderer = std::move(renderer);
- }
-
+ renderer_ = std::move(renderer);
renderer_ended_ = false;
text_renderer_ended_ = false;
base::TimeDelta start_timestamp =
@@ -422,9 +428,18 @@ void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer,
void PipelineImpl::RendererWrapper::SetPlaybackRate(double playback_rate) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
+ if (!shared_state_.media_time_reference.is_null()) {
+ base::AutoLock auto_lock(shared_state_lock_);
+ base::TimeTicks now_time = base::TimeTicks::Now();
+ shared_state_.media_time_min = CurrentMediaTime(
+ shared_state_.media_time_min, shared_state_.media_time_max,
+ shared_state_.media_time_reference, now_time, playback_rate_);
+ shared_state_.media_time_reference = now_time;
+ }
+
playback_rate_ = playback_rate;
if (state_ == kPlaying)
- shared_state_.renderer->SetPlaybackRate(playback_rate_);
+ renderer_->SetPlaybackRate(playback_rate_);
}
void PipelineImpl::RendererWrapper::SetVolume(float volume) {
@@ -432,17 +447,18 @@ void PipelineImpl::RendererWrapper::SetVolume(float volume) {
volume_ = volume;
if (state_ == kPlaying)
- shared_state_.renderer->SetVolume(volume_);
+ renderer_->SetVolume(volume_);
}
-base::TimeDelta PipelineImpl::RendererWrapper::GetMediaTime() const {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
-
+void PipelineImpl::RendererWrapper::GetMediaTimeExtents(
+ base::TimeDelta* time_min,
+ base::TimeDelta* time_max,
+ base::TimeTicks* time_reference) const {
base::AutoLock auto_lock(shared_state_lock_);
- if (shared_state_.suspend_timestamp != kNoTimestamp)
- return shared_state_.suspend_timestamp;
- return shared_state_.renderer ? shared_state_.renderer->GetMediaTime()
- : base::TimeDelta();
+
+ *time_min = shared_state_.media_time_min;
+ *time_max = shared_state_.media_time_max;
+ *time_reference = shared_state_.media_time_reference;
}
Ranges<base::TimeDelta> PipelineImpl::RendererWrapper::GetBufferedTimeRanges()
@@ -474,15 +490,15 @@ void PipelineImpl::RendererWrapper::SetCdm(
const CdmAttachedCB& cdm_attached_cb) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
- if (!shared_state_.renderer) {
+ if (!renderer_) {
cdm_context_ = cdm_context;
cdm_attached_cb.Run(true);
return;
}
- shared_state_.renderer->SetCdm(
- cdm_context, base::Bind(&RendererWrapper::OnCdmAttached, weak_this_,
- cdm_attached_cb, cdm_context));
+ renderer_->SetCdm(cdm_context,
+ base::Bind(&RendererWrapper::OnCdmAttached, weak_this_,
+ cdm_attached_cb, cdm_context));
}
void PipelineImpl::RendererWrapper::OnBufferedTimeRangesChanged(
@@ -582,11 +598,10 @@ void PipelineImpl::RendererWrapper::OnEnabledAudioTracksChanged(
}
DCHECK(demuxer_);
- DCHECK(shared_state_.renderer);
+ DCHECK(renderer_);
- base::TimeDelta currTime = (state_ == kPlaying)
- ? shared_state_.renderer->GetMediaTime()
- : demuxer_->GetStartTime();
+ base::TimeDelta currTime = (state_ == kPlaying) ? renderer_->GetMediaTime()
+ : demuxer_->GetStartTime();
demuxer_->OnEnabledAudioTracksChanged(enabledTrackIds, currTime);
}
@@ -601,11 +616,10 @@ void PipelineImpl::RendererWrapper::OnSelectedVideoTrackChanged(
}
DCHECK(demuxer_);
- DCHECK(shared_state_.renderer);
+ DCHECK(renderer_);
- base::TimeDelta currTime = (state_ == kPlaying)
- ? shared_state_.renderer->GetMediaTime()
- : demuxer_->GetStartTime();
+ base::TimeDelta currTime = (state_ == kPlaying) ? renderer_->GetMediaTime()
+ : demuxer_->GetStartTime();
demuxer_->OnSelectedVideoTrackChanged(selectedTrackId, currTime);
}
@@ -658,6 +672,19 @@ void PipelineImpl::RendererWrapper::OnVideoOpacityChange(bool opaque) {
base::Bind(&PipelineImpl::OnVideoOpacityChange, weak_pipeline_, opaque));
}
+void PipelineImpl::RendererWrapper::OnTimeUpdate(base::TimeDelta curr_time,
+ base::TimeDelta max_time,
+ base::TimeTicks capture_time) {
+ DVLOG(4) << __func__ << "(" << curr_time.InMicroseconds() << ", "
+ << max_time.InMicroseconds() << ", " << capture_time << ")";
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ base::AutoLock auto_lock(shared_state_lock_);
+ shared_state_.media_time_min = curr_time;
+ shared_state_.media_time_max = max_time;
+ shared_state_.media_time_reference = capture_time;
+}
+
void PipelineImpl::RendererWrapper::OnTextRendererEnded() {
DCHECK(media_task_runner_->BelongsToCurrentThread());
media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED));
@@ -727,7 +754,7 @@ void PipelineImpl::RendererWrapper::OnCdmAttached(
void PipelineImpl::RendererWrapper::CheckPlaybackEnded() {
DCHECK(media_task_runner_->BelongsToCurrentThread());
- if (shared_state_.renderer && !renderer_ended_)
+ if (renderer_ && !renderer_ended_)
return;
if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_)
@@ -760,18 +787,20 @@ void PipelineImpl::RendererWrapper::CompleteSeek(base::TimeDelta seek_time,
return;
}
- shared_state_.renderer->StartPlayingFrom(
- std::max(seek_time, demuxer_->GetStartTime()));
- {
- base::AutoLock auto_lock(shared_state_lock_);
- shared_state_.suspend_timestamp = kNoTimestamp;
- }
+ seek_time = std::max(seek_time, demuxer_->GetStartTime());
+ renderer_->StartPlayingFrom(seek_time);
+ renderer_->SetPlaybackRate(playback_rate_);
+ renderer_->SetVolume(volume_);
if (text_renderer_)
text_renderer_->StartPlaying();
- shared_state_.renderer->SetPlaybackRate(playback_rate_);
- shared_state_.renderer->SetVolume(volume_);
+ {
+ base::AutoLock auto_lock(shared_state_lock_);
+ shared_state_.media_time_min = seek_time;
+ shared_state_.media_time_max = seek_time;
+ shared_state_.media_time_reference = base::TimeTicks();
+ }
SetState(kPlaying);
main_task_runner_->PostTask(
@@ -791,7 +820,7 @@ void PipelineImpl::RendererWrapper::CompleteSuspend(PipelineStatus status) {
LOG_IF(WARNING, status != PIPELINE_OK)
<< "Encountered pipeline error while suspending: " << status;
- DestroyRenderer();
+ renderer_.reset();
{
base::AutoLock auto_lock(shared_state_lock_);
shared_state_.statistics.audio_memory_usage = 0;
@@ -821,22 +850,9 @@ void PipelineImpl::RendererWrapper::InitializeRenderer(
}
if (cdm_context_)
- shared_state_.renderer->SetCdm(cdm_context_,
- base::Bind(&IgnoreCdmAttached));
+ renderer_->SetCdm(cdm_context_, base::Bind(&IgnoreCdmAttached));
- shared_state_.renderer->Initialize(demuxer_, this, done_cb);
-}
-
-void PipelineImpl::RendererWrapper::DestroyRenderer() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- // Destroy the renderer outside the lock scope to avoid holding the lock
- // while renderer is being destroyed (in case Renderer destructor is costly).
- std::unique_ptr<Renderer> renderer;
- {
- base::AutoLock auto_lock(shared_state_lock_);
- renderer.swap(shared_state_.renderer);
- }
+ renderer_->Initialize(demuxer_, this, done_cb);
}
void PipelineImpl::RendererWrapper::ReportMetadata() {
@@ -979,6 +995,8 @@ void PipelineImpl::Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) {
DCHECK(seek_cb_.is_null());
seek_cb_ = seek_cb;
+ media_time_last_ = base::TimeDelta();
+
media_task_runner_->PostTask(
FROM_HERE, base::Bind(&RendererWrapper::Seek,
base::Unretained(renderer_wrapper_.get()), time));
@@ -1008,6 +1026,7 @@ void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer,
DCHECK(IsRunning());
DCHECK(seek_cb_.is_null());
seek_cb_ = seek_cb;
+ media_time_last_ = base::TimeDelta();
media_task_runner_->PostTask(
FROM_HERE, base::Bind(&RendererWrapper::Resume,
@@ -1060,7 +1079,34 @@ void PipelineImpl::SetVolume(float volume) {
base::TimeDelta PipelineImpl::GetMediaTime() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return renderer_wrapper_->GetMediaTime();
+
+ base::TimeDelta time_min, time_max;
+ base::TimeTicks time_ref;
+ renderer_wrapper_->GetMediaTimeExtents(&time_min, &time_max, &time_ref);
+
+ // Return the current time based on the known extents of media data plus an
+ // estimate based on the last time those values were calculated.
+ base::TimeDelta media_time =
+ time_ref.is_null()
+ ? time_min
+ : CurrentMediaTime(time_min, time_max, time_ref,
+ base::TimeTicks::Now(), playback_rate_);
+
+ // Clamp current media time to the last reported value, this prevents higher
+ // level clients from seeing time go backwards based on inaccurate or spurious
+ // delay values reported to the AudioClock.
+ //
+ // It is expected that such events are transient and will be recovered as
+ // rendering continues over time.
+ if (media_time < media_time_last_) {
+ DVLOG(2) << __func__ << ": " << media_time_last_
+ << " (clamped), actual: " << media_time;
+ return media_time_last_;
+ }
+
+ DVLOG(2) << __func__ << ": " << media_time;
+ media_time_last_ = media_time;
+ return media_time;
}
Ranges<base::TimeDelta> PipelineImpl::GetBufferedTimeRanges() const {
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/base/renderer_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698