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

Side by Side Diff: media/filters/video_renderer_base.cc

Issue 10796074: Move VideoRenderer out of Filter heirarchy. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: Created 8 years, 5 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 | Annotate | Revision Log
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/filters/video_renderer_base.h"
6
5 #include "base/bind.h" 7 #include "base/bind.h"
6 #include "base/callback.h" 8 #include "base/callback.h"
7 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
8 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
9 #include "media/base/buffers.h" 11 #include "media/base/buffers.h"
10 #include "media/base/filter_host.h"
11 #include "media/base/limits.h" 12 #include "media/base/limits.h"
12 #include "media/base/pipeline.h" 13 #include "media/base/pipeline.h"
13 #include "media/base/video_frame.h" 14 #include "media/base/video_frame.h"
14 #include "media/filters/video_renderer_base.h"
15 15
16 namespace media { 16 namespace media {
17 17
18 VideoRendererBase::VideoRendererBase(const base::Closure& paint_cb, 18 VideoRendererBase::VideoRendererBase(const base::Closure& paint_cb,
19 const SetOpaqueCB& set_opaque_cb, 19 const SetOpaqueCB& set_opaque_cb,
20 bool drop_frames) 20 bool drop_frames)
21 : host_(NULL), 21 : frame_available_(&lock_),
22 frame_available_(&lock_),
23 state_(kUninitialized), 22 state_(kUninitialized),
24 thread_(base::kNullThreadHandle), 23 thread_(base::kNullThreadHandle),
25 pending_read_(false), 24 pending_read_(false),
26 pending_paint_(false), 25 pending_paint_(false),
27 pending_paint_with_last_available_(false), 26 pending_paint_with_last_available_(false),
28 drop_frames_(drop_frames), 27 drop_frames_(drop_frames),
29 playback_rate_(0), 28 playback_rate_(0),
30 paint_cb_(paint_cb), 29 paint_cb_(paint_cb),
31 set_opaque_cb_(set_opaque_cb) { 30 set_opaque_cb_(set_opaque_cb) {
32 DCHECK(!paint_cb_.is_null()); 31 DCHECK(!paint_cb_.is_null());
33 } 32 }
34 33
35 void VideoRendererBase::SetHost(FilterHost* host) {
36 DCHECK(host);
37 DCHECK(!host_);
38 host_ = host;
39 }
40
41 void VideoRendererBase::Play(const base::Closure& callback) { 34 void VideoRendererBase::Play(const base::Closure& callback) {
42 base::AutoLock auto_lock(lock_); 35 base::AutoLock auto_lock(lock_);
43 DCHECK_EQ(kPrerolled, state_); 36 DCHECK_EQ(kPrerolled, state_);
44 state_ = kPlaying; 37 state_ = kPlaying;
45 callback.Run(); 38 callback.Run();
46 } 39 }
47 40
48 void VideoRendererBase::Pause(const base::Closure& callback) { 41 void VideoRendererBase::Pause(const base::Closure& callback) {
49 base::AutoLock auto_lock(lock_); 42 base::AutoLock auto_lock(lock_);
50 DCHECK(state_ != kUninitialized || state_ == kError); 43 DCHECK(state_ != kUninitialized || state_ == kError);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 102
110 state_ = kSeeking; 103 state_ = kSeeking;
111 seek_cb_ = cb; 104 seek_cb_ = cb;
112 seek_timestamp_ = time; 105 seek_timestamp_ = time;
113 AttemptRead_Locked(); 106 AttemptRead_Locked();
114 } 107 }
115 108
116 void VideoRendererBase::Initialize(const scoped_refptr<VideoDecoder>& decoder, 109 void VideoRendererBase::Initialize(const scoped_refptr<VideoDecoder>& decoder,
117 const PipelineStatusCB& status_cb, 110 const PipelineStatusCB& status_cb,
118 const StatisticsCB& statistics_cb, 111 const StatisticsCB& statistics_cb,
119 const TimeCB& time_cb) { 112 const TimeCB& time_cb,
113 const NaturalSizeChangedCB& size_changed_cb,
114 const base::Closure& ended_cb,
115 const PipelineStatusCB& error_cb,
116 const TimeDeltaCB& get_time_cb,
117 const TimeDeltaCB& get_duration_cb) {
120 base::AutoLock auto_lock(lock_); 118 base::AutoLock auto_lock(lock_);
121 DCHECK(decoder); 119 DCHECK(decoder);
122 DCHECK(!status_cb.is_null()); 120 DCHECK(!status_cb.is_null());
123 DCHECK(!statistics_cb.is_null()); 121 DCHECK(!statistics_cb.is_null());
124 DCHECK(!time_cb.is_null()); 122 DCHECK(!time_cb.is_null());
123 DCHECK(!size_changed_cb.is_null());
124 DCHECK(!ended_cb.is_null());
125 DCHECK(!get_time_cb.is_null());
126 DCHECK(!get_duration_cb.is_null());
125 DCHECK_EQ(kUninitialized, state_); 127 DCHECK_EQ(kUninitialized, state_);
126 decoder_ = decoder; 128 decoder_ = decoder;
127 129
128 statistics_cb_ = statistics_cb; 130 statistics_cb_ = statistics_cb;
129 time_cb_ = time_cb; 131 time_cb_ = time_cb;
132 size_changed_cb_ = size_changed_cb;
133 ended_cb_ = ended_cb;
134 error_cb_ = error_cb;
135 get_time_cb_ = get_time_cb;
136 get_duration_cb_ = get_duration_cb;
130 137
131 // Notify the pipeline of the video dimensions. 138 // Notify the pipeline of the video dimensions.
132 host_->SetNaturalVideoSize(decoder_->natural_size()); 139 size_changed_cb_.Run(decoder_->natural_size());
133 140
134 // We're all good! Consider ourselves flushed. (ThreadMain() should never 141 // We're all good! Consider ourselves flushed. (ThreadMain() should never
135 // see us in the kUninitialized state). 142 // see us in the kUninitialized state).
136 // Since we had an initial Seek, we consider ourself flushed, because we 143 // Since we had an initial Seek, we consider ourself flushed, because we
137 // have not populated any buffers yet. 144 // have not populated any buffers yet.
138 state_ = kFlushed; 145 state_ = kFlushed;
139 146
140 set_opaque_cb_.Run(!decoder->HasAlpha()); 147 set_opaque_cb_.Run(!decoder->HasAlpha());
141 set_opaque_cb_.Reset(); 148 set_opaque_cb_.Reset();
142 149
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 if (ready_frames_.empty()) { 208 if (ready_frames_.empty()) {
202 frame_available_.TimedWait(kIdleTimeDelta); 209 frame_available_.TimedWait(kIdleTimeDelta);
203 continue; 210 continue;
204 } 211 }
205 212
206 // Remain idle until we've initialized |current_frame_| via prerolling. 213 // Remain idle until we've initialized |current_frame_| via prerolling.
207 if (!current_frame_) { 214 if (!current_frame_) {
208 // This can happen if our preroll only contains end of stream frames. 215 // This can happen if our preroll only contains end of stream frames.
209 if (ready_frames_.front()->IsEndOfStream()) { 216 if (ready_frames_.front()->IsEndOfStream()) {
210 state_ = kEnded; 217 state_ = kEnded;
211 host_->NotifyEnded(); 218 ended_cb_.Run();
212 ready_frames_.clear(); 219 ready_frames_.clear();
213 220
214 // No need to sleep here as we idle when |state_ != kPlaying|. 221 // No need to sleep here as we idle when |state_ != kPlaying|.
215 continue; 222 continue;
216 } 223 }
217 224
218 frame_available_.TimedWait(kIdleTimeDelta); 225 frame_available_.TimedWait(kIdleTimeDelta);
219 continue; 226 continue;
220 } 227 }
221 228
(...skipping 18 matching lines...) Expand all
240 // of time and also have the next frame that ready for rendering. 247 // of time and also have the next frame that ready for rendering.
241 248
242 249
243 // If the next frame is end of stream then we are truly at the end of the 250 // If the next frame is end of stream then we are truly at the end of the
244 // video stream. 251 // video stream.
245 // 252 //
246 // TODO(scherkus): deduplicate this end of stream check after we get rid of 253 // TODO(scherkus): deduplicate this end of stream check after we get rid of
247 // |current_frame_|. 254 // |current_frame_|.
248 if (ready_frames_.front()->IsEndOfStream()) { 255 if (ready_frames_.front()->IsEndOfStream()) {
249 state_ = kEnded; 256 state_ = kEnded;
250 host_->NotifyEnded(); 257 ended_cb_.Run();
251 ready_frames_.clear(); 258 ready_frames_.clear();
252 259
253 // No need to sleep here as we idle when |state_ != kPlaying|. 260 // No need to sleep here as we idle when |state_ != kPlaying|.
254 continue; 261 continue;
255 } 262 }
256 263
257 // We cannot update |current_frame_| until we've completed the pending 264 // We cannot update |current_frame_| until we've completed the pending
258 // paint. Furthermore, the pending paint might be really slow: check to 265 // paint. Furthermore, the pending paint might be really slow: check to
259 // see if we have any ready frames that we can drop if they've already 266 // see if we have any ready frames that we can drop if they've already
260 // expired. 267 // expired.
261 if (pending_paint_) { 268 if (pending_paint_) {
262 while (!ready_frames_.empty()) { 269 while (!ready_frames_.empty()) {
263 // Can't drop anything if we're at the end. 270 // Can't drop anything if we're at the end.
264 if (ready_frames_.front()->IsEndOfStream()) 271 if (ready_frames_.front()->IsEndOfStream())
265 break; 272 break;
266 273
267 base::TimeDelta remaining_time = 274 base::TimeDelta remaining_time =
268 ready_frames_.front()->GetTimestamp() - host_->GetTime(); 275 ready_frames_.front()->GetTimestamp() - get_time_cb_.Run();
269 276
270 // Still a chance we can render the frame! 277 // Still a chance we can render the frame!
271 if (remaining_time.InMicroseconds() > 0) 278 if (remaining_time.InMicroseconds() > 0)
272 break; 279 break;
273 280
274 if (!drop_frames_) 281 if (!drop_frames_)
275 break; 282 break;
276 283
277 // Frame dropped: read again. 284 // Frame dropped: read again.
278 ++frames_dropped; 285 ++frames_dropped;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 DCHECK(!frame); 384 DCHECK(!frame);
378 PipelineStatus error = PIPELINE_ERROR_DECODE; 385 PipelineStatus error = PIPELINE_ERROR_DECODE;
379 if (status == VideoDecoder::kDecryptError) 386 if (status == VideoDecoder::kDecryptError)
380 error = PIPELINE_ERROR_DECRYPT; 387 error = PIPELINE_ERROR_DECRYPT;
381 388
382 if (!seek_cb_.is_null()) { 389 if (!seek_cb_.is_null()) {
383 base::ResetAndReturn(&seek_cb_).Run(error); 390 base::ResetAndReturn(&seek_cb_).Run(error);
384 return; 391 return;
385 } 392 }
386 393
387 host_->SetError(error); 394 error_cb_.Run(error);
388 return; 395 return;
389 } 396 }
390 397
391 // Already-queued Decoder ReadCB's can fire after various state transitions 398 // Already-queued Decoder ReadCB's can fire after various state transitions
392 // have happened; in that case just drop those frames immediately. 399 // have happened; in that case just drop those frames immediately.
393 if (state_ == kStopped || state_ == kError || state_ == kFlushed || 400 if (state_ == kStopped || state_ == kError || state_ == kFlushed ||
394 state_ == kFlushingDecoder) 401 state_ == kFlushingDecoder)
395 return; 402 return;
396 403
397 if (state_ == kFlushing) { 404 if (state_ == kFlushing) {
(...skipping 19 matching lines...) Expand all
417 AttemptRead_Locked(); 424 AttemptRead_Locked();
418 return; 425 return;
419 } 426 }
420 427
421 // Adjust the incoming frame if its rendering stop time is past the duration 428 // Adjust the incoming frame if its rendering stop time is past the duration
422 // of the video itself. This is typically the last frame of the video and 429 // of the video itself. This is typically the last frame of the video and
423 // occurs if the container specifies a duration that isn't a multiple of the 430 // occurs if the container specifies a duration that isn't a multiple of the
424 // frame rate. Another way for this to happen is for the container to state a 431 // frame rate. Another way for this to happen is for the container to state a
425 // smaller duration than the largest packet timestamp. 432 // smaller duration than the largest packet timestamp.
426 if (!frame->IsEndOfStream()) { 433 if (!frame->IsEndOfStream()) {
427 if (frame->GetTimestamp() > host_->GetDuration()) 434 base::TimeDelta duration = get_duration_cb_.Run();
428 frame->SetTimestamp(host_->GetDuration()); 435 if (frame->GetTimestamp() > duration)
429 if ((frame->GetTimestamp() + frame->GetDuration()) > host_->GetDuration()) 436 frame->SetTimestamp(duration);
430 frame->SetDuration(host_->GetDuration() - frame->GetTimestamp()); 437 if ((frame->GetTimestamp() + frame->GetDuration()) > duration)
438 frame->SetDuration(duration - frame->GetTimestamp());
431 } 439 }
432 440
433 // This one's a keeper! Place it in the ready queue. 441 // This one's a keeper! Place it in the ready queue.
434 ready_frames_.push_back(frame); 442 ready_frames_.push_back(frame);
435 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); 443 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames);
436 if (!frame->IsEndOfStream()) 444 if (!frame->IsEndOfStream())
437 time_cb_.Run(frame->GetTimestamp() + frame->GetDuration()); 445 time_cb_.Run(frame->GetTimestamp() + frame->GetDuration());
438 frame_available_.Signal(); 446 frame_available_.Signal();
439 447
440 PipelineStatistics statistics; 448 PipelineStatistics statistics;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 state_ = kFlushed; 517 state_ = kFlushed;
510 current_frame_ = NULL; 518 current_frame_ = NULL;
511 base::ResetAndReturn(&flush_cb_).Run(); 519 base::ResetAndReturn(&flush_cb_).Run();
512 } 520 }
513 } 521 }
514 522
515 base::TimeDelta VideoRendererBase::CalculateSleepDuration( 523 base::TimeDelta VideoRendererBase::CalculateSleepDuration(
516 const scoped_refptr<VideoFrame>& next_frame, 524 const scoped_refptr<VideoFrame>& next_frame,
517 float playback_rate) { 525 float playback_rate) {
518 // Determine the current and next presentation timestamps. 526 // Determine the current and next presentation timestamps.
519 base::TimeDelta now = host_->GetTime(); 527 base::TimeDelta now = get_time_cb_.Run();
520 base::TimeDelta this_pts = current_frame_->GetTimestamp(); 528 base::TimeDelta this_pts = current_frame_->GetTimestamp();
521 base::TimeDelta next_pts; 529 base::TimeDelta next_pts;
522 if (!next_frame->IsEndOfStream()) { 530 if (!next_frame->IsEndOfStream()) {
523 next_pts = next_frame->GetTimestamp(); 531 next_pts = next_frame->GetTimestamp();
524 } else { 532 } else {
525 next_pts = this_pts + current_frame_->GetDuration(); 533 next_pts = this_pts + current_frame_->GetDuration();
526 } 534 }
527 535
528 // Scale our sleep based on the playback rate. 536 // Scale our sleep based on the playback rate.
529 base::TimeDelta sleep = next_pts - now; 537 base::TimeDelta sleep = next_pts - now;
(...skipping 12 matching lines...) Expand all
542 550
543 int VideoRendererBase::NumFrames_Locked() const { 551 int VideoRendererBase::NumFrames_Locked() const {
544 lock_.AssertAcquired(); 552 lock_.AssertAcquired();
545 int outstanding_frames = 553 int outstanding_frames =
546 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + 554 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) +
547 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); 555 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0);
548 return ready_frames_.size() + outstanding_frames; 556 return ready_frames_.size() + outstanding_frames;
549 } 557 }
550 558
551 } // namespace media 559 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698