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), |
26 set_decryptor_ready_cb_(set_decryptor_ready_cb) { | 27 decoder_selector_( |
| 28 message_loop_, decoders.Pass(), 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 decoder_selector_.SelectVideoDecoder(this, statistics_cb, base::Bind( |
48 new VideoDecoderSelector(message_loop_, | 49 &VideoFrameStream::OnDecoderSelected, weak_this_)); |
49 decoders, | |
50 set_decryptor_ready_cb_)); | |
51 | |
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 | |
56 decoder_selector_ptr->SelectVideoDecoder( | |
57 this, | |
58 statistics_cb, | |
59 base::Bind(&VideoFrameStream::OnDecoderSelected, weak_this_, | |
60 base::Passed(&decoder_selector))); | |
61 } | 50 } |
62 | 51 |
63 void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { | 52 void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { |
64 DCHECK(message_loop_->BelongsToCurrentThread()); | 53 DCHECK(message_loop_->BelongsToCurrentThread()); |
65 DCHECK_EQ(state_, NORMAL); | 54 DCHECK_EQ(state_, NORMAL); |
66 // No two reads in the flight at any time. | 55 // No two reads in the flight at any time. |
67 DCHECK(read_cb_.is_null()); | 56 DCHECK(read_cb_.is_null()); |
68 // No read during resetting or stopping process. | 57 // No read during resetting or stopping process. |
69 DCHECK(reset_cb_.is_null()); | 58 DCHECK(reset_cb_.is_null()); |
70 DCHECK(stop_cb_.is_null()); | 59 DCHECK(stop_cb_.is_null()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 StopDecoder(); | 110 StopDecoder(); |
122 return; | 111 return; |
123 } | 112 } |
124 | 113 |
125 state_ = STOPPED; | 114 state_ = STOPPED; |
126 // Break the ref-count loop so we don't leak objects. | 115 // Break the ref-count loop so we don't leak objects. |
127 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so | 116 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so |
128 // we don't need this here. See: http://crbug.com/173313 | 117 // we don't need this here. See: http://crbug.com/173313 |
129 stream_ = NULL; | 118 stream_ = NULL; |
130 decrypting_demuxer_stream_ = NULL; | 119 decrypting_demuxer_stream_ = NULL; |
131 decoder_ = NULL; | 120 decoder_.reset(); |
132 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 121 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
133 } | 122 } |
134 | 123 |
135 bool VideoFrameStream::HasOutputFrameAvailable() const { | 124 bool VideoFrameStream::HasOutputFrameAvailable() const { |
136 DCHECK(message_loop_->BelongsToCurrentThread()); | 125 DCHECK(message_loop_->BelongsToCurrentThread()); |
137 return decoder_->HasOutputFrameAvailable(); | 126 return decoder_->HasOutputFrameAvailable(); |
138 } | 127 } |
139 | 128 |
140 void VideoFrameStream::Read(const ReadCB& read_cb) { | 129 void VideoFrameStream::Read(const ReadCB& read_cb) { |
141 DCHECK(message_loop_->BelongsToCurrentThread()); | 130 DCHECK(message_loop_->BelongsToCurrentThread()); |
(...skipping 15 matching lines...) Expand all Loading... |
157 DCHECK(message_loop_->BelongsToCurrentThread()); | 146 DCHECK(message_loop_->BelongsToCurrentThread()); |
158 return VIDEO; | 147 return VIDEO; |
159 } | 148 } |
160 | 149 |
161 void VideoFrameStream::EnableBitstreamConverter() { | 150 void VideoFrameStream::EnableBitstreamConverter() { |
162 DCHECK(message_loop_->BelongsToCurrentThread()); | 151 DCHECK(message_loop_->BelongsToCurrentThread()); |
163 stream_->EnableBitstreamConverter(); | 152 stream_->EnableBitstreamConverter(); |
164 } | 153 } |
165 | 154 |
166 void VideoFrameStream::OnDecoderSelected( | 155 void VideoFrameStream::OnDecoderSelected( |
167 scoped_ptr<VideoDecoderSelector> decoder_selector, | 156 scoped_ptr<VideoDecoder> selected_decoder, |
168 const scoped_refptr<VideoDecoder>& selected_decoder, | |
169 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { | 157 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { |
170 DCHECK(message_loop_->BelongsToCurrentThread()); | 158 DCHECK(message_loop_->BelongsToCurrentThread()); |
171 DCHECK_EQ(state_, UNINITIALIZED); | 159 DCHECK_EQ(state_, UNINITIALIZED); |
172 DCHECK(!init_cb_.is_null()); | 160 DCHECK(!init_cb_.is_null()); |
173 | 161 |
174 if (!selected_decoder) { | 162 if (!selected_decoder) { |
175 state_ = UNINITIALIZED; | 163 state_ = UNINITIALIZED; |
176 base::ResetAndReturn(&init_cb_).Run(false, false); | 164 base::ResetAndReturn(&init_cb_).Run(false, false); |
177 } else { | 165 } else { |
178 decoder_ = selected_decoder; | 166 decoder_ = selected_decoder.Pass(); |
179 decrypting_demuxer_stream_ = decrypting_demuxer_stream; | 167 decrypting_demuxer_stream_ = decrypting_demuxer_stream; |
180 state_ = NORMAL; | 168 state_ = NORMAL; |
181 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); | 169 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); |
182 } | 170 } |
183 | 171 |
184 // Stop() called during initialization. | 172 // Stop() called during initialization. |
185 if (!stop_cb_.is_null()) { | 173 if (!stop_cb_.is_null()) { |
186 Stop(base::ResetAndReturn(&stop_cb_)); | 174 Stop(base::ResetAndReturn(&stop_cb_)); |
187 return; | 175 return; |
188 } | 176 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 DCHECK(read_cb_.is_null()); | 220 DCHECK(read_cb_.is_null()); |
233 DCHECK(reset_cb_.is_null()); | 221 DCHECK(reset_cb_.is_null()); |
234 DCHECK(!stop_cb_.is_null()); | 222 DCHECK(!stop_cb_.is_null()); |
235 | 223 |
236 state_ = STOPPED; | 224 state_ = STOPPED; |
237 // Break the ref-count loop so we don't leak objects. | 225 // Break the ref-count loop so we don't leak objects. |
238 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so | 226 // TODO(scherkus): Make DemuxerStream and/or VideoDecoder not ref-counted so |
239 // we don't need this here. See: http://crbug.com/173313 | 227 // we don't need this here. See: http://crbug.com/173313 |
240 stream_ = NULL; | 228 stream_ = NULL; |
241 decrypting_demuxer_stream_ = NULL; | 229 decrypting_demuxer_stream_ = NULL; |
242 decoder_ = NULL; | 230 decoder_.reset(); |
243 base::ResetAndReturn(&stop_cb_).Run(); | 231 base::ResetAndReturn(&stop_cb_).Run(); |
244 } | 232 } |
245 | 233 |
246 } // namespace media | 234 } // namespace media |
OLD | NEW |