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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/base/renderer_client.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/pipeline_impl.h" 5 #include "media/base/pipeline_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 11 matching lines...) Expand all
22 #include "media/base/media_log.h" 22 #include "media/base/media_log.h"
23 #include "media/base/media_switches.h" 23 #include "media/base/media_switches.h"
24 #include "media/base/renderer.h" 24 #include "media/base/renderer.h"
25 #include "media/base/renderer_client.h" 25 #include "media/base/renderer_client.h"
26 #include "media/base/serial_runner.h" 26 #include "media/base/serial_runner.h"
27 #include "media/base/text_renderer.h" 27 #include "media/base/text_renderer.h"
28 #include "media/base/text_track_config.h" 28 #include "media/base/text_track_config.h"
29 #include "media/base/timestamp_constants.h" 29 #include "media/base/timestamp_constants.h"
30 #include "media/base/video_decoder_config.h" 30 #include "media/base/video_decoder_config.h"
31 31
32 namespace {
32 static const double kDefaultPlaybackRate = 0.0; 33 static const double kDefaultPlaybackRate = 0.0;
33 static const float kDefaultVolume = 1.0f; 34 static const float kDefaultVolume = 1.0f;
34 35
36 base::TimeDelta CurrentMediaTime(base::TimeDelta min_time,
37 base::TimeDelta max_time,
38 base::TimeTicks ref_time,
39 base::TimeTicks curr_time,
40 double playback_rate) {
41 DCHECK(!ref_time.is_null());
42 return std::min(min_time + (curr_time - ref_time) * playback_rate, max_time);
43 }
44
45 } // namespace
46
35 namespace media { 47 namespace media {
36 48
37 class PipelineImpl::RendererWrapper : public DemuxerHost, 49 class PipelineImpl::RendererWrapper : public DemuxerHost,
38 public RendererClient { 50 public RendererClient {
39 public: 51 public:
40 RendererWrapper(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, 52 RendererWrapper(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
41 scoped_refptr<MediaLog> media_log); 53 scoped_refptr<MediaLog> media_log);
42 ~RendererWrapper() final; 54 ~RendererWrapper() final;
43 55
44 void Start(Demuxer* demuxer, 56 void Start(Demuxer* demuxer,
45 std::unique_ptr<Renderer> renderer, 57 std::unique_ptr<Renderer> renderer,
46 std::unique_ptr<TextRenderer> text_renderer, 58 std::unique_ptr<TextRenderer> text_renderer,
47 base::WeakPtr<PipelineImpl> weak_pipeline); 59 base::WeakPtr<PipelineImpl> weak_pipeline);
48 void Stop(const base::Closure& stop_cb); 60 void Stop(const base::Closure& stop_cb);
49 void Seek(base::TimeDelta time); 61 void Seek(base::TimeDelta time);
50 void Suspend(); 62 void Suspend();
51 void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time); 63 void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time);
52 void SetPlaybackRate(double playback_rate); 64 void SetPlaybackRate(double playback_rate);
53 void SetVolume(float volume); 65 void SetVolume(float volume);
54 base::TimeDelta GetMediaTime() const; 66 void GetMediaTimeExtents(base::TimeDelta* time_min,
67 base::TimeDelta* time_max,
68 base::TimeTicks* time_reference) const;
55 Ranges<base::TimeDelta> GetBufferedTimeRanges() const; 69 Ranges<base::TimeDelta> GetBufferedTimeRanges() const;
56 bool DidLoadingProgress(); 70 bool DidLoadingProgress();
57 PipelineStatistics GetStatistics() const; 71 PipelineStatistics GetStatistics() const;
58 void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb); 72 void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb);
59 73
60 // |enabledTrackIds| contains track ids of enabled audio tracks. 74 // |enabledTrackIds| contains track ids of enabled audio tracks.
61 void OnEnabledAudioTracksChanged( 75 void OnEnabledAudioTracksChanged(
62 const std::vector<MediaTrack::Id>& enabledTrackIds); 76 const std::vector<MediaTrack::Id>& enabledTrackIds);
63 77
64 // |trackId| either empty, which means no video track is selected, or contain 78 // |trackId| either empty, which means no video track is selected, or contain
65 // one element - the selected video track id. 79 // one element - the selected video track id.
66 void OnSelectedVideoTrackChanged( 80 void OnSelectedVideoTrackChanged(
67 const std::vector<MediaTrack::Id>& selectedTrackId); 81 const std::vector<MediaTrack::Id>& selectedTrackId);
68 82
69 private: 83 private:
70 // Contains state shared between main and media thread. 84 // Contains state shared between main and media thread.
71 // Main thread can only read. Media thread can both - read and write. 85 // Main thread can only read. Media thread can both - read and write.
72 // So it is not necessary to lock when reading from the media thread. 86 // So it is not necessary to lock when reading from the media thread.
73 // This struct should only contain state that is not immediately needed by 87 // This struct should only contain state that is not immediately needed by
74 // PipelineClient and can be cached on the media thread until queried. 88 // PipelineClient and can be cached on the media thread until queried.
75 // Alternatively we could cache it on the main thread by posting the 89 // Alternatively we could cache it on the main thread by posting the
76 // notification to the main thread. But some of the state change notifications 90 // notification to the main thread. But some of the state change notifications
77 // (OnStatisticsUpdate and OnBufferedTimeRangesChanged) arrive much more 91 // (OnStatisticsUpdate and OnBufferedTimeRangesChanged) arrive much more
78 // frequently than needed. Posting all those notifications to the main thread 92 // frequently than needed. Posting all those notifications to the main thread
79 // causes performance issues: crbug.com/619975. 93 // causes performance issues: crbug.com/619975.
80 struct SharedState { 94 struct SharedState {
81 // TODO(scherkus): Enforce that Renderer is only called on a single thread,
82 // even for accessing media time http://crbug.com/370634
83 std::unique_ptr<Renderer> renderer;
84
85 // True when OnBufferedTimeRangesChanged() has been called more recently 95 // True when OnBufferedTimeRangesChanged() has been called more recently
86 // than DidLoadingProgress(). 96 // than DidLoadingProgress().
87 bool did_loading_progress = false; 97 bool did_loading_progress = false;
88 98
89 // Amount of available buffered data as reported by Demuxer. 99 // Amount of available buffered data as reported by Demuxer.
90 Ranges<base::TimeDelta> buffered_time_ranges; 100 Ranges<base::TimeDelta> buffered_time_ranges;
91 101
92 // Accumulated statistics reported by the renderer. 102 // Accumulated statistics reported by the renderer.
93 PipelineStatistics statistics; 103 PipelineStatistics statistics;
94 104
95 // The media timestamp to return while the pipeline is suspended. 105 // Media time extents reported by the renderer.
96 // Otherwise set to kNoTimestamp. 106 base::TimeDelta media_time_min;
97 base::TimeDelta suspend_timestamp = kNoTimestamp; 107 base::TimeDelta media_time_max;
108 base::TimeTicks media_time_reference;
98 }; 109 };
99 110
100 // DemuxerHost implementaion. 111 // DemuxerHost implementaion.
101 void OnBufferedTimeRangesChanged(const Ranges<base::TimeDelta>& ranges) final; 112 void OnBufferedTimeRangesChanged(const Ranges<base::TimeDelta>& ranges) final;
102 void SetDuration(base::TimeDelta duration) final; 113 void SetDuration(base::TimeDelta duration) final;
103 void OnDemuxerError(PipelineStatus error) final; 114 void OnDemuxerError(PipelineStatus error) final;
104 void AddTextStream(DemuxerStream* text_stream, 115 void AddTextStream(DemuxerStream* text_stream,
105 const TextTrackConfig& config) final; 116 const TextTrackConfig& config) final;
106 void RemoveTextStream(DemuxerStream* text_stream) final; 117 void RemoveTextStream(DemuxerStream* text_stream) final;
107 118
108 // RendererClient implementation. 119 // RendererClient implementation.
109 void OnError(PipelineStatus error) final; 120 void OnError(PipelineStatus error) final;
110 void OnEnded() final; 121 void OnEnded() final;
111 void OnStatisticsUpdate(const PipelineStatistics& stats) final; 122 void OnStatisticsUpdate(const PipelineStatistics& stats) final;
112 void OnBufferingStateChange(BufferingState state) final; 123 void OnBufferingStateChange(BufferingState state) final;
113 void OnWaitingForDecryptionKey() final; 124 void OnWaitingForDecryptionKey() final;
114 void OnVideoNaturalSizeChange(const gfx::Size& size) final; 125 void OnVideoNaturalSizeChange(const gfx::Size& size) final;
115 void OnVideoOpacityChange(bool opaque) final; 126 void OnVideoOpacityChange(bool opaque) final;
127 void OnTimeUpdate(base::TimeDelta curr_time,
128 base::TimeDelta max_time,
129 base::TimeTicks capture_time) final;
116 130
117 // TextRenderer tasks and notifications. 131 // TextRenderer tasks and notifications.
118 void OnTextRendererEnded(); 132 void OnTextRendererEnded();
119 void AddTextStreamTask(DemuxerStream* text_stream, 133 void AddTextStreamTask(DemuxerStream* text_stream,
120 const TextTrackConfig& config); 134 const TextTrackConfig& config);
121 void RemoveTextStreamTask(DemuxerStream* text_stream); 135 void RemoveTextStreamTask(DemuxerStream* text_stream);
122 136
123 // Common handlers for notifications from renderers and demuxer. 137 // Common handlers for notifications from renderers and demuxer.
124 void OnPipelineError(PipelineStatus error); 138 void OnPipelineError(PipelineStatus error);
125 void OnCdmAttached(const CdmAttachedCB& cdm_attached_cb, 139 void OnCdmAttached(const CdmAttachedCB& cdm_attached_cb,
126 CdmContext* cdm_context, 140 CdmContext* cdm_context,
127 bool success); 141 bool success);
128 void CheckPlaybackEnded(); 142 void CheckPlaybackEnded();
129 143
130 // State transition tasks. 144 // State transition tasks.
131 void SetState(State next_state); 145 void SetState(State next_state);
132 void CompleteSeek(base::TimeDelta seek_time, PipelineStatus status); 146 void CompleteSeek(base::TimeDelta seek_time, PipelineStatus status);
133 void CompleteSuspend(PipelineStatus status); 147 void CompleteSuspend(PipelineStatus status);
134 void InitializeDemuxer(const PipelineStatusCB& done_cb); 148 void InitializeDemuxer(const PipelineStatusCB& done_cb);
135 void InitializeRenderer(const PipelineStatusCB& done_cb); 149 void InitializeRenderer(const PipelineStatusCB& done_cb);
136 void DestroyRenderer();
137 void ReportMetadata(); 150 void ReportMetadata();
138 151
139 const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; 152 const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
140 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; 153 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
141 const scoped_refptr<MediaLog> media_log_; 154 const scoped_refptr<MediaLog> media_log_;
142 155
143 base::WeakPtr<PipelineImpl> weak_pipeline_; 156 base::WeakPtr<PipelineImpl> weak_pipeline_;
144 Demuxer* demuxer_; 157 Demuxer* demuxer_;
158 std::unique_ptr<Renderer> renderer_;
145 std::unique_ptr<TextRenderer> text_renderer_; 159 std::unique_ptr<TextRenderer> text_renderer_;
146 double playback_rate_; 160 double playback_rate_;
147 float volume_; 161 float volume_;
148 CdmContext* cdm_context_; 162 CdmContext* cdm_context_;
149 163
150 // Lock used to serialize |shared_state_|. 164 // Lock used to serialize |shared_state_|.
151 mutable base::Lock shared_state_lock_; 165 mutable base::Lock shared_state_lock_;
152 166
153 // State shared between main and media thread. 167 // State shared between main and media thread.
154 SharedState shared_state_; 168 SharedState shared_state_;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 std::unique_ptr<Renderer> renderer, 223 std::unique_ptr<Renderer> renderer,
210 std::unique_ptr<TextRenderer> text_renderer, 224 std::unique_ptr<TextRenderer> text_renderer,
211 base::WeakPtr<PipelineImpl> weak_pipeline) { 225 base::WeakPtr<PipelineImpl> weak_pipeline) {
212 DCHECK(media_task_runner_->BelongsToCurrentThread()); 226 DCHECK(media_task_runner_->BelongsToCurrentThread());
213 DCHECK_EQ(kCreated, state_) << "Received start in unexpected state: " 227 DCHECK_EQ(kCreated, state_) << "Received start in unexpected state: "
214 << state_; 228 << state_;
215 229
216 SetState(kStarting); 230 SetState(kStarting);
217 231
218 DCHECK(!demuxer_); 232 DCHECK(!demuxer_);
219 DCHECK(!shared_state_.renderer); 233 DCHECK(!renderer_);
220 DCHECK(!text_renderer_); 234 DCHECK(!text_renderer_);
221 DCHECK(!renderer_ended_); 235 DCHECK(!renderer_ended_);
222 DCHECK(!text_renderer_ended_); 236 DCHECK(!text_renderer_ended_);
223 DCHECK(!weak_pipeline_); 237 DCHECK(!weak_pipeline_);
224 demuxer_ = demuxer; 238 demuxer_ = demuxer;
225 { 239 renderer_ = std::move(renderer);
226 base::AutoLock auto_lock(shared_state_lock_);
227 shared_state_.renderer = std::move(renderer);
228 }
229 text_renderer_ = std::move(text_renderer); 240 text_renderer_ = std::move(text_renderer);
230 if (text_renderer_) { 241 if (text_renderer_) {
231 text_renderer_->Initialize( 242 text_renderer_->Initialize(
232 base::Bind(&RendererWrapper::OnTextRendererEnded, weak_this_)); 243 base::Bind(&RendererWrapper::OnTextRendererEnded, weak_this_));
233 } 244 }
234 weak_pipeline_ = weak_pipeline; 245 weak_pipeline_ = weak_pipeline;
235 246
236 // Queue asynchronous actions required to start. 247 // Queue asynchronous actions required to start.
237 DCHECK(!pending_callbacks_); 248 DCHECK(!pending_callbacks_);
238 SerialRunner::Queue fns; 249 SerialRunner::Queue fns;
(...skipping 24 matching lines...) Expand all
263 UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount", 274 UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount",
264 shared_state_.statistics.video_frames_dropped); 275 shared_state_.statistics.video_frames_dropped);
265 } 276 }
266 277
267 // If we stop during starting/seeking/suspending/resuming we don't want to 278 // If we stop during starting/seeking/suspending/resuming we don't want to
268 // leave outstanding callbacks around. The callbacks also do not get run if 279 // leave outstanding callbacks around. The callbacks also do not get run if
269 // the pipeline is stopped before it had a chance to complete outstanding 280 // the pipeline is stopped before it had a chance to complete outstanding
270 // tasks. 281 // tasks.
271 pending_callbacks_.reset(); 282 pending_callbacks_.reset();
272 283
273 DestroyRenderer(); 284 renderer_.reset();
274 text_renderer_.reset(); 285 text_renderer_.reset();
275
276 if (demuxer_) { 286 if (demuxer_) {
277 demuxer_->Stop(); 287 demuxer_->Stop();
278 demuxer_ = NULL; 288 demuxer_ = NULL;
279 } 289 }
280 290
281 SetState(kStopped); 291 SetState(kStopped);
282 292
283 // Post the stop callback to enqueue it after the tasks that may have been 293 // Post the stop callback to enqueue it after the tasks that may have been
284 // posted by Demuxer and Renderer during stopping. Note that in theory the 294 // posted by Demuxer and Renderer during stopping. Note that in theory the
285 // tasks posted by Demuxer/Renderer may post even more tasks that will get 295 // tasks posted by Demuxer/Renderer may post even more tasks that will get
286 // enqueued after |stop_cb|. This may be problematic because Demuxer may 296 // enqueued after |stop_cb|. This may be problematic because Demuxer may
287 // get destroyed as soon as |stop_cb| is run. In practice this is not a 297 // get destroyed as soon as |stop_cb| is run. In practice this is not a
288 // problem, but ideally Demuxer should be destroyed on the media thread. 298 // problem, but ideally Demuxer should be destroyed on the media thread.
289 media_task_runner_->PostTask(FROM_HERE, stop_cb); 299 media_task_runner_->PostTask(FROM_HERE, stop_cb);
290 } 300 }
291 301
292 void PipelineImpl::RendererWrapper::Seek(base::TimeDelta time) { 302 void PipelineImpl::RendererWrapper::Seek(base::TimeDelta time) {
293 DCHECK(media_task_runner_->BelongsToCurrentThread()); 303 DCHECK(media_task_runner_->BelongsToCurrentThread());
294 304
295 // Suppress seeking if we're not fully started. 305 // Suppress seeking if we're not fully started.
296 if (state_ != kPlaying) { 306 if (state_ != kPlaying) {
297 DCHECK(state_ == kStopping || state_ == kStopped) 307 DCHECK(state_ == kStopping || state_ == kStopped)
298 << "Receive seek in unexpected state: " << state_; 308 << "Receive seek in unexpected state: " << state_;
299 OnPipelineError(PIPELINE_ERROR_INVALID_STATE); 309 OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
300 return; 310 return;
301 } 311 }
302 312
303 base::TimeDelta seek_timestamp = std::max(time, demuxer_->GetStartTime());
304
305 SetState(kSeeking); 313 SetState(kSeeking);
306 renderer_ended_ = false; 314 renderer_ended_ = false;
307 text_renderer_ended_ = false; 315 text_renderer_ended_ = false;
308 316
309 // Queue asynchronous actions required to start. 317 // Queue asynchronous actions required to start.
310 DCHECK(!pending_callbacks_); 318 DCHECK(!pending_callbacks_);
311 SerialRunner::Queue bound_fns; 319 SerialRunner::Queue bound_fns;
312 320
313 // Pause. 321 // Pause.
314 if (text_renderer_) { 322 if (text_renderer_) {
315 bound_fns.Push(base::Bind(&TextRenderer::Pause, 323 bound_fns.Push(base::Bind(&TextRenderer::Pause,
316 base::Unretained(text_renderer_.get()))); 324 base::Unretained(text_renderer_.get())));
317 } 325 }
318 326
319 // Flush. 327 // Flush.
320 DCHECK(shared_state_.renderer); 328 DCHECK(renderer_);
321 bound_fns.Push(base::Bind(&Renderer::Flush, 329 bound_fns.Push(
322 base::Unretained(shared_state_.renderer.get()))); 330 base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
323 331
324 if (text_renderer_) { 332 if (text_renderer_) {
325 bound_fns.Push(base::Bind(&TextRenderer::Flush, 333 bound_fns.Push(base::Bind(&TextRenderer::Flush,
326 base::Unretained(text_renderer_.get()))); 334 base::Unretained(text_renderer_.get())));
327 } 335 }
328 336
329 // Seek demuxer. 337 // Seek demuxer.
338 base::TimeDelta seek_time = std::max(time, demuxer_->GetStartTime());
330 bound_fns.Push( 339 bound_fns.Push(
331 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); 340 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_time));
332 341
333 // Run tasks. 342 // Run tasks.
334 pending_callbacks_ = SerialRunner::Run( 343 pending_callbacks_ = SerialRunner::Run(
335 bound_fns, 344 bound_fns,
336 base::Bind(&RendererWrapper::CompleteSeek, weak_this_, seek_timestamp)); 345 base::Bind(&RendererWrapper::CompleteSeek, weak_this_, seek_time));
337 } 346 }
338 347
339 void PipelineImpl::RendererWrapper::Suspend() { 348 void PipelineImpl::RendererWrapper::Suspend() {
340 DCHECK(media_task_runner_->BelongsToCurrentThread()); 349 DCHECK(media_task_runner_->BelongsToCurrentThread());
341 350
342 // Suppress suspending if we're not playing. 351 // Suppress suspending if we're not playing.
343 if (state_ != kPlaying) { 352 if (state_ != kPlaying) {
344 DCHECK(state_ == kStopping || state_ == kStopped) 353 DCHECK(state_ == kStopping || state_ == kStopped)
345 << "Receive suspend in unexpected state: " << state_; 354 << "Receive suspend in unexpected state: " << state_;
346 OnPipelineError(PIPELINE_ERROR_INVALID_STATE); 355 OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
347 return; 356 return;
348 } 357 }
349 DCHECK(shared_state_.renderer); 358 DCHECK(renderer_);
350 DCHECK(!pending_callbacks_.get()); 359 DCHECK(!pending_callbacks_.get());
351 360
352 SetState(kSuspending); 361 SetState(kSuspending);
353 362
354 // Freeze playback and record the media time before flushing. (Flushing clears 363 // Freeze playback and record the media time before flushing. (Flushing clears
355 // the value.) 364 // the value.)
356 shared_state_.renderer->SetPlaybackRate(0.0); 365 renderer_->SetPlaybackRate(0.0);
366 base::TimeDelta media_time = renderer_->GetMediaTime();
357 { 367 {
358 base::AutoLock auto_lock(shared_state_lock_); 368 base::AutoLock auto_lock(shared_state_lock_);
359 shared_state_.suspend_timestamp = shared_state_.renderer->GetMediaTime(); 369 shared_state_.media_time_min = media_time;
360 DCHECK(shared_state_.suspend_timestamp != kNoTimestamp); 370 shared_state_.media_time_max = media_time;
371 shared_state_.media_time_reference = base::TimeTicks();
361 } 372 }
362 373
363 // Queue the asynchronous actions required to stop playback. 374 // Queue the asynchronous actions required to stop playback.
364 SerialRunner::Queue fns; 375 SerialRunner::Queue fns;
365 376
366 if (text_renderer_) { 377 if (text_renderer_) {
367 fns.Push(base::Bind(&TextRenderer::Pause, 378 fns.Push(base::Bind(&TextRenderer::Pause,
368 base::Unretained(text_renderer_.get()))); 379 base::Unretained(text_renderer_.get())));
369 } 380 }
370 381
371 fns.Push(base::Bind(&Renderer::Flush, 382 fns.Push(base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
372 base::Unretained(shared_state_.renderer.get())));
373 383
374 if (text_renderer_) { 384 if (text_renderer_) {
375 fns.Push(base::Bind(&TextRenderer::Flush, 385 fns.Push(base::Bind(&TextRenderer::Flush,
376 base::Unretained(text_renderer_.get()))); 386 base::Unretained(text_renderer_.get())));
377 } 387 }
378 388
379 pending_callbacks_ = SerialRunner::Run( 389 pending_callbacks_ = SerialRunner::Run(
380 fns, base::Bind(&RendererWrapper::CompleteSuspend, weak_this_)); 390 fns, base::Bind(&RendererWrapper::CompleteSuspend, weak_this_));
381 } 391 }
382 392
383 void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer, 393 void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer,
384 base::TimeDelta timestamp) { 394 base::TimeDelta timestamp) {
385 DCHECK(media_task_runner_->BelongsToCurrentThread()); 395 DCHECK(media_task_runner_->BelongsToCurrentThread());
386 396
387 // Suppress resuming if we're not suspended. 397 // Suppress resuming if we're not suspended.
388 if (state_ != kSuspended) { 398 if (state_ != kSuspended) {
389 DCHECK(state_ == kStopping || state_ == kStopped) 399 DCHECK(state_ == kStopping || state_ == kStopped)
390 << "Receive resume in unexpected state: " << state_; 400 << "Receive resume in unexpected state: " << state_;
391 OnPipelineError(PIPELINE_ERROR_INVALID_STATE); 401 OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
392 return; 402 return;
393 } 403 }
394 DCHECK(!shared_state_.renderer); 404 DCHECK(!renderer_);
395 DCHECK(!pending_callbacks_.get()); 405 DCHECK(!pending_callbacks_.get());
396 406
397 SetState(kResuming); 407 SetState(kResuming);
398 408
399 { 409 renderer_ = std::move(renderer);
400 base::AutoLock auto_lock(shared_state_lock_);
401 shared_state_.renderer = std::move(renderer);
402 }
403
404 renderer_ended_ = false; 410 renderer_ended_ = false;
405 text_renderer_ended_ = false; 411 text_renderer_ended_ = false;
406 base::TimeDelta start_timestamp = 412 base::TimeDelta start_timestamp =
407 std::max(timestamp, demuxer_->GetStartTime()); 413 std::max(timestamp, demuxer_->GetStartTime());
408 414
409 // Queue the asynchronous actions required to start playback. 415 // Queue the asynchronous actions required to start playback.
410 SerialRunner::Queue fns; 416 SerialRunner::Queue fns;
411 417
412 fns.Push( 418 fns.Push(
413 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), start_timestamp)); 419 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), start_timestamp));
414 420
415 fns.Push(base::Bind(&RendererWrapper::InitializeRenderer, weak_this_)); 421 fns.Push(base::Bind(&RendererWrapper::InitializeRenderer, weak_this_));
416 422
417 pending_callbacks_ = SerialRunner::Run( 423 pending_callbacks_ = SerialRunner::Run(
418 fns, 424 fns,
419 base::Bind(&RendererWrapper::CompleteSeek, weak_this_, start_timestamp)); 425 base::Bind(&RendererWrapper::CompleteSeek, weak_this_, start_timestamp));
420 } 426 }
421 427
422 void PipelineImpl::RendererWrapper::SetPlaybackRate(double playback_rate) { 428 void PipelineImpl::RendererWrapper::SetPlaybackRate(double playback_rate) {
423 DCHECK(media_task_runner_->BelongsToCurrentThread()); 429 DCHECK(media_task_runner_->BelongsToCurrentThread());
424 430
431 if (!shared_state_.media_time_reference.is_null()) {
432 base::AutoLock auto_lock(shared_state_lock_);
433 base::TimeTicks now_time = base::TimeTicks::Now();
434 shared_state_.media_time_min = CurrentMediaTime(
435 shared_state_.media_time_min, shared_state_.media_time_max,
436 shared_state_.media_time_reference, now_time, playback_rate_);
437 shared_state_.media_time_reference = now_time;
438 }
439
425 playback_rate_ = playback_rate; 440 playback_rate_ = playback_rate;
426 if (state_ == kPlaying) 441 if (state_ == kPlaying)
427 shared_state_.renderer->SetPlaybackRate(playback_rate_); 442 renderer_->SetPlaybackRate(playback_rate_);
428 } 443 }
429 444
430 void PipelineImpl::RendererWrapper::SetVolume(float volume) { 445 void PipelineImpl::RendererWrapper::SetVolume(float volume) {
431 DCHECK(media_task_runner_->BelongsToCurrentThread()); 446 DCHECK(media_task_runner_->BelongsToCurrentThread());
432 447
433 volume_ = volume; 448 volume_ = volume;
434 if (state_ == kPlaying) 449 if (state_ == kPlaying)
435 shared_state_.renderer->SetVolume(volume_); 450 renderer_->SetVolume(volume_);
436 } 451 }
437 452
438 base::TimeDelta PipelineImpl::RendererWrapper::GetMediaTime() const { 453 void PipelineImpl::RendererWrapper::GetMediaTimeExtents(
439 DCHECK(main_task_runner_->BelongsToCurrentThread()); 454 base::TimeDelta* time_min,
455 base::TimeDelta* time_max,
456 base::TimeTicks* time_reference) const {
457 base::AutoLock auto_lock(shared_state_lock_);
440 458
441 base::AutoLock auto_lock(shared_state_lock_); 459 *time_min = shared_state_.media_time_min;
442 if (shared_state_.suspend_timestamp != kNoTimestamp) 460 *time_max = shared_state_.media_time_max;
443 return shared_state_.suspend_timestamp; 461 *time_reference = shared_state_.media_time_reference;
444 return shared_state_.renderer ? shared_state_.renderer->GetMediaTime()
445 : base::TimeDelta();
446 } 462 }
447 463
448 Ranges<base::TimeDelta> PipelineImpl::RendererWrapper::GetBufferedTimeRanges() 464 Ranges<base::TimeDelta> PipelineImpl::RendererWrapper::GetBufferedTimeRanges()
449 const { 465 const {
450 DCHECK(main_task_runner_->BelongsToCurrentThread()); 466 DCHECK(main_task_runner_->BelongsToCurrentThread());
451 467
452 base::AutoLock auto_lock(shared_state_lock_); 468 base::AutoLock auto_lock(shared_state_lock_);
453 return shared_state_.buffered_time_ranges; 469 return shared_state_.buffered_time_ranges;
454 } 470 }
455 471
(...skipping 11 matching lines...) Expand all
467 483
468 base::AutoLock auto_lock(shared_state_lock_); 484 base::AutoLock auto_lock(shared_state_lock_);
469 return shared_state_.statistics; 485 return shared_state_.statistics;
470 } 486 }
471 487
472 void PipelineImpl::RendererWrapper::SetCdm( 488 void PipelineImpl::RendererWrapper::SetCdm(
473 CdmContext* cdm_context, 489 CdmContext* cdm_context,
474 const CdmAttachedCB& cdm_attached_cb) { 490 const CdmAttachedCB& cdm_attached_cb) {
475 DCHECK(media_task_runner_->BelongsToCurrentThread()); 491 DCHECK(media_task_runner_->BelongsToCurrentThread());
476 492
477 if (!shared_state_.renderer) { 493 if (!renderer_) {
478 cdm_context_ = cdm_context; 494 cdm_context_ = cdm_context;
479 cdm_attached_cb.Run(true); 495 cdm_attached_cb.Run(true);
480 return; 496 return;
481 } 497 }
482 498
483 shared_state_.renderer->SetCdm( 499 renderer_->SetCdm(cdm_context,
484 cdm_context, base::Bind(&RendererWrapper::OnCdmAttached, weak_this_, 500 base::Bind(&RendererWrapper::OnCdmAttached, weak_this_,
485 cdm_attached_cb, cdm_context)); 501 cdm_attached_cb, cdm_context));
486 } 502 }
487 503
488 void PipelineImpl::RendererWrapper::OnBufferedTimeRangesChanged( 504 void PipelineImpl::RendererWrapper::OnBufferedTimeRangesChanged(
489 const Ranges<base::TimeDelta>& ranges) { 505 const Ranges<base::TimeDelta>& ranges) {
490 // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer 506 // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer
491 // implementations call DemuxerHost on the media thread. 507 // implementations call DemuxerHost on the media thread.
492 base::AutoLock auto_lock(shared_state_lock_); 508 base::AutoLock auto_lock(shared_state_lock_);
493 shared_state_.did_loading_progress = true; 509 shared_state_.did_loading_progress = true;
494 shared_state_.buffered_time_ranges = ranges; 510 shared_state_.buffered_time_ranges = ranges;
495 } 511 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 const std::vector<MediaTrack::Id>& enabledTrackIds) { 591 const std::vector<MediaTrack::Id>& enabledTrackIds) {
576 DCHECK(media_task_runner_->BelongsToCurrentThread()); 592 DCHECK(media_task_runner_->BelongsToCurrentThread());
577 593
578 // Track status notifications might be delivered asynchronously. If we receive 594 // Track status notifications might be delivered asynchronously. If we receive
579 // a notification when pipeline is stopped/shut down, it's safe to ignore it. 595 // a notification when pipeline is stopped/shut down, it's safe to ignore it.
580 if (state_ == kStopping || state_ == kStopped) { 596 if (state_ == kStopping || state_ == kStopped) {
581 return; 597 return;
582 } 598 }
583 599
584 DCHECK(demuxer_); 600 DCHECK(demuxer_);
585 DCHECK(shared_state_.renderer); 601 DCHECK(renderer_);
586 602
587 base::TimeDelta currTime = (state_ == kPlaying) 603 base::TimeDelta currTime = (state_ == kPlaying) ? renderer_->GetMediaTime()
588 ? shared_state_.renderer->GetMediaTime() 604 : demuxer_->GetStartTime();
589 : demuxer_->GetStartTime();
590 demuxer_->OnEnabledAudioTracksChanged(enabledTrackIds, currTime); 605 demuxer_->OnEnabledAudioTracksChanged(enabledTrackIds, currTime);
591 } 606 }
592 607
593 void PipelineImpl::RendererWrapper::OnSelectedVideoTrackChanged( 608 void PipelineImpl::RendererWrapper::OnSelectedVideoTrackChanged(
594 const std::vector<MediaTrack::Id>& selectedTrackId) { 609 const std::vector<MediaTrack::Id>& selectedTrackId) {
595 DCHECK(media_task_runner_->BelongsToCurrentThread()); 610 DCHECK(media_task_runner_->BelongsToCurrentThread());
596 611
597 // Track status notifications might be delivered asynchronously. If we receive 612 // Track status notifications might be delivered asynchronously. If we receive
598 // a notification when pipeline is stopped/shut down, it's safe to ignore it. 613 // a notification when pipeline is stopped/shut down, it's safe to ignore it.
599 if (state_ == kStopping || state_ == kStopped) { 614 if (state_ == kStopping || state_ == kStopped) {
600 return; 615 return;
601 } 616 }
602 617
603 DCHECK(demuxer_); 618 DCHECK(demuxer_);
604 DCHECK(shared_state_.renderer); 619 DCHECK(renderer_);
605 620
606 base::TimeDelta currTime = (state_ == kPlaying) 621 base::TimeDelta currTime = (state_ == kPlaying) ? renderer_->GetMediaTime()
607 ? shared_state_.renderer->GetMediaTime() 622 : demuxer_->GetStartTime();
608 : demuxer_->GetStartTime();
609 demuxer_->OnSelectedVideoTrackChanged(selectedTrackId, currTime); 623 demuxer_->OnSelectedVideoTrackChanged(selectedTrackId, currTime);
610 } 624 }
611 625
612 void PipelineImpl::RendererWrapper::OnStatisticsUpdate( 626 void PipelineImpl::RendererWrapper::OnStatisticsUpdate(
613 const PipelineStatistics& stats) { 627 const PipelineStatistics& stats) {
614 DVLOG(3) << __func__; 628 DVLOG(3) << __func__;
615 DCHECK(media_task_runner_->BelongsToCurrentThread()); 629 DCHECK(media_task_runner_->BelongsToCurrentThread());
616 630
617 base::AutoLock auto_lock(shared_state_lock_); 631 base::AutoLock auto_lock(shared_state_lock_);
618 shared_state_.statistics.audio_bytes_decoded += stats.audio_bytes_decoded; 632 shared_state_.statistics.audio_bytes_decoded += stats.audio_bytes_decoded;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 } 665 }
652 666
653 void PipelineImpl::RendererWrapper::OnVideoOpacityChange(bool opaque) { 667 void PipelineImpl::RendererWrapper::OnVideoOpacityChange(bool opaque) {
654 DCHECK(media_task_runner_->BelongsToCurrentThread()); 668 DCHECK(media_task_runner_->BelongsToCurrentThread());
655 669
656 main_task_runner_->PostTask( 670 main_task_runner_->PostTask(
657 FROM_HERE, 671 FROM_HERE,
658 base::Bind(&PipelineImpl::OnVideoOpacityChange, weak_pipeline_, opaque)); 672 base::Bind(&PipelineImpl::OnVideoOpacityChange, weak_pipeline_, opaque));
659 } 673 }
660 674
675 void PipelineImpl::RendererWrapper::OnTimeUpdate(base::TimeDelta curr_time,
676 base::TimeDelta max_time,
677 base::TimeTicks capture_time) {
678 DVLOG(4) << __func__ << "(" << curr_time.InMicroseconds() << ", "
679 << max_time.InMicroseconds() << ", " << capture_time << ")";
680 DCHECK(media_task_runner_->BelongsToCurrentThread());
681
682 base::AutoLock auto_lock(shared_state_lock_);
683 shared_state_.media_time_min = curr_time;
684 shared_state_.media_time_max = max_time;
685 shared_state_.media_time_reference = capture_time;
686 }
687
661 void PipelineImpl::RendererWrapper::OnTextRendererEnded() { 688 void PipelineImpl::RendererWrapper::OnTextRendererEnded() {
662 DCHECK(media_task_runner_->BelongsToCurrentThread()); 689 DCHECK(media_task_runner_->BelongsToCurrentThread());
663 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED)); 690 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED));
664 691
665 if (state_ != kPlaying) 692 if (state_ != kPlaying)
666 return; 693 return;
667 694
668 DCHECK(!text_renderer_ended_); 695 DCHECK(!text_renderer_ended_);
669 text_renderer_ended_ = true; 696 text_renderer_ended_ = true;
670 CheckPlaybackEnded(); 697 CheckPlaybackEnded();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 DCHECK(media_task_runner_->BelongsToCurrentThread()); 747 DCHECK(media_task_runner_->BelongsToCurrentThread());
721 748
722 if (success) 749 if (success)
723 cdm_context_ = cdm_context; 750 cdm_context_ = cdm_context;
724 cdm_attached_cb.Run(success); 751 cdm_attached_cb.Run(success);
725 } 752 }
726 753
727 void PipelineImpl::RendererWrapper::CheckPlaybackEnded() { 754 void PipelineImpl::RendererWrapper::CheckPlaybackEnded() {
728 DCHECK(media_task_runner_->BelongsToCurrentThread()); 755 DCHECK(media_task_runner_->BelongsToCurrentThread());
729 756
730 if (shared_state_.renderer && !renderer_ended_) 757 if (renderer_ && !renderer_ended_)
731 return; 758 return;
732 759
733 if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_) 760 if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_)
734 return; 761 return;
735 762
736 DCHECK_EQ(status_, PIPELINE_OK); 763 DCHECK_EQ(status_, PIPELINE_OK);
737 main_task_runner_->PostTask( 764 main_task_runner_->PostTask(
738 FROM_HERE, base::Bind(&PipelineImpl::OnEnded, weak_pipeline_)); 765 FROM_HERE, base::Bind(&PipelineImpl::OnEnded, weak_pipeline_));
739 } 766 }
740 767
(...skipping 12 matching lines...) Expand all
753 DCHECK(state_ == kStarting || state_ == kSeeking || state_ == kResuming); 780 DCHECK(state_ == kStarting || state_ == kSeeking || state_ == kResuming);
754 781
755 DCHECK(pending_callbacks_); 782 DCHECK(pending_callbacks_);
756 pending_callbacks_.reset(); 783 pending_callbacks_.reset();
757 784
758 if (status != PIPELINE_OK) { 785 if (status != PIPELINE_OK) {
759 OnPipelineError(status); 786 OnPipelineError(status);
760 return; 787 return;
761 } 788 }
762 789
763 shared_state_.renderer->StartPlayingFrom( 790 seek_time = std::max(seek_time, demuxer_->GetStartTime());
764 std::max(seek_time, demuxer_->GetStartTime())); 791 renderer_->StartPlayingFrom(seek_time);
765 { 792 renderer_->SetPlaybackRate(playback_rate_);
766 base::AutoLock auto_lock(shared_state_lock_); 793 renderer_->SetVolume(volume_);
767 shared_state_.suspend_timestamp = kNoTimestamp;
768 }
769 794
770 if (text_renderer_) 795 if (text_renderer_)
771 text_renderer_->StartPlaying(); 796 text_renderer_->StartPlaying();
772 797
773 shared_state_.renderer->SetPlaybackRate(playback_rate_); 798 {
774 shared_state_.renderer->SetVolume(volume_); 799 base::AutoLock auto_lock(shared_state_lock_);
800 shared_state_.media_time_min = seek_time;
801 shared_state_.media_time_max = seek_time;
802 shared_state_.media_time_reference = base::TimeTicks();
803 }
775 804
776 SetState(kPlaying); 805 SetState(kPlaying);
777 main_task_runner_->PostTask( 806 main_task_runner_->PostTask(
778 FROM_HERE, base::Bind(&PipelineImpl::OnSeekDone, weak_pipeline_)); 807 FROM_HERE, base::Bind(&PipelineImpl::OnSeekDone, weak_pipeline_));
779 } 808 }
780 809
781 void PipelineImpl::RendererWrapper::CompleteSuspend(PipelineStatus status) { 810 void PipelineImpl::RendererWrapper::CompleteSuspend(PipelineStatus status) {
782 DCHECK(media_task_runner_->BelongsToCurrentThread()); 811 DCHECK(media_task_runner_->BelongsToCurrentThread());
783 DCHECK_EQ(kSuspending, state_); 812 DCHECK_EQ(kSuspending, state_);
784 813
785 DCHECK(pending_callbacks_); 814 DCHECK(pending_callbacks_);
786 pending_callbacks_.reset(); 815 pending_callbacks_.reset();
787 816
788 // In case we are suspending or suspended, the error may be recoverable, 817 // In case we are suspending or suspended, the error may be recoverable,
789 // so don't propagate it now, instead let the subsequent seek during resume 818 // so don't propagate it now, instead let the subsequent seek during resume
790 // propagate it if it's unrecoverable. 819 // propagate it if it's unrecoverable.
791 LOG_IF(WARNING, status != PIPELINE_OK) 820 LOG_IF(WARNING, status != PIPELINE_OK)
792 << "Encountered pipeline error while suspending: " << status; 821 << "Encountered pipeline error while suspending: " << status;
793 822
794 DestroyRenderer(); 823 renderer_.reset();
795 { 824 {
796 base::AutoLock auto_lock(shared_state_lock_); 825 base::AutoLock auto_lock(shared_state_lock_);
797 shared_state_.statistics.audio_memory_usage = 0; 826 shared_state_.statistics.audio_memory_usage = 0;
798 shared_state_.statistics.video_memory_usage = 0; 827 shared_state_.statistics.video_memory_usage = 0;
799 } 828 }
800 829
801 SetState(kSuspended); 830 SetState(kSuspended);
802 main_task_runner_->PostTask( 831 main_task_runner_->PostTask(
803 FROM_HERE, base::Bind(&PipelineImpl::OnSuspendDone, weak_pipeline_)); 832 FROM_HERE, base::Bind(&PipelineImpl::OnSuspendDone, weak_pipeline_));
804 } 833 }
805 834
806 void PipelineImpl::RendererWrapper::InitializeDemuxer( 835 void PipelineImpl::RendererWrapper::InitializeDemuxer(
807 const PipelineStatusCB& done_cb) { 836 const PipelineStatusCB& done_cb) {
808 DCHECK(media_task_runner_->BelongsToCurrentThread()); 837 DCHECK(media_task_runner_->BelongsToCurrentThread());
809 838
810 demuxer_->Initialize(this, done_cb, !!text_renderer_); 839 demuxer_->Initialize(this, done_cb, !!text_renderer_);
811 } 840 }
812 841
813 void PipelineImpl::RendererWrapper::InitializeRenderer( 842 void PipelineImpl::RendererWrapper::InitializeRenderer(
814 const PipelineStatusCB& done_cb) { 843 const PipelineStatusCB& done_cb) {
815 DCHECK(media_task_runner_->BelongsToCurrentThread()); 844 DCHECK(media_task_runner_->BelongsToCurrentThread());
816 845
817 if (!demuxer_->GetStream(DemuxerStream::AUDIO) && 846 if (!demuxer_->GetStream(DemuxerStream::AUDIO) &&
818 !demuxer_->GetStream(DemuxerStream::VIDEO)) { 847 !demuxer_->GetStream(DemuxerStream::VIDEO)) {
819 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); 848 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
820 return; 849 return;
821 } 850 }
822 851
823 if (cdm_context_) 852 if (cdm_context_)
824 shared_state_.renderer->SetCdm(cdm_context_, 853 renderer_->SetCdm(cdm_context_, base::Bind(&IgnoreCdmAttached));
825 base::Bind(&IgnoreCdmAttached));
826 854
827 shared_state_.renderer->Initialize(demuxer_, this, done_cb); 855 renderer_->Initialize(demuxer_, this, done_cb);
828 }
829
830 void PipelineImpl::RendererWrapper::DestroyRenderer() {
831 DCHECK(media_task_runner_->BelongsToCurrentThread());
832
833 // Destroy the renderer outside the lock scope to avoid holding the lock
834 // while renderer is being destroyed (in case Renderer destructor is costly).
835 std::unique_ptr<Renderer> renderer;
836 {
837 base::AutoLock auto_lock(shared_state_lock_);
838 renderer.swap(shared_state_.renderer);
839 }
840 } 856 }
841 857
842 void PipelineImpl::RendererWrapper::ReportMetadata() { 858 void PipelineImpl::RendererWrapper::ReportMetadata() {
843 DCHECK(media_task_runner_->BelongsToCurrentThread()); 859 DCHECK(media_task_runner_->BelongsToCurrentThread());
844 860
845 PipelineMetadata metadata; 861 PipelineMetadata metadata;
846 metadata.timeline_offset = demuxer_->GetTimelineOffset(); 862 metadata.timeline_offset = demuxer_->GetTimelineOffset();
847 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 863 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
848 if (stream) { 864 if (stream) {
849 metadata.has_video = true; 865 metadata.has_video = true;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 DCHECK(thread_checker_.CalledOnValidThread()); 988 DCHECK(thread_checker_.CalledOnValidThread());
973 DCHECK(!seek_cb.is_null()); 989 DCHECK(!seek_cb.is_null());
974 990
975 if (!IsRunning()) { 991 if (!IsRunning()) {
976 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; 992 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek().";
977 return; 993 return;
978 } 994 }
979 995
980 DCHECK(seek_cb_.is_null()); 996 DCHECK(seek_cb_.is_null());
981 seek_cb_ = seek_cb; 997 seek_cb_ = seek_cb;
998 media_time_last_ = base::TimeDelta();
999
982 media_task_runner_->PostTask( 1000 media_task_runner_->PostTask(
983 FROM_HERE, base::Bind(&RendererWrapper::Seek, 1001 FROM_HERE, base::Bind(&RendererWrapper::Seek,
984 base::Unretained(renderer_wrapper_.get()), time)); 1002 base::Unretained(renderer_wrapper_.get()), time));
985 } 1003 }
986 1004
987 void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) { 1005 void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) {
988 DVLOG(2) << __func__; 1006 DVLOG(2) << __func__;
989 DCHECK(!suspend_cb.is_null()); 1007 DCHECK(!suspend_cb.is_null());
990 1008
991 DCHECK(IsRunning()); 1009 DCHECK(IsRunning());
992 DCHECK(suspend_cb_.is_null()); 1010 DCHECK(suspend_cb_.is_null());
993 suspend_cb_ = suspend_cb; 1011 suspend_cb_ = suspend_cb;
994 1012
995 media_task_runner_->PostTask( 1013 media_task_runner_->PostTask(
996 FROM_HERE, base::Bind(&RendererWrapper::Suspend, 1014 FROM_HERE, base::Bind(&RendererWrapper::Suspend,
997 base::Unretained(renderer_wrapper_.get()))); 1015 base::Unretained(renderer_wrapper_.get())));
998 } 1016 }
999 1017
1000 void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer, 1018 void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer,
1001 base::TimeDelta time, 1019 base::TimeDelta time,
1002 const PipelineStatusCB& seek_cb) { 1020 const PipelineStatusCB& seek_cb) {
1003 DVLOG(2) << __func__; 1021 DVLOG(2) << __func__;
1004 DCHECK(thread_checker_.CalledOnValidThread()); 1022 DCHECK(thread_checker_.CalledOnValidThread());
1005 DCHECK(renderer); 1023 DCHECK(renderer);
1006 DCHECK(!seek_cb.is_null()); 1024 DCHECK(!seek_cb.is_null());
1007 1025
1008 DCHECK(IsRunning()); 1026 DCHECK(IsRunning());
1009 DCHECK(seek_cb_.is_null()); 1027 DCHECK(seek_cb_.is_null());
1010 seek_cb_ = seek_cb; 1028 seek_cb_ = seek_cb;
1029 media_time_last_ = base::TimeDelta();
1011 1030
1012 media_task_runner_->PostTask( 1031 media_task_runner_->PostTask(
1013 FROM_HERE, base::Bind(&RendererWrapper::Resume, 1032 FROM_HERE, base::Bind(&RendererWrapper::Resume,
1014 base::Unretained(renderer_wrapper_.get()), 1033 base::Unretained(renderer_wrapper_.get()),
1015 base::Passed(&renderer), time)); 1034 base::Passed(&renderer), time));
1016 } 1035 }
1017 1036
1018 bool PipelineImpl::IsRunning() const { 1037 bool PipelineImpl::IsRunning() const {
1019 DCHECK(thread_checker_.CalledOnValidThread()); 1038 DCHECK(thread_checker_.CalledOnValidThread());
1020 return !!client_; 1039 return !!client_;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 1072
1054 volume_ = volume; 1073 volume_ = volume;
1055 media_task_runner_->PostTask( 1074 media_task_runner_->PostTask(
1056 FROM_HERE, 1075 FROM_HERE,
1057 base::Bind(&RendererWrapper::SetVolume, 1076 base::Bind(&RendererWrapper::SetVolume,
1058 base::Unretained(renderer_wrapper_.get()), volume_)); 1077 base::Unretained(renderer_wrapper_.get()), volume_));
1059 } 1078 }
1060 1079
1061 base::TimeDelta PipelineImpl::GetMediaTime() const { 1080 base::TimeDelta PipelineImpl::GetMediaTime() const {
1062 DCHECK(thread_checker_.CalledOnValidThread()); 1081 DCHECK(thread_checker_.CalledOnValidThread());
1063 return renderer_wrapper_->GetMediaTime(); 1082
1083 base::TimeDelta time_min, time_max;
1084 base::TimeTicks time_ref;
1085 renderer_wrapper_->GetMediaTimeExtents(&time_min, &time_max, &time_ref);
1086
1087 // Return the current time based on the known extents of media data plus an
1088 // estimate based on the last time those values were calculated.
1089 base::TimeDelta media_time =
1090 time_ref.is_null()
1091 ? time_min
1092 : CurrentMediaTime(time_min, time_max, time_ref,
1093 base::TimeTicks::Now(), playback_rate_);
1094
1095 // Clamp current media time to the last reported value, this prevents higher
1096 // level clients from seeing time go backwards based on inaccurate or spurious
1097 // delay values reported to the AudioClock.
1098 //
1099 // It is expected that such events are transient and will be recovered as
1100 // rendering continues over time.
1101 if (media_time < media_time_last_) {
1102 DVLOG(2) << __func__ << ": " << media_time_last_
1103 << " (clamped), actual: " << media_time;
1104 return media_time_last_;
1105 }
1106
1107 DVLOG(2) << __func__ << ": " << media_time;
1108 media_time_last_ = media_time;
1109 return media_time;
1064 } 1110 }
1065 1111
1066 Ranges<base::TimeDelta> PipelineImpl::GetBufferedTimeRanges() const { 1112 Ranges<base::TimeDelta> PipelineImpl::GetBufferedTimeRanges() const {
1067 DCHECK(thread_checker_.CalledOnValidThread()); 1113 DCHECK(thread_checker_.CalledOnValidThread());
1068 return renderer_wrapper_->GetBufferedTimeRanges(); 1114 return renderer_wrapper_->GetBufferedTimeRanges();
1069 } 1115 }
1070 1116
1071 base::TimeDelta PipelineImpl::GetMediaDuration() const { 1117 base::TimeDelta PipelineImpl::GetMediaDuration() const {
1072 DCHECK(thread_checker_.CalledOnValidThread()); 1118 DCHECK(thread_checker_.CalledOnValidThread());
1073 return duration_; 1119 return duration_;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 void PipelineImpl::OnSuspendDone() { 1275 void PipelineImpl::OnSuspendDone() {
1230 DVLOG(3) << __func__; 1276 DVLOG(3) << __func__;
1231 DCHECK(thread_checker_.CalledOnValidThread()); 1277 DCHECK(thread_checker_.CalledOnValidThread());
1232 DCHECK(IsRunning()); 1278 DCHECK(IsRunning());
1233 1279
1234 DCHECK(!suspend_cb_.is_null()); 1280 DCHECK(!suspend_cb_.is_null());
1235 base::ResetAndReturn(&suspend_cb_).Run(PIPELINE_OK); 1281 base::ResetAndReturn(&suspend_cb_).Run(PIPELINE_OK);
1236 } 1282 }
1237 1283
1238 } // namespace media 1284 } // namespace media
OLDNEW
« 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