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

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

Issue 11428095: Pass in media message loop to VideoRendererBase and enforce calling on the right thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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/decrypting_video_decoder.h ('k') | media/filters/ffmpeg_video_decoder.h » ('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/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
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
OLDNEW
« no previous file with comments | « media/filters/decrypting_video_decoder.h ('k') | media/filters/ffmpeg_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698