OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_frame_stream.h" | 5 #include "media/filters/video_frame_stream.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop_proxy.h" | 11 #include "base/message_loop_proxy.h" |
12 #include "media/base/bind_to_loop.h" | 12 #include "media/base/bind_to_loop.h" |
13 #include "media/base/demuxer_stream.h" | 13 #include "media/base/demuxer_stream.h" |
14 #include "media/base/video_decoder_config.h" | 14 #include "media/base/video_decoder_config.h" |
15 #include "media/filters/decrypting_demuxer_stream.h" | 15 #include "media/filters/decrypting_demuxer_stream.h" |
16 #include "media/filters/video_decoder_selector.h" | 16 #include "media/filters/video_decoder_selector.h" |
17 | 17 |
18 namespace media { | 18 namespace media { |
19 | 19 |
20 VideoFrameStream::VideoFrameStream( | 20 VideoFrameStream::VideoFrameStream( |
21 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 21 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| 22 ScopedVector<VideoDecoder> decoders, |
22 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 23 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
23 : message_loop_(message_loop), | 24 : message_loop_(message_loop), |
24 weak_factory_(this), | 25 weak_factory_(this), |
25 state_(UNINITIALIZED), | 26 state_(UNINITIALIZED), |
| 27 decoders_(decoders.Pass()), |
26 set_decryptor_ready_cb_(set_decryptor_ready_cb) { | 28 set_decryptor_ready_cb_(set_decryptor_ready_cb) { |
27 } | 29 } |
28 | 30 |
29 VideoFrameStream::~VideoFrameStream() { | 31 VideoFrameStream::~VideoFrameStream() { |
30 DCHECK(state_ == UNINITIALIZED || state_ == STOPPED) << state_; | 32 DCHECK(state_ == UNINITIALIZED || state_ == STOPPED) << state_; |
31 } | 33 } |
32 | 34 |
33 void VideoFrameStream::Initialize(const scoped_refptr<DemuxerStream>& stream, | 35 void VideoFrameStream::Initialize(const scoped_refptr<DemuxerStream>& stream, |
34 const VideoDecoderList& decoders, | |
35 const StatisticsCB& statistics_cb, | 36 const StatisticsCB& statistics_cb, |
36 const InitCB& init_cb) { | 37 const InitCB& init_cb) { |
37 DCHECK(message_loop_->BelongsToCurrentThread()); | 38 DCHECK(message_loop_->BelongsToCurrentThread()); |
38 DCHECK_EQ(state_, UNINITIALIZED); | 39 DCHECK_EQ(state_, UNINITIALIZED); |
39 | 40 |
40 weak_this_ = weak_factory_.GetWeakPtr(); | 41 weak_this_ = weak_factory_.GetWeakPtr(); |
41 | 42 |
42 DCHECK(init_cb_.is_null()); | 43 DCHECK(init_cb_.is_null()); |
43 DCHECK(!init_cb.is_null()); | 44 DCHECK(!init_cb.is_null()); |
44 init_cb_ = init_cb; | 45 init_cb_ = init_cb; |
45 stream_ = stream; | 46 stream_ = stream; |
46 | 47 |
47 scoped_ptr<VideoDecoderSelector> decoder_selector( | 48 // TODO(scherkus): Make |decoder_selector| a member variable after |
48 new VideoDecoderSelector(message_loop_, | 49 // DemuxerStream is no longer refcounted. Today we're forced to do this |
49 decoders, | 50 // because it creates a refcount loop between |this| and |decoder_selector|. |
50 set_decryptor_ready_cb_)); | 51 scoped_ptr<VideoDecoderSelector> decoder_selector(new VideoDecoderSelector( |
| 52 message_loop_, decoders_.Pass(), set_decryptor_ready_cb_)); |
| 53 set_decryptor_ready_cb_.Reset(); |
51 | 54 |
52 // To avoid calling |decoder_selector| methods and passing ownership of | |
53 // |decoder_selector| in the same line. | |
54 VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get(); | 55 VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get(); |
55 | 56 |
56 decoder_selector_ptr->SelectVideoDecoder( | 57 decoder_selector_ptr->SelectVideoDecoder(this, statistics_cb, base::Bind( |
57 this, | 58 &VideoFrameStream::OnDecoderSelected, weak_this_, |
58 statistics_cb, | 59 base::Passed(&decoder_selector))); |
59 base::Bind(&VideoFrameStream::OnDecoderSelected, weak_this_, | |
60 base::Passed(&decoder_selector))); | |
61 } | 60 } |
62 | 61 |
63 void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { | 62 void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { |
64 DCHECK(message_loop_->BelongsToCurrentThread()); | 63 DCHECK(message_loop_->BelongsToCurrentThread()); |
65 DCHECK_EQ(state_, NORMAL); | 64 DCHECK_EQ(state_, NORMAL); |
66 // No two reads in the flight at any time. | 65 // No two reads in the flight at any time. |
67 DCHECK(read_cb_.is_null()); | 66 DCHECK(read_cb_.is_null()); |
68 // No read during resetting or stopping process. | 67 // No read during resetting or stopping process. |
69 DCHECK(reset_cb_.is_null()); | 68 DCHECK(reset_cb_.is_null()); |
70 DCHECK(stop_cb_.is_null()); | 69 DCHECK(stop_cb_.is_null()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 StopDecoder(); | 120 StopDecoder(); |
122 return; | 121 return; |
123 } | 122 } |
124 | 123 |
125 state_ = STOPPED; | 124 state_ = STOPPED; |
126 // Break the ref-count loop so we don't leak objects. | 125 // Break the ref-count loop so we don't leak objects. |
127 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so | 126 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so |
128 // we don't need this here. See: http://crbug.com/173313 | 127 // we don't need this here. See: http://crbug.com/173313 |
129 stream_ = NULL; | 128 stream_ = NULL; |
130 decrypting_demuxer_stream_ = NULL; | 129 decrypting_demuxer_stream_ = NULL; |
131 decoder_ = NULL; | 130 decoder_.reset(); |
132 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 131 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
133 } | 132 } |
134 | 133 |
135 bool VideoFrameStream::HasOutputFrameAvailable() const { | 134 bool VideoFrameStream::HasOutputFrameAvailable() const { |
136 DCHECK(message_loop_->BelongsToCurrentThread()); | 135 DCHECK(message_loop_->BelongsToCurrentThread()); |
137 return decoder_->HasOutputFrameAvailable(); | 136 return decoder_->HasOutputFrameAvailable(); |
138 } | 137 } |
139 | 138 |
140 void VideoFrameStream::Read(const ReadCB& read_cb) { | 139 void VideoFrameStream::Read(const ReadCB& read_cb) { |
141 DCHECK(message_loop_->BelongsToCurrentThread()); | 140 DCHECK(message_loop_->BelongsToCurrentThread()); |
(...skipping 16 matching lines...) Expand all Loading... |
158 return VIDEO; | 157 return VIDEO; |
159 } | 158 } |
160 | 159 |
161 void VideoFrameStream::EnableBitstreamConverter() { | 160 void VideoFrameStream::EnableBitstreamConverter() { |
162 DCHECK(message_loop_->BelongsToCurrentThread()); | 161 DCHECK(message_loop_->BelongsToCurrentThread()); |
163 stream_->EnableBitstreamConverter(); | 162 stream_->EnableBitstreamConverter(); |
164 } | 163 } |
165 | 164 |
166 void VideoFrameStream::OnDecoderSelected( | 165 void VideoFrameStream::OnDecoderSelected( |
167 scoped_ptr<VideoDecoderSelector> decoder_selector, | 166 scoped_ptr<VideoDecoderSelector> decoder_selector, |
168 const scoped_refptr<VideoDecoder>& selected_decoder, | 167 scoped_ptr<VideoDecoder> selected_decoder, |
169 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { | 168 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { |
170 DCHECK(message_loop_->BelongsToCurrentThread()); | 169 DCHECK(message_loop_->BelongsToCurrentThread()); |
171 DCHECK_EQ(state_, UNINITIALIZED); | 170 DCHECK_EQ(state_, UNINITIALIZED); |
172 DCHECK(!init_cb_.is_null()); | 171 DCHECK(!init_cb_.is_null()); |
173 | 172 |
174 if (!selected_decoder) { | 173 if (!selected_decoder) { |
175 state_ = UNINITIALIZED; | 174 state_ = UNINITIALIZED; |
176 base::ResetAndReturn(&init_cb_).Run(false, false); | 175 base::ResetAndReturn(&init_cb_).Run(false, false); |
177 } else { | 176 } else { |
178 decoder_ = selected_decoder; | 177 decoder_ = selected_decoder.Pass(); |
179 decrypting_demuxer_stream_ = decrypting_demuxer_stream; | 178 decrypting_demuxer_stream_ = decrypting_demuxer_stream; |
180 state_ = NORMAL; | 179 state_ = NORMAL; |
181 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); | 180 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); |
182 } | 181 } |
183 | 182 |
184 // Stop() called during initialization. | 183 // Stop() called during initialization. |
185 if (!stop_cb_.is_null()) { | 184 if (!stop_cb_.is_null()) { |
186 Stop(base::ResetAndReturn(&stop_cb_)); | 185 Stop(base::ResetAndReturn(&stop_cb_)); |
187 return; | 186 return; |
188 } | 187 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 DCHECK(read_cb_.is_null()); | 231 DCHECK(read_cb_.is_null()); |
233 DCHECK(reset_cb_.is_null()); | 232 DCHECK(reset_cb_.is_null()); |
234 DCHECK(!stop_cb_.is_null()); | 233 DCHECK(!stop_cb_.is_null()); |
235 | 234 |
236 state_ = STOPPED; | 235 state_ = STOPPED; |
237 // Break the ref-count loop so we don't leak objects. | 236 // Break the ref-count loop so we don't leak objects. |
238 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so | 237 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so |
239 // we don't need this here. See: http://crbug.com/173313 | 238 // we don't need this here. See: http://crbug.com/173313 |
240 stream_ = NULL; | 239 stream_ = NULL; |
241 decrypting_demuxer_stream_ = NULL; | 240 decrypting_demuxer_stream_ = NULL; |
242 decoder_ = NULL; | 241 decoder_.reset(); |
243 base::ResetAndReturn(&stop_cb_).Run(); | 242 base::ResetAndReturn(&stop_cb_).Run(); |
244 } | 243 } |
245 | 244 |
246 } // namespace media | 245 } // namespace media |
OLD | NEW |