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

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

Issue 12818004: Introduce VideoFrameStream, the video frame provider in media pipeline. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Prettier name for test. Created 7 years, 9 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
« no previous file with comments | « media/filters/video_renderer_base.h ('k') | media/filters/video_renderer_base_unittest.cc » ('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/filters/video_renderer_base.h" 5 #include "media/filters/video_renderer_base.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/threading/platform_thread.h" 11 #include "base/threading/platform_thread.h"
12 #include "media/base/buffers.h" 12 #include "media/base/buffers.h"
13 #include "media/base/limits.h" 13 #include "media/base/limits.h"
14 #include "media/base/pipeline.h" 14 #include "media/base/pipeline.h"
15 #include "media/base/video_frame.h" 15 #include "media/base/video_frame.h"
16 #include "media/filters/decrypting_demuxer_stream.h" 16 #include "media/filters/decrypting_demuxer_stream.h"
17 #include "media/filters/video_decoder_selector.h"
18 17
19 namespace media { 18 namespace media {
20 19
21 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { 20 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() {
22 return base::TimeDelta::FromMilliseconds(250); 21 return base::TimeDelta::FromMilliseconds(250);
23 } 22 }
24 23
25 VideoRendererBase::VideoRendererBase( 24 VideoRendererBase::VideoRendererBase(
26 const scoped_refptr<base::MessageLoopProxy>& message_loop, 25 const scoped_refptr<base::MessageLoopProxy>& message_loop,
27 const SetDecryptorReadyCB& set_decryptor_ready_cb, 26 const SetDecryptorReadyCB& set_decryptor_ready_cb,
28 const PaintCB& paint_cb, 27 const PaintCB& paint_cb,
29 const SetOpaqueCB& set_opaque_cb, 28 const SetOpaqueCB& set_opaque_cb,
30 bool drop_frames) 29 bool drop_frames)
31 : message_loop_(message_loop), 30 : message_loop_(message_loop),
32 weak_factory_(this), 31 weak_factory_(this),
33 set_decryptor_ready_cb_(set_decryptor_ready_cb), 32 video_frame_stream_(message_loop, set_decryptor_ready_cb),
34 received_end_of_stream_(false), 33 received_end_of_stream_(false),
35 frame_available_(&lock_), 34 frame_available_(&lock_),
36 state_(kUninitialized), 35 state_(kUninitialized),
37 thread_(base::kNullThreadHandle), 36 thread_(base::kNullThreadHandle),
38 pending_read_(false), 37 pending_read_(false),
39 drop_frames_(drop_frames), 38 drop_frames_(drop_frames),
40 playback_rate_(0), 39 playback_rate_(0),
41 paint_cb_(paint_cb), 40 paint_cb_(paint_cb),
42 set_opaque_cb_(set_opaque_cb), 41 set_opaque_cb_(set_opaque_cb),
43 last_timestamp_(kNoTimestamp()) { 42 last_timestamp_(kNoTimestamp()) {
(...skipping 22 matching lines...) Expand all
66 callback.Run(); 65 callback.Run();
67 } 66 }
68 67
69 void VideoRendererBase::Flush(const base::Closure& callback) { 68 void VideoRendererBase::Flush(const base::Closure& callback) {
70 DCHECK(message_loop_->BelongsToCurrentThread()); 69 DCHECK(message_loop_->BelongsToCurrentThread());
71 base::AutoLock auto_lock(lock_); 70 base::AutoLock auto_lock(lock_);
72 DCHECK_EQ(state_, kPaused); 71 DCHECK_EQ(state_, kPaused);
73 flush_cb_ = callback; 72 flush_cb_ = callback;
74 state_ = kFlushingDecoder; 73 state_ = kFlushingDecoder;
75 74
76 if (decrypting_demuxer_stream_) { 75 video_frame_stream_.Reset(base::Bind(
77 decrypting_demuxer_stream_->Reset(base::Bind( 76 &VideoRendererBase::OnVideoFrameStreamResetDone, weak_this_));
78 &VideoRendererBase::ResetDecoder, weak_this_));
79 return;
80 }
81
82 decoder_->Reset(base::Bind(
83 &VideoRendererBase::OnDecoderResetDone, weak_this_));
84 }
85
86 void VideoRendererBase::ResetDecoder() {
87 DCHECK(message_loop_->BelongsToCurrentThread());
88 base::AutoLock auto_lock(lock_);
89 decoder_->Reset(base::Bind(
90 &VideoRendererBase::OnDecoderResetDone, weak_this_));
91 } 77 }
92 78
93 void VideoRendererBase::Stop(const base::Closure& callback) { 79 void VideoRendererBase::Stop(const base::Closure& callback) {
94 DCHECK(message_loop_->BelongsToCurrentThread()); 80 DCHECK(message_loop_->BelongsToCurrentThread());
95 base::AutoLock auto_lock(lock_); 81 base::AutoLock auto_lock(lock_);
96 if (state_ == kUninitialized || state_ == kStopped) { 82 if (state_ == kUninitialized || state_ == kStopped) {
97 callback.Run(); 83 callback.Run();
98 return; 84 return;
99 } 85 }
100 86
(...skipping 13 matching lines...) Expand all
114 // thread waiting for a read to complete. 100 // thread waiting for a read to complete.
115 frame_available_.Signal(); 101 frame_available_.Signal();
116 std::swap(thread_, thread_to_join); 102 std::swap(thread_, thread_to_join);
117 } 103 }
118 104
119 if (thread_to_join != base::kNullThreadHandle) { 105 if (thread_to_join != base::kNullThreadHandle) {
120 base::AutoUnlock auto_unlock(lock_); 106 base::AutoUnlock auto_unlock(lock_);
121 base::PlatformThread::Join(thread_to_join); 107 base::PlatformThread::Join(thread_to_join);
122 } 108 }
123 109
124 if (decrypting_demuxer_stream_) { 110 video_frame_stream_.Stop(callback);
125 decrypting_demuxer_stream_->Reset(base::Bind(
126 &VideoRendererBase::StopDecoder, weak_this_, callback));
127 return;
128 }
129
130 if (decoder_) {
131 decoder_->Stop(callback);
132 return;
133 }
134
135 callback.Run();
136 }
137
138 void VideoRendererBase::StopDecoder(const base::Closure& callback) {
139 DCHECK(message_loop_->BelongsToCurrentThread());
140 base::AutoLock auto_lock(lock_);
141 decoder_->Stop(callback);
142 } 111 }
143 112
144 void VideoRendererBase::SetPlaybackRate(float playback_rate) { 113 void VideoRendererBase::SetPlaybackRate(float playback_rate) {
145 DCHECK(message_loop_->BelongsToCurrentThread()); 114 DCHECK(message_loop_->BelongsToCurrentThread());
146 base::AutoLock auto_lock(lock_); 115 base::AutoLock auto_lock(lock_);
147 playback_rate_ = playback_rate; 116 playback_rate_ = playback_rate;
148 } 117 }
149 118
150 void VideoRendererBase::Preroll(base::TimeDelta time, 119 void VideoRendererBase::Preroll(base::TimeDelta time,
151 const PipelineStatusCB& cb) { 120 const PipelineStatusCB& cb) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 init_cb_ = init_cb; 158 init_cb_ = init_cb;
190 statistics_cb_ = statistics_cb; 159 statistics_cb_ = statistics_cb;
191 max_time_cb_ = max_time_cb; 160 max_time_cb_ = max_time_cb;
192 size_changed_cb_ = size_changed_cb; 161 size_changed_cb_ = size_changed_cb;
193 ended_cb_ = ended_cb; 162 ended_cb_ = ended_cb;
194 error_cb_ = error_cb; 163 error_cb_ = error_cb;
195 get_time_cb_ = get_time_cb; 164 get_time_cb_ = get_time_cb;
196 get_duration_cb_ = get_duration_cb; 165 get_duration_cb_ = get_duration_cb;
197 state_ = kInitializing; 166 state_ = kInitializing;
198 167
199 scoped_ptr<VideoDecoderSelector> decoder_selector( 168 video_frame_stream_.Initialize(
200 new VideoDecoderSelector(base::MessageLoopProxy::current(),
201 decoders,
202 set_decryptor_ready_cb_));
203
204 // To avoid calling |decoder_selector| methods and passing ownership of
205 // |decoder_selector| in the same line.
206 VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get();
207
208 decoder_selector_ptr->SelectVideoDecoder(
209 stream, 169 stream,
170 decoders,
210 statistics_cb, 171 statistics_cb,
211 base::Bind(&VideoRendererBase::OnDecoderSelected, weak_this_, 172 base::Bind(&VideoRendererBase::OnVideoFrameStreamInitialized,
212 base::Passed(&decoder_selector))); 173 weak_this_));
213 } 174 }
214 175
215 void VideoRendererBase::OnDecoderSelected( 176 void VideoRendererBase::OnVideoFrameStreamInitialized(bool success,
216 scoped_ptr<VideoDecoderSelector> decoder_selector, 177 bool has_alpha) {
217 const scoped_refptr<VideoDecoder>& selected_decoder,
218 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) {
219 DCHECK(message_loop_->BelongsToCurrentThread()); 178 DCHECK(message_loop_->BelongsToCurrentThread());
220 base::AutoLock auto_lock(lock_); 179 base::AutoLock auto_lock(lock_);
221 180
222 if (state_ == kStopped) 181 if (state_ == kStopped)
223 return; 182 return;
224 183
225 DCHECK_EQ(state_, kInitializing); 184 DCHECK_EQ(state_, kInitializing);
226 185
227 if (!selected_decoder) { 186 if (!success) {
228 state_ = kUninitialized; 187 state_ = kUninitialized;
229 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 188 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
230 return; 189 return;
231 } 190 }
232 191
233 decoder_ = selected_decoder;
234 decrypting_demuxer_stream_ = decrypting_demuxer_stream;
235
236 // We're all good! Consider ourselves flushed. (ThreadMain() should never 192 // We're all good! Consider ourselves flushed. (ThreadMain() should never
237 // see us in the kUninitialized state). 193 // see us in the kUninitialized state).
238 // Since we had an initial Preroll(), we consider ourself flushed, because we 194 // Since we had an initial Preroll(), we consider ourself flushed, because we
239 // have not populated any buffers yet. 195 // have not populated any buffers yet.
240 state_ = kFlushed; 196 state_ = kFlushed;
241 197
242 set_opaque_cb_.Run(!decoder_->HasAlpha()); 198 set_opaque_cb_.Run(!has_alpha);
243 set_opaque_cb_.Reset(); 199 set_opaque_cb_.Reset();
244 200
245 // Create our video thread. 201 // Create our video thread.
246 if (!base::PlatformThread::Create(0, this, &thread_)) { 202 if (!base::PlatformThread::Create(0, this, &thread_)) {
247 NOTREACHED() << "Video thread creation failed"; 203 NOTREACHED() << "Video thread creation failed";
248 state_ = kError; 204 state_ = kError;
249 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 205 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
250 return; 206 return;
251 } 207 }
252 208
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 386
431 // Maintain the latest frame decoded so the correct frame is displayed after 387 // Maintain the latest frame decoded so the correct frame is displayed after
432 // prerolling has completed. 388 // prerolling has completed.
433 if (state_ == kPrerolling && frame->GetTimestamp() <= preroll_timestamp_) { 389 if (state_ == kPrerolling && frame->GetTimestamp() <= preroll_timestamp_) {
434 ready_frames_.clear(); 390 ready_frames_.clear();
435 } 391 }
436 392
437 AddReadyFrame_Locked(frame); 393 AddReadyFrame_Locked(frame);
438 394
439 if (state_ == kPrerolling) { 395 if (state_ == kPrerolling) {
440 if (!decoder_->HasOutputFrameAvailable() || 396 if (!video_frame_stream_.HasOutputFrameAvailable() ||
441 ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames)) { 397 ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames)) {
442 TransitionToPrerolled_Locked(); 398 TransitionToPrerolled_Locked();
443 } 399 }
444 } else { 400 } else {
445 // We only count frames decoded during normal playback. 401 // We only count frames decoded during normal playback.
446 PipelineStatistics statistics; 402 PipelineStatistics statistics;
447 statistics.video_frames_decoded = 1; 403 statistics.video_frames_decoded = 1;
448 statistics_cb_.Run(statistics); 404 statistics_cb_.Run(statistics);
449 } 405 }
450 406
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { 450 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) {
495 return; 451 return;
496 } 452 }
497 453
498 switch (state_) { 454 switch (state_) {
499 case kPaused: 455 case kPaused:
500 case kFlushing: 456 case kFlushing:
501 case kPrerolling: 457 case kPrerolling:
502 case kPlaying: 458 case kPlaying:
503 pending_read_ = true; 459 pending_read_ = true;
504 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, weak_this_)); 460 video_frame_stream_.ReadFrame(base::Bind(&VideoRendererBase::FrameReady,
461 weak_this_));
505 return; 462 return;
506 463
507 case kUninitialized: 464 case kUninitialized:
508 case kInitializing: 465 case kInitializing:
509 case kPrerolled: 466 case kPrerolled:
510 case kFlushingDecoder: 467 case kFlushingDecoder:
511 case kFlushed: 468 case kFlushed:
512 case kEnded: 469 case kEnded:
513 case kStopped: 470 case kStopped:
514 case kError: 471 case kError:
515 return; 472 return;
516 } 473 }
517 } 474 }
518 475
519 void VideoRendererBase::OnDecoderResetDone() { 476 void VideoRendererBase::OnVideoFrameStreamResetDone() {
520 base::AutoLock auto_lock(lock_); 477 base::AutoLock auto_lock(lock_);
521 if (state_ == kStopped) 478 if (state_ == kStopped)
522 return; 479 return;
523 480
524 DCHECK_EQ(kFlushingDecoder, state_); 481 DCHECK_EQ(kFlushingDecoder, state_);
525 DCHECK(!pending_read_); 482 DCHECK(!pending_read_);
526 483
527 state_ = kFlushing; 484 state_ = kFlushing;
528 AttemptFlush_Locked(); 485 AttemptFlush_Locked();
529 } 486 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 // Because we might remain in the prerolled state for an undetermined amount 528 // Because we might remain in the prerolled state for an undetermined amount
572 // of time (e.g., we seeked while paused), we'll paint the first prerolled 529 // of time (e.g., we seeked while paused), we'll paint the first prerolled
573 // frame. 530 // frame.
574 if (!ready_frames_.empty()) 531 if (!ready_frames_.empty())
575 PaintNextReadyFrame_Locked(); 532 PaintNextReadyFrame_Locked();
576 533
577 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); 534 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
578 } 535 }
579 536
580 } // namespace media 537 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/video_renderer_base.h ('k') | media/filters/video_renderer_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698