OLD | NEW |
---|---|
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/decrypting_video_decoder.h" | 5 #include "media/filters/decrypting_video_decoder.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/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
13 #include "media/base/bind_to_loop.h" | 13 #include "media/base/bind_to_loop.h" |
14 #include "media/base/decoder_buffer.h" | 14 #include "media/base/decoder_buffer.h" |
15 #include "media/base/decryptor.h" | 15 #include "media/base/decryptor.h" |
16 #include "media/base/demuxer_stream.h" | 16 #include "media/base/demuxer_stream.h" |
17 #include "media/base/pipeline.h" | 17 #include "media/base/pipeline.h" |
18 #include "media/base/video_decoder_config.h" | 18 #include "media/base/video_decoder_config.h" |
19 #include "media/base/video_frame.h" | 19 #include "media/base/video_frame.h" |
20 | 20 |
21 namespace media { | 21 namespace media { |
22 | 22 |
23 #define BIND_TO_LOOP(function) \ | |
24 media::BindToLoop(message_loop_, base::Bind(function, this)) | |
25 | |
26 DecryptingVideoDecoder::DecryptingVideoDecoder( | 23 DecryptingVideoDecoder::DecryptingVideoDecoder( |
27 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 24 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
28 const RequestDecryptorNotificationCB& request_decryptor_notification_cb) | 25 const RequestDecryptorNotificationCB& request_decryptor_notification_cb) |
29 : message_loop_(message_loop), | 26 : message_loop_(message_loop), |
30 state_(kUninitialized), | 27 state_(kUninitialized), |
31 request_decryptor_notification_cb_(request_decryptor_notification_cb), | 28 request_decryptor_notification_cb_(request_decryptor_notification_cb), |
32 decryptor_(NULL), | 29 decryptor_(NULL), |
33 key_added_while_decode_pending_(false), | 30 key_added_while_decode_pending_(false), |
34 trace_id_(0) { | 31 trace_id_(0) { |
35 } | 32 } |
36 | 33 |
37 void DecryptingVideoDecoder::Initialize( | 34 void DecryptingVideoDecoder::Initialize( |
38 const scoped_refptr<DemuxerStream>& stream, | 35 const scoped_refptr<DemuxerStream>& stream, |
39 const PipelineStatusCB& status_cb, | 36 const PipelineStatusCB& status_cb, |
40 const StatisticsCB& statistics_cb) { | 37 const StatisticsCB& statistics_cb) { |
41 if (!message_loop_->BelongsToCurrentThread()) { | 38 DVLOG(2) << "Initialize()"; |
42 message_loop_->PostTask(FROM_HERE, base::Bind( | 39 DCHECK(message_loop_->BelongsToCurrentThread()); |
43 &DecryptingVideoDecoder::DoInitialize, this, | 40 DCHECK_EQ(state_, kUninitialized) << state_; |
44 stream, status_cb, statistics_cb)); | 41 DCHECK(stream); |
42 init_cb_ = BindToCurrentLoop(status_cb); | |
43 | |
44 const VideoDecoderConfig& config = stream->video_decoder_config(); | |
45 if (!config.IsValidConfig()) { | |
46 DLOG(ERROR) << "Invalid video stream config: " | |
47 << config.AsHumanReadableString(); | |
48 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); | |
45 return; | 49 return; |
46 } | 50 } |
47 DoInitialize(stream, status_cb, statistics_cb); | 51 |
52 // DecryptingVideoDecoder only accepts potentially encrypted stream. | |
53 if (!config.is_encrypted()) { | |
54 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | |
55 return; | |
56 } | |
57 | |
58 DCHECK(!demuxer_stream_); | |
59 demuxer_stream_ = stream; | |
60 statistics_cb_ = statistics_cb; | |
61 | |
62 state_ = kDecryptorRequested; | |
63 request_decryptor_notification_cb_.Run(BindToCurrentLoop(base::Bind( | |
64 &DecryptingVideoDecoder::SetDecryptor, this))); | |
48 } | 65 } |
49 | 66 |
50 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { | 67 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { |
51 // Complete operation asynchronously on different stack of execution as per | 68 DVLOG(3) << "Read()"; |
52 // the API contract of VideoDecoder::Read() | 69 DCHECK(message_loop_->BelongsToCurrentThread()); |
53 message_loop_->PostTask(FROM_HERE, base::Bind( | 70 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
54 &DecryptingVideoDecoder::DoRead, this, read_cb)); | 71 DCHECK(!read_cb.is_null()); |
72 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | |
73 read_cb_ = BindToCurrentLoop(read_cb); | |
74 | |
75 // Return empty frames if decoding has finished. | |
76 if (state_ == kDecodeFinished) { | |
77 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); | |
78 return; | |
79 } | |
80 | |
81 state_ = kPendingDemuxerRead; | |
82 ReadFromDemuxerStream(); | |
55 } | 83 } |
56 | 84 |
57 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { | 85 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { |
58 if (!message_loop_->BelongsToCurrentThread()) { | |
59 message_loop_->PostTask(FROM_HERE, base::Bind( | |
60 &DecryptingVideoDecoder::Reset, this, closure)); | |
61 return; | |
62 } | |
63 | |
64 DVLOG(2) << "Reset() - state: " << state_; | 86 DVLOG(2) << "Reset() - state: " << state_; |
87 DCHECK(message_loop_->BelongsToCurrentThread()); | |
65 DCHECK(state_ == kIdle || | 88 DCHECK(state_ == kIdle || |
66 state_ == kPendingDemuxerRead || | 89 state_ == kPendingDemuxerRead || |
67 state_ == kPendingDecode || | 90 state_ == kPendingDecode || |
68 state_ == kWaitingForKey || | 91 state_ == kWaitingForKey || |
69 state_ == kDecodeFinished) << state_; | 92 state_ == kDecodeFinished) << state_; |
70 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 93 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
71 DCHECK(reset_cb_.is_null()); | 94 DCHECK(reset_cb_.is_null()); |
72 | 95 |
73 reset_cb_ = closure; | 96 reset_cb_ = BindToCurrentLoop(closure); |
74 | 97 |
75 decryptor_->ResetDecoder(Decryptor::kVideo); | 98 decryptor_->ResetDecoder(Decryptor::kVideo); |
76 | 99 |
77 // Reset() cannot complete if the read callback is still pending. | 100 // Reset() cannot complete if the read callback is still pending. |
78 // Defer the resetting process in this case. The |reset_cb_| will be fired | 101 // Defer the resetting process in this case. The |reset_cb_| will be fired |
79 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and | 102 // after the read callback is fired - see DecryptAndDecodeBuffer() and |
80 // DoDeliverFrame(). | 103 // DeliverFrame(). |
81 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { | 104 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { |
82 DCHECK(!read_cb_.is_null()); | 105 DCHECK(!read_cb_.is_null()); |
83 return; | 106 return; |
84 } | 107 } |
85 | 108 |
86 if (state_ == kWaitingForKey) { | 109 if (state_ == kWaitingForKey) { |
87 DCHECK(!read_cb_.is_null()); | 110 DCHECK(!read_cb_.is_null()); |
88 pending_buffer_to_decode_ = NULL; | 111 pending_buffer_to_decode_ = NULL; |
89 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 112 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
90 } | 113 } |
91 | 114 |
92 DCHECK(read_cb_.is_null()); | 115 DCHECK(read_cb_.is_null()); |
93 DoReset(); | 116 DoReset(); |
94 } | 117 } |
95 | 118 |
96 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { | 119 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { |
97 if (!message_loop_->BelongsToCurrentThread()) { | 120 DCHECK(message_loop_->BelongsToCurrentThread()); |
98 message_loop_->PostTask(FROM_HERE, base::Bind( | |
99 &DecryptingVideoDecoder::Stop, this, closure)); | |
100 return; | |
101 } | |
102 | |
103 DVLOG(2) << "Stop() - state: " << state_; | 121 DVLOG(2) << "Stop() - state: " << state_; |
104 | 122 |
105 // At this point the render thread is likely paused (in WebMediaPlayerImpl's | 123 // At this point the render thread is likely paused (in WebMediaPlayerImpl's |
106 // Destroy()), so running |closure| can't wait for anything that requires the | 124 // Destroy()), so running |closure| can't wait for anything that requires the |
107 // render thread to be processing messages to complete (such as PPAPI | 125 // render thread to be processing messages to complete (such as PPAPI |
108 // callbacks). | 126 // callbacks). |
109 if (decryptor_) { | 127 if (decryptor_) { |
110 decryptor_->RegisterKeyAddedCB(Decryptor::kVideo, Decryptor::KeyAddedCB()); | 128 decryptor_->RegisterKeyAddedCB(Decryptor::kVideo, Decryptor::KeyAddedCB()); |
111 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 129 decryptor_->DeinitializeDecoder(Decryptor::kVideo); |
112 decryptor_ = NULL; | 130 decryptor_ = NULL; |
113 } | 131 } |
114 if (!request_decryptor_notification_cb_.is_null()) { | 132 if (!request_decryptor_notification_cb_.is_null()) { |
115 base::ResetAndReturn(&request_decryptor_notification_cb_).Run( | 133 base::ResetAndReturn(&request_decryptor_notification_cb_).Run( |
116 DecryptorNotificationCB()); | 134 DecryptorNotificationCB()); |
117 } | 135 } |
118 pending_buffer_to_decode_ = NULL; | 136 pending_buffer_to_decode_ = NULL; |
119 if (!init_cb_.is_null()) | 137 if (!init_cb_.is_null()) |
120 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 138 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
121 if (!read_cb_.is_null()) | 139 if (!read_cb_.is_null()) |
122 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 140 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
123 if (!reset_cb_.is_null()) | 141 if (!reset_cb_.is_null()) |
124 base::ResetAndReturn(&reset_cb_).Run(); | 142 base::ResetAndReturn(&reset_cb_).Run(); |
125 state_ = kStopped; | 143 state_ = kStopped; |
126 closure.Run(); | 144 BindToCurrentLoop(closure).Run(); |
xhwang
2012/12/07 01:21:07
Is this used to force posting the task to prevent
scherkus (not reviewing)
2012/12/07 01:43:16
I agree the naming could be better but I'd like to
xhwang
2012/12/07 02:22:19
SGTM
| |
127 } | 145 } |
128 | 146 |
129 DecryptingVideoDecoder::~DecryptingVideoDecoder() { | 147 DecryptingVideoDecoder::~DecryptingVideoDecoder() { |
130 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 148 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; |
131 } | 149 } |
132 | 150 |
133 void DecryptingVideoDecoder::DoInitialize( | |
134 const scoped_refptr<DemuxerStream>& stream, | |
135 const PipelineStatusCB& status_cb, | |
136 const StatisticsCB& statistics_cb) { | |
137 DVLOG(2) << "DoInitialize()"; | |
138 DCHECK(message_loop_->BelongsToCurrentThread()); | |
139 DCHECK_EQ(state_, kUninitialized) << state_; | |
140 DCHECK(stream); | |
141 | |
142 const VideoDecoderConfig& config = stream->video_decoder_config(); | |
143 if (!config.IsValidConfig()) { | |
144 DLOG(ERROR) << "Invalid video stream config: " | |
145 << config.AsHumanReadableString(); | |
146 status_cb.Run(PIPELINE_ERROR_DECODE); | |
147 return; | |
148 } | |
149 | |
150 // DecryptingVideoDecoder only accepts potentially encrypted stream. | |
151 if (!config.is_encrypted()) { | |
152 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | |
153 return; | |
154 } | |
155 | |
156 DCHECK(!demuxer_stream_); | |
157 demuxer_stream_ = stream; | |
158 statistics_cb_ = statistics_cb; | |
159 | |
160 init_cb_ = status_cb; | |
161 | |
162 state_ = kDecryptorRequested; | |
163 request_decryptor_notification_cb_.Run( | |
164 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor)); | |
165 } | |
166 | |
167 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { | 151 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { |
168 DVLOG(2) << "SetDecryptor()"; | 152 DVLOG(2) << "SetDecryptor()"; |
169 DCHECK(message_loop_->BelongsToCurrentThread()); | 153 DCHECK(message_loop_->BelongsToCurrentThread()); |
170 | 154 |
171 if (state_ == kStopped) | 155 if (state_ == kStopped) |
172 return; | 156 return; |
173 | 157 |
174 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 158 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
175 DCHECK(!init_cb_.is_null()); | 159 DCHECK(!init_cb_.is_null()); |
176 DCHECK(!request_decryptor_notification_cb_.is_null()); | 160 DCHECK(!request_decryptor_notification_cb_.is_null()); |
177 request_decryptor_notification_cb_.Reset(); | 161 request_decryptor_notification_cb_.Reset(); |
178 | 162 |
179 decryptor_ = decryptor; | 163 decryptor_ = decryptor; |
180 | 164 |
181 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); | 165 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); |
182 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); | 166 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); |
183 | 167 |
184 state_ = kPendingDecoderInit; | 168 state_ = kPendingDecoderInit; |
185 decryptor_->InitializeVideoDecoder( | 169 decryptor_->InitializeVideoDecoder( |
186 scoped_config.Pass(), | 170 scoped_config.Pass(), BindToCurrentLoop(base::Bind( |
187 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization)); | 171 &DecryptingVideoDecoder::FinishInitialization, this))); |
188 } | 172 } |
189 | 173 |
190 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 174 void DecryptingVideoDecoder::FinishInitialization(bool success) { |
191 DVLOG(2) << "FinishInitialization()"; | 175 DVLOG(2) << "FinishInitialization()"; |
192 DCHECK(message_loop_->BelongsToCurrentThread()); | 176 DCHECK(message_loop_->BelongsToCurrentThread()); |
193 | 177 |
194 if (state_ == kStopped) | 178 if (state_ == kStopped) |
195 return; | 179 return; |
196 | 180 |
197 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 181 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
198 DCHECK(!init_cb_.is_null()); | 182 DCHECK(!init_cb_.is_null()); |
199 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 183 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
200 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 184 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
201 | 185 |
202 if (!success) { | 186 if (!success) { |
203 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 187 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
204 state_ = kStopped; | 188 state_ = kStopped; |
205 return; | 189 return; |
206 } | 190 } |
207 | 191 |
208 decryptor_->RegisterKeyAddedCB( | 192 decryptor_->RegisterKeyAddedCB(Decryptor::kVideo, BindToCurrentLoop( |
209 Decryptor::kVideo, BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); | 193 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, this))); |
210 | 194 |
211 // Success! | 195 // Success! |
212 state_ = kIdle; | 196 state_ = kIdle; |
213 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 197 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
214 } | 198 } |
215 | 199 |
216 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { | |
217 DVLOG(3) << "DoRead()"; | |
218 DCHECK(message_loop_->BelongsToCurrentThread()); | |
219 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | |
220 DCHECK(!read_cb.is_null()); | |
221 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | |
222 | |
223 // Return empty frames if decoding has finished. | |
224 if (state_ == kDecodeFinished) { | |
225 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); | |
226 return; | |
227 } | |
228 | |
229 read_cb_ = read_cb; | |
230 state_ = kPendingDemuxerRead; | |
231 ReadFromDemuxerStream(); | |
232 } | |
233 | |
234 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | 200 void DecryptingVideoDecoder::ReadFromDemuxerStream() { |
235 DCHECK(message_loop_->BelongsToCurrentThread()); | 201 DCHECK(message_loop_->BelongsToCurrentThread()); |
236 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 202 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
237 DCHECK(!read_cb_.is_null()); | 203 DCHECK(!read_cb_.is_null()); |
238 | 204 |
239 demuxer_stream_->Read( | 205 demuxer_stream_->Read( |
240 base::Bind(&DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this)); | 206 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); |
241 } | 207 } |
242 | 208 |
243 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( | 209 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( |
244 DemuxerStream::Status status, | 210 DemuxerStream::Status status, |
245 const scoped_refptr<DecoderBuffer>& buffer) { | 211 const scoped_refptr<DecoderBuffer>& buffer) { |
246 if (!message_loop_->BelongsToCurrentThread()) { | 212 DVLOG(3) << "DecryptAndDecodeBuffer()"; |
247 message_loop_->PostTask(FROM_HERE, base::Bind( | 213 DCHECK(message_loop_->BelongsToCurrentThread()); |
248 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, | |
249 status, buffer)); | |
250 return; | |
251 } | |
252 | |
253 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; | |
254 | 214 |
255 if (state_ == kStopped) | 215 if (state_ == kStopped) |
256 return; | 216 return; |
257 | 217 |
258 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 218 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
259 DCHECK(!read_cb_.is_null()); | 219 DCHECK(!read_cb_.is_null()); |
260 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 220 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
261 | 221 |
262 if (!reset_cb_.is_null()) { | 222 if (!reset_cb_.is_null()) { |
263 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 223 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
264 if (!reset_cb_.is_null()) | 224 if (!reset_cb_.is_null()) |
265 DoReset(); | 225 DoReset(); |
266 return; | 226 return; |
267 } | 227 } |
268 | 228 |
269 if (status == DemuxerStream::kAborted) { | 229 if (status == DemuxerStream::kAborted) { |
270 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; | 230 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted"; |
271 state_ = kIdle; | 231 state_ = kIdle; |
272 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 232 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
273 return; | 233 return; |
274 } | 234 } |
275 | 235 |
276 if (status == DemuxerStream::kConfigChanged) { | 236 if (status == DemuxerStream::kConfigChanged) { |
277 // TODO(xhwang): Add config change support. | 237 // TODO(xhwang): Add config change support. |
278 // The |state_| is chosen to be kDecodeFinished here to be consistent with | 238 // The |state_| is chosen to be kDecodeFinished here to be consistent with |
279 // the implementation of FFmpegVideoDecoder. | 239 // the implementation of FFmpegVideoDecoder. |
280 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; | 240 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged"; |
281 state_ = kDecodeFinished; | 241 state_ = kDecodeFinished; |
282 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 242 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
283 return; | 243 return; |
284 } | 244 } |
285 | 245 |
286 DCHECK_EQ(status, DemuxerStream::kOk); | 246 DCHECK_EQ(status, DemuxerStream::kOk); |
287 pending_buffer_to_decode_ = buffer; | 247 pending_buffer_to_decode_ = buffer; |
288 state_ = kPendingDecode; | 248 state_ = kPendingDecode; |
289 DecodePendingBuffer(); | 249 DecodePendingBuffer(); |
290 } | 250 } |
291 | 251 |
292 void DecryptingVideoDecoder::DecodePendingBuffer() { | 252 void DecryptingVideoDecoder::DecodePendingBuffer() { |
293 DCHECK(message_loop_->BelongsToCurrentThread()); | 253 DCHECK(message_loop_->BelongsToCurrentThread()); |
294 DCHECK_EQ(state_, kPendingDecode) << state_; | 254 DCHECK_EQ(state_, kPendingDecode) << state_; |
295 TRACE_EVENT_ASYNC_BEGIN0( | 255 TRACE_EVENT_ASYNC_BEGIN0( |
296 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); | 256 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); |
297 decryptor_->DecryptAndDecodeVideo( | 257 decryptor_->DecryptAndDecodeVideo( |
298 pending_buffer_to_decode_, | 258 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind( |
299 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, | 259 &DecryptingVideoDecoder::DeliverFrame, this, |
xhwang
2012/12/07 01:21:07
indent
scherkus (not reviewing)
2012/12/07 01:43:16
Done.
| |
300 pending_buffer_to_decode_->GetDataSize())); | 260 pending_buffer_to_decode_->GetDataSize()))); |
301 } | 261 } |
302 | 262 |
303 void DecryptingVideoDecoder::DeliverFrame( | 263 void DecryptingVideoDecoder::DeliverFrame( |
304 int buffer_size, | 264 int buffer_size, |
305 Decryptor::Status status, | 265 Decryptor::Status status, |
306 const scoped_refptr<VideoFrame>& frame) { | 266 const scoped_refptr<VideoFrame>& frame) { |
307 // We need to force task post here because the VideoDecodeCB can be executed | 267 DVLOG(3) << "DeliverFrame() - status: " << status; |
308 // synchronously in Reset()/Stop(). Instead of using more complicated logic in | |
309 // those function to fix it, why not force task post here to make everything | |
310 // simple and clear? | |
311 message_loop_->PostTask(FROM_HERE, base::Bind( | |
312 &DecryptingVideoDecoder::DoDeliverFrame, this, | |
313 buffer_size, status, frame)); | |
314 } | |
315 | |
316 void DecryptingVideoDecoder::DoDeliverFrame( | |
317 int buffer_size, | |
318 Decryptor::Status status, | |
319 const scoped_refptr<VideoFrame>& frame) { | |
320 DVLOG(3) << "DoDeliverFrame() - status: " << status; | |
321 DCHECK(message_loop_->BelongsToCurrentThread()); | 268 DCHECK(message_loop_->BelongsToCurrentThread()); |
322 TRACE_EVENT_ASYNC_END0( | 269 TRACE_EVENT_ASYNC_END0( |
323 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_); | 270 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_); |
324 | 271 |
325 if (state_ == kStopped) | 272 if (state_ == kStopped) |
326 return; | 273 return; |
327 | 274 |
328 DCHECK_EQ(state_, kPendingDecode) << state_; | 275 DCHECK_EQ(state_, kPendingDecode) << state_; |
329 DCHECK(!read_cb_.is_null()); | 276 DCHECK(!read_cb_.is_null()); |
330 DCHECK(pending_buffer_to_decode_); | 277 DCHECK(pending_buffer_to_decode_); |
331 | 278 |
332 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; | 279 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; |
333 key_added_while_decode_pending_ = false; | 280 key_added_while_decode_pending_ = false; |
334 | 281 |
335 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = | 282 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = |
336 pending_buffer_to_decode_; | 283 pending_buffer_to_decode_; |
337 pending_buffer_to_decode_ = NULL; | 284 pending_buffer_to_decode_ = NULL; |
338 | 285 |
339 if (!reset_cb_.is_null()) { | 286 if (!reset_cb_.is_null()) { |
340 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 287 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
341 DoReset(); | 288 DoReset(); |
342 return; | 289 return; |
343 } | 290 } |
344 | 291 |
345 DCHECK_EQ(status == Decryptor::kSuccess, frame != NULL); | 292 DCHECK_EQ(status == Decryptor::kSuccess, frame != NULL); |
346 | 293 |
347 if (status == Decryptor::kError) { | 294 if (status == Decryptor::kError) { |
348 DVLOG(2) << "DoDeliverFrame() - kError"; | 295 DVLOG(2) << "DeliverFrame() - kError"; |
349 state_ = kDecodeFinished; | 296 state_ = kDecodeFinished; |
350 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 297 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
351 return; | 298 return; |
352 } | 299 } |
353 | 300 |
354 if (status == Decryptor::kNoKey) { | 301 if (status == Decryptor::kNoKey) { |
355 DVLOG(2) << "DoDeliverFrame() - kNoKey"; | 302 DVLOG(2) << "DeliverFrame() - kNoKey"; |
356 // Set |pending_buffer_to_decode_| back as we need to try decoding the | 303 // Set |pending_buffer_to_decode_| back as we need to try decoding the |
357 // pending buffer again when new key is added to the decryptor. | 304 // pending buffer again when new key is added to the decryptor. |
358 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; | 305 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; |
359 | 306 |
360 if (need_to_try_again_if_nokey_is_returned) { | 307 if (need_to_try_again_if_nokey_is_returned) { |
361 // The |state_| is still kPendingDecode. | 308 // The |state_| is still kPendingDecode. |
362 DecodePendingBuffer(); | 309 DecodePendingBuffer(); |
363 return; | 310 return; |
364 } | 311 } |
365 | 312 |
366 state_ = kWaitingForKey; | 313 state_ = kWaitingForKey; |
367 return; | 314 return; |
368 } | 315 } |
369 | 316 |
370 // The buffer has been accepted by the decoder, let's report statistics. | 317 // The buffer has been accepted by the decoder, let's report statistics. |
371 if (buffer_size) { | 318 if (buffer_size) { |
372 PipelineStatistics statistics; | 319 PipelineStatistics statistics; |
373 statistics.video_bytes_decoded = buffer_size; | 320 statistics.video_bytes_decoded = buffer_size; |
374 statistics_cb_.Run(statistics); | 321 statistics_cb_.Run(statistics); |
375 } | 322 } |
376 | 323 |
377 if (status == Decryptor::kNeedMoreData) { | 324 if (status == Decryptor::kNeedMoreData) { |
378 DVLOG(2) << "DoDeliverFrame() - kNeedMoreData"; | 325 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; |
379 if (scoped_pending_buffer_to_decode->IsEndOfStream()) { | 326 if (scoped_pending_buffer_to_decode->IsEndOfStream()) { |
380 state_ = kDecodeFinished; | 327 state_ = kDecodeFinished; |
381 base::ResetAndReturn(&read_cb_).Run( | 328 base::ResetAndReturn(&read_cb_).Run( |
382 kOk, media::VideoFrame::CreateEmptyFrame()); | 329 kOk, media::VideoFrame::CreateEmptyFrame()); |
383 return; | 330 return; |
384 } | 331 } |
385 | 332 |
386 state_ = kPendingDemuxerRead; | 333 state_ = kPendingDemuxerRead; |
387 ReadFromDemuxerStream(); | 334 ReadFromDemuxerStream(); |
388 return; | 335 return; |
(...skipping 22 matching lines...) Expand all Loading... | |
411 } | 358 } |
412 | 359 |
413 void DecryptingVideoDecoder::DoReset() { | 360 void DecryptingVideoDecoder::DoReset() { |
414 DCHECK(init_cb_.is_null()); | 361 DCHECK(init_cb_.is_null()); |
415 DCHECK(read_cb_.is_null()); | 362 DCHECK(read_cb_.is_null()); |
416 state_ = kIdle; | 363 state_ = kIdle; |
417 base::ResetAndReturn(&reset_cb_).Run(); | 364 base::ResetAndReturn(&reset_cb_).Run(); |
418 } | 365 } |
419 | 366 |
420 } // namespace media | 367 } // namespace media |
OLD | NEW |