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

Side by Side Diff: media/base/android/media_codec_decoder.cc

Issue 1254293003: MediaCodecPlayer implementation (stage 4 - preroll) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-browserseek
Patch Set: Save the first post-preroll audio buffer and replay it when preroll is done Created 5 years, 4 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/base/android/media_codec_decoder.h" 5 #include "media/base/android/media_codec_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 17 matching lines...) Expand all
28 const int kInputBufferTimeout = 20; 28 const int kInputBufferTimeout = 20;
29 29
30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds. 30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds.
31 const int kOutputBufferTimeout = 20; 31 const int kOutputBufferTimeout = 20;
32 } 32 }
33 33
34 MediaCodecDecoder::MediaCodecDecoder( 34 MediaCodecDecoder::MediaCodecDecoder(
35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
36 const base::Closure& external_request_data_cb, 36 const base::Closure& external_request_data_cb,
37 const base::Closure& starvation_cb, 37 const base::Closure& starvation_cb,
38 const base::Closure& preroll_done_cb,
38 const base::Closure& stop_done_cb, 39 const base::Closure& stop_done_cb,
39 const base::Closure& error_cb, 40 const base::Closure& error_cb,
40 const char* decoder_thread_name) 41 const char* decoder_thread_name)
41 : media_task_runner_(media_task_runner), 42 : media_task_runner_(media_task_runner),
42 decoder_thread_(decoder_thread_name), 43 decoder_thread_(decoder_thread_name),
43 needs_reconfigure_(false), 44 needs_reconfigure_(false),
44 external_request_data_cb_(external_request_data_cb), 45 external_request_data_cb_(external_request_data_cb),
45 starvation_cb_(starvation_cb), 46 starvation_cb_(starvation_cb),
47 preroll_done_cb_(preroll_done_cb),
46 stop_done_cb_(stop_done_cb), 48 stop_done_cb_(stop_done_cb),
47 error_cb_(error_cb), 49 error_cb_(error_cb),
48 state_(kStopped), 50 state_(kStopped),
49 eos_enqueued_(false), 51 eos_enqueued_(false),
50 completed_(false), 52 completed_(false),
51 last_frame_posted_(false), 53 last_frame_posted_(false),
52 is_data_request_in_progress_(false), 54 is_data_request_in_progress_(false),
53 is_incoming_data_invalid_(false), 55 is_incoming_data_invalid_(false),
54 #ifndef NDEBUG 56 #ifndef NDEBUG
55 verify_next_frame_is_key_(false), 57 verify_next_frame_is_key_(false),
56 #endif 58 #endif
57 weak_factory_(this) { 59 weak_factory_(this) {
58 DCHECK(media_task_runner_->BelongsToCurrentThread()); 60 DCHECK(media_task_runner_->BelongsToCurrentThread());
59 61
60 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; 62 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name;
61 63
62 internal_error_cb_ = 64 internal_error_cb_ =
63 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); 65 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr());
66 internal_preroll_done_cb_ =
67 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr());
64 request_data_cb_ = 68 request_data_cb_ =
65 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); 69 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr());
66 } 70 }
67 71
68 MediaCodecDecoder::~MediaCodecDecoder() { 72 MediaCodecDecoder::~MediaCodecDecoder() {
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); 73 DCHECK(media_task_runner_->BelongsToCurrentThread());
70 74
71 DVLOG(1) << "Decoder::~Decoder()"; 75 DVLOG(1) << "Decoder::~Decoder()";
72 76
73 // NB: ReleaseDecoderResources() is virtual 77 // NB: ReleaseDecoderResources() is virtual
74 ReleaseDecoderResources(); 78 ReleaseDecoderResources();
75 } 79 }
76 80
77 const char* MediaCodecDecoder::class_name() const { 81 const char* MediaCodecDecoder::class_name() const {
78 return "Decoder"; 82 return "Decoder";
79 } 83 }
80 84
81 void MediaCodecDecoder::ReleaseDecoderResources() { 85 void MediaCodecDecoder::ReleaseDecoderResources() {
82 DCHECK(media_task_runner_->BelongsToCurrentThread()); 86 DCHECK(media_task_runner_->BelongsToCurrentThread());
83 87
84 DVLOG(1) << class_name() << "::" << __FUNCTION__; 88 DVLOG(1) << class_name() << "::" << __FUNCTION__;
85 89
86 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 90 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
87 SetState(kInEmergencyStop); 91 SetState(kInEmergencyStop);
88 92
89 decoder_thread_.Stop(); // synchronous 93 decoder_thread_.Stop(); // synchronous
90 94
91 SetState(kStopped); 95 SetState(kStopped);
92 media_codec_bridge_.reset(); 96 ReleaseMediaCodec();
93 } 97 }
94 98
95 void MediaCodecDecoder::Flush() { 99 void MediaCodecDecoder::Flush() {
96 DCHECK(media_task_runner_->BelongsToCurrentThread()); 100 DCHECK(media_task_runner_->BelongsToCurrentThread());
97 101
98 DVLOG(1) << class_name() << "::" << __FUNCTION__; 102 DVLOG(1) << class_name() << "::" << __FUNCTION__;
99 103
100 DCHECK_EQ(GetState(), kStopped); 104 DCHECK_EQ(GetState(), kStopped);
101 105
102 // Flush() is a part of the Seek request. Whenever we request a seek we need 106 // Flush() is a part of the Seek request. Whenever we request a seek we need
(...skipping 21 matching lines...) Expand all
124 DVLOG(0) << class_name() << "::" << __FUNCTION__ 128 DVLOG(0) << class_name() << "::" << __FUNCTION__
125 << "MediaCodecBridge::Reset() failed"; 129 << "MediaCodecBridge::Reset() failed";
126 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 130 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
127 } 131 }
128 } 132 }
129 } 133 }
130 134
131 void MediaCodecDecoder::ReleaseMediaCodec() { 135 void MediaCodecDecoder::ReleaseMediaCodec() {
132 DCHECK(media_task_runner_->BelongsToCurrentThread()); 136 DCHECK(media_task_runner_->BelongsToCurrentThread());
133 137
134 DVLOG(1) << class_name() << "::" << __FUNCTION__;
135
136 media_codec_bridge_.reset(); 138 media_codec_bridge_.reset();
137 } 139 }
138 140
139 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { 141 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
140 DCHECK(media_task_runner_->BelongsToCurrentThread()); 142 DCHECK(media_task_runner_->BelongsToCurrentThread());
141 143
144 // Whether decoder needs to be stopped.
142 base::AutoLock lock(state_lock_); 145 base::AutoLock lock(state_lock_);
143 return state_ == kPrefetching || state_ == kRunning; 146 switch (state_) {
147 case kPrefetching:
148 case kPrefetched:
149 case kPrerolling:
150 case kPrerolled:
151 case kRunning:
152 return true;
153 case kStopped:
154 case kStopping:
155 case kInEmergencyStop:
156 case kError:
157 return false;
158 }
159 NOTREACHED();
160 return false;
161 }
162
163 bool MediaCodecDecoder::IsPrerollDone() const {
164 DCHECK(media_task_runner_->BelongsToCurrentThread());
165
166 return !HasStream() || IsCompleted() || GetState() == kPrerolled;
144 } 167 }
145 168
146 bool MediaCodecDecoder::IsStopped() const { 169 bool MediaCodecDecoder::IsStopped() const {
147 DCHECK(media_task_runner_->BelongsToCurrentThread()); 170 DCHECK(media_task_runner_->BelongsToCurrentThread());
148 171
149 return GetState() == kStopped; 172 return GetState() == kStopped;
150 } 173 }
151 174
152 bool MediaCodecDecoder::IsCompleted() const { 175 bool MediaCodecDecoder::IsCompleted() const {
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); 176 DCHECK(media_task_runner_->BelongsToCurrentThread());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 208
186 if (GetState() == kError) { 209 if (GetState() == kError) {
187 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; 210 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
188 return kConfigFailure; 211 return kConfigFailure;
189 } 212 }
190 213
191 if (needs_reconfigure_) { 214 if (needs_reconfigure_) {
192 DVLOG(1) << class_name() << "::" << __FUNCTION__ 215 DVLOG(1) << class_name() << "::" << __FUNCTION__
193 << ": needs reconfigure, deleting MediaCodec"; 216 << ": needs reconfigure, deleting MediaCodec";
194 needs_reconfigure_ = false; 217 needs_reconfigure_ = false;
195 media_codec_bridge_.reset(); 218 ReleaseMediaCodec();
196
197 // No need to release these buffers since the MediaCodec is deleted, just
198 // remove their indexes from |delayed_buffers_|.
199
200 ClearDelayedBuffers(false);
201 } 219 }
202 220
203 MediaCodecDecoder::ConfigStatus result; 221 MediaCodecDecoder::ConfigStatus result;
204 if (media_codec_bridge_) { 222 if (media_codec_bridge_) {
205 DVLOG(1) << class_name() << "::" << __FUNCTION__ 223 DVLOG(1) << class_name() << "::" << __FUNCTION__
206 << ": reconfiguration is not required, ignoring"; 224 << ": reconfiguration is not required, ignoring";
207 result = kConfigOk; 225 result = kConfigOk;
208 } else { 226 } else {
209 result = ConfigureInternal(); 227 result = ConfigureInternal();
210 228
211 #ifndef NDEBUG 229 #ifndef NDEBUG
212 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 230 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
213 // This DCHECK ensures we won't need to lock this variable. 231 // This DCHECK ensures we won't need to lock this variable.
214 DCHECK(!decoder_thread_.IsRunning()); 232 DCHECK(!decoder_thread_.IsRunning());
215 233
216 // For video the first frame after reconfiguration must be key frame. 234 // For video the first frame after reconfiguration must be key frame.
217 if (result == kConfigOk) 235 if (result == kConfigOk)
218 verify_next_frame_is_key_ = true; 236 verify_next_frame_is_key_ = true;
219 #endif 237 #endif
220 } 238 }
221 239
222 return result; 240 return result;
223 } 241 }
224 242
225 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { 243 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) {
244 DCHECK(media_task_runner_->BelongsToCurrentThread());
245 DCHECK(!decoder_thread_.IsRunning());
246
247 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp;
248
249 // Do not set preroll timestamp if it's too close to zero.
250 preroll_timestamp_ = preroll_timestamp;
251 }
252
253 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) {
226 DCHECK(media_task_runner_->BelongsToCurrentThread()); 254 DCHECK(media_task_runner_->BelongsToCurrentThread());
227 255
228 DVLOG(1) << class_name() << "::" << __FUNCTION__ 256 DVLOG(1) << class_name() << "::" << __FUNCTION__
229 << " current_time:" << current_time; 257 << " start_timestamp:" << start_timestamp;
230 258
231 DecoderState state = GetState(); 259 DecoderState state = GetState();
232 if (state == kRunning) { 260 if (state == kPrerolling || state == kRunning) {
233 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; 261 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started";
234 return true; // already started 262 return true; // already started
235 } 263 }
236 264
237 if (state != kPrefetched) { 265 if (state != kPrefetched) {
238 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " 266 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
239 << AsString(state) << ", ignoring"; 267 << AsString(state) << ", ignoring";
240 return false; 268 return false;
241 } 269 }
242 270
243 if (!media_codec_bridge_) { 271 if (!media_codec_bridge_) {
244 DVLOG(0) << class_name() << "::" << __FUNCTION__ 272 DVLOG(0) << class_name() << "::" << __FUNCTION__
245 << ": not configured, ignoring"; 273 << ": not configured, ignoring";
246 return false; 274 return false;
247 } 275 }
248 276
249 DCHECK(!decoder_thread_.IsRunning()); 277 DCHECK(!decoder_thread_.IsRunning());
250 278
279 const bool needs_preroll = (preroll_timestamp_ != base::TimeDelta());
qinmin 2015/07/31 18:43:10 why not preroll if timestamp is 0? it will help us
Tima Vaisburd 2015/07/31 19:26:42 I think decoder initialization delay has been alre
Tima Vaisburd 2015/08/01 04:34:43 Min explained that there is internal codec initial
280
251 // We only synchronize video stream. 281 // We only synchronize video stream.
252 // When audio is present, the |current_time| is audio time. 282 if (needs_preroll)
253 SynchronizePTSWithTime(current_time); 283 DissociatePTSFromTime(); // associaton will happen after preroll is done.
284 else
285 AssociateCurrentTimeWithPTS(start_timestamp);
254 286
255 last_frame_posted_ = false; 287 last_frame_posted_ = false;
256 288
257 // Start the decoder thread 289 // Start the decoder thread
258 if (!decoder_thread_.Start()) { 290 if (!decoder_thread_.Start()) {
259 DVLOG(1) << class_name() << "::" << __FUNCTION__ 291 DVLOG(1) << class_name() << "::" << __FUNCTION__
260 << ": cannot start decoder thread"; 292 << ": cannot start decoder thread";
261 return false; 293 return false;
262 } 294 }
263 295
264 SetState(kRunning); 296 SetState(needs_preroll ? kPrerolling : kRunning);
265 297
266 decoder_thread_.task_runner()->PostTask( 298 decoder_thread_.task_runner()->PostTask(
267 FROM_HERE, 299 FROM_HERE,
268 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); 300 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
269 301
270 return true; 302 return true;
271 } 303 }
272 304
305 void MediaCodecDecoder::ResumeAfterPreroll() {
306 DCHECK(media_task_runner_->BelongsToCurrentThread());
307
308 DVLOG(1) << class_name() << "::" << __FUNCTION__;
309
310 DCHECK(GetState() == kPrerolled);
311 DCHECK(decoder_thread_.IsRunning());
312
313 SetState(kRunning);
314
315 AssociateCurrentTimeWithPTS(preroll_timestamp_);
316 preroll_timestamp_ = base::TimeDelta();
317
318 decoder_thread_.task_runner()->PostTask(
319 FROM_HERE,
320 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
321 }
322
273 void MediaCodecDecoder::SyncStop() { 323 void MediaCodecDecoder::SyncStop() {
274 DCHECK(media_task_runner_->BelongsToCurrentThread()); 324 DCHECK(media_task_runner_->BelongsToCurrentThread());
275 325
276 DVLOG(1) << class_name() << "::" << __FUNCTION__; 326 DVLOG(1) << class_name() << "::" << __FUNCTION__;
277 327
278 if (GetState() == kError) { 328 if (GetState() == kError) {
279 DVLOG(0) << class_name() << "::" << __FUNCTION__ 329 DVLOG(0) << class_name() << "::" << __FUNCTION__
280 << ": wrong state kError, ignoring"; 330 << ": wrong state kError, ignoring";
281 return; 331 return;
282 } 332 }
283 333
284 // After this method returns, decoder thread will not be running. 334 // After this method returns, decoder thread will not be running.
285 335
286 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 336 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
287 SetState(kInEmergencyStop); 337 SetState(kInEmergencyStop);
288 338
289 decoder_thread_.Stop(); // synchronous 339 decoder_thread_.Stop(); // synchronous
290 340
291 SetState(kStopped); 341 SetState(kStopped);
292 342
293 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|. 343 ReleaseDelayedBuffers();
294 } 344 }
295 345
296 void MediaCodecDecoder::RequestToStop() { 346 void MediaCodecDecoder::RequestToStop() {
297 DCHECK(media_task_runner_->BelongsToCurrentThread()); 347 DCHECK(media_task_runner_->BelongsToCurrentThread());
298 348
299 DVLOG(1) << class_name() << "::" << __FUNCTION__; 349 DVLOG(1) << class_name() << "::" << __FUNCTION__;
300 350
301 DecoderState state = GetState(); 351 DecoderState state = GetState();
302 switch (state) { 352 switch (state) {
303 case kError: 353 case kError:
304 DVLOG(0) << class_name() << "::" << __FUNCTION__ 354 DVLOG(0) << class_name() << "::" << __FUNCTION__
305 << ": wrong state kError, ignoring"; 355 << ": wrong state kError, ignoring";
306 break; 356 break;
307 case kRunning: 357 case kRunning:
308 SetState(kStopping); 358 SetState(kStopping);
309 break; 359 break;
360 case kPrerolling:
361 case kPrerolled:
362 DCHECK(decoder_thread_.IsRunning());
363 // Synchronous stop.
364 decoder_thread_.Stop();
365 SetState(kStopped);
366 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
367 break;
310 case kStopping: 368 case kStopping:
311 break; // ignore 369 break; // ignore
312 case kStopped: 370 case kStopped:
313 case kPrefetching: 371 case kPrefetching:
314 case kPrefetched: 372 case kPrefetched:
315 // There is nothing to wait for, we can sent nofigication right away. 373 // There is nothing to wait for, we can sent nofigication right away.
316 DCHECK(!decoder_thread_.IsRunning()); 374 DCHECK(!decoder_thread_.IsRunning());
317 SetState(kStopped); 375 SetState(kStopped);
318 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 376 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
319 break; 377 break;
(...skipping 10 matching lines...) Expand all
330 << " completed:" << completed; 388 << " completed:" << completed;
331 389
332 decoder_thread_.Stop(); // synchronous 390 decoder_thread_.Stop(); // synchronous
333 391
334 SetState(kStopped); 392 SetState(kStopped);
335 completed_ = completed; 393 completed_ = completed;
336 394
337 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 395 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
338 } 396 }
339 397
398 void MediaCodecDecoder::OnPrerollDone() {
399 DCHECK(media_task_runner_->BelongsToCurrentThread());
400
401 DVLOG(1) << class_name() << "::" << __FUNCTION__;
402
403 if (GetState() == kPrerolling) {
404 SetState(kPrerolled);
405 media_task_runner_->PostTask(FROM_HERE, preroll_done_cb_);
406 }
407 }
408
340 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { 409 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
341 DCHECK(media_task_runner_->BelongsToCurrentThread()); 410 DCHECK(media_task_runner_->BelongsToCurrentThread());
342 411
343 // If |data| contains an aborted data, the last AU will have kAborted status. 412 // If |data| contains an aborted data, the last AU will have kAborted status.
344 bool aborted_data = 413 bool aborted_data =
345 !data.access_units.empty() && 414 !data.access_units.empty() &&
346 data.access_units.back().status == DemuxerStream::kAborted; 415 data.access_units.back().status == DemuxerStream::kAborted;
347 416
348 #ifndef NDEBUG 417 #ifndef NDEBUG
349 const char* explain_if_skipped = 418 const char* explain_if_skipped =
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 request_data_cb_.Run(); 500 request_data_cb_.Run();
432 } 501 }
433 502
434 void MediaCodecDecoder::ProcessNextFrame() { 503 void MediaCodecDecoder::ProcessNextFrame() {
435 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 504 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
436 505
437 DVLOG(2) << class_name() << "::" << __FUNCTION__; 506 DVLOG(2) << class_name() << "::" << __FUNCTION__;
438 507
439 DecoderState state = GetState(); 508 DecoderState state = GetState();
440 509
441 if (state != kRunning && state != kStopping) { 510 if (state != kPrerolling && state != kRunning && state != kStopping) {
442 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; 511 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running";
443 return; 512 return;
444 } 513 }
445 514
446 if (state == kStopping) { 515 if (state == kStopping) {
447 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { 516 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) {
448 DVLOG(1) << class_name() << "::" << __FUNCTION__ 517 DVLOG(1) << class_name() << "::" << __FUNCTION__
449 << ": kStopping, posting OnLastFrameRendered"; 518 << ": kStopping, posting OnLastFrameRendered";
450 media_task_runner_->PostTask( 519 media_task_runner_->PostTask(
451 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, 520 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
452 weak_factory_.GetWeakPtr(), false)); 521 weak_factory_.GetWeakPtr(), false));
453 last_frame_posted_ = true; 522 last_frame_posted_ = true;
454 } 523 }
455 524
456 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. 525 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
457 // We only need to let finish the delayed rendering tasks. 526 // We only need to let finish the delayed rendering tasks.
458 return; 527 return;
459 } 528 }
460 529
461 DCHECK(state == kRunning); 530 DCHECK(state == kPrerolling || state == kRunning);
462 531
463 if (!EnqueueInputBuffer()) 532 if (!EnqueueInputBuffer())
464 return; 533 return;
465 534
466 if (!DepleteOutputBufferQueue()) 535 if (!DepleteOutputBufferQueue())
467 return; 536 return;
468 537
469 // We need a small delay if we want to stop this thread by 538 // We need a small delay if we want to stop this thread by
470 // decoder_thread_.Stop() reliably. 539 // decoder_thread_.Stop() reliably.
471 // The decoder thread message loop processes all pending 540 // The decoder thread message loop processes all pending
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 662
594 DVLOG(2) << class_name() << "::" << __FUNCTION__; 663 DVLOG(2) << class_name() << "::" << __FUNCTION__;
595 664
596 int buffer_index = 0; 665 int buffer_index = 0;
597 size_t offset = 0; 666 size_t offset = 0;
598 size_t size = 0; 667 size_t size = 0;
599 base::TimeDelta pts; 668 base::TimeDelta pts;
600 MediaCodecStatus status; 669 MediaCodecStatus status;
601 bool eos_encountered = false; 670 bool eos_encountered = false;
602 671
672 RenderMode render_mode;
673 bool preroll_done = false;
674
603 base::TimeDelta timeout = 675 base::TimeDelta timeout =
604 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); 676 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
605 677
606 // Extract all output buffers that are available. 678 // Extract all output buffers that are available.
607 // Usually there will be only one, but sometimes it is preceeded by 679 // Usually there will be only one, but sometimes it is preceeded by
608 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. 680 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
609 do { 681 do {
610 status = media_codec_bridge_->DequeueOutputBuffer( 682 status = media_codec_bridge_->DequeueOutputBuffer(
611 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, 683 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered,
612 nullptr); 684 nullptr);
613 685
614 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls 686 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
615 // to quickly break the loop after we got all currently available buffers. 687 // to quickly break the loop after we got all currently available buffers.
616 timeout = base::TimeDelta::FromMilliseconds(0); 688 timeout = base::TimeDelta::FromMilliseconds(0);
617 689
618 switch (status) { 690 switch (status) {
619 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 691 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
620 // Output buffers are replaced in MediaCodecBridge, nothing to do. 692 // Output buffers are replaced in MediaCodecBridge, nothing to do.
621 break; 693 break;
622 694
623 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: 695 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
624 DVLOG(2) << class_name() << "::" << __FUNCTION__ 696 DVLOG(2) << class_name() << "::" << __FUNCTION__
625 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; 697 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
626 OnOutputFormatChanged(); 698 OnOutputFormatChanged();
627 break; 699 break;
628 700
629 case MEDIA_CODEC_OK: 701 case MEDIA_CODEC_OK: {
630 // We got the decoded frame 702 // We got the decoded frame.
631 Render(buffer_index, size, true, pts, eos_encountered); 703
632 break; 704 if (pts < preroll_timestamp_)
705 render_mode = kRenderSkip;
706 else if (GetState() == kPrerolling)
707 render_mode = kRenderAfterPreroll;
708 else
709 render_mode = kRenderNow;
710
711 Render(buffer_index, size, render_mode, pts, eos_encountered);
712
713 if (render_mode == kRenderAfterPreroll) {
714 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
715 preroll_done = true;
qinmin 2015/07/31 18:43:10 why not just return false here.
Tima Vaisburd 2015/07/31 19:26:42 Done.
716 }
717 } break;
qinmin 2015/07/31 18:43:10 move the break to a new line
Tima Vaisburd 2015/07/31 19:26:42 Done.
633 718
634 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 719 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
635 // Nothing to do. 720 // Nothing to do.
636 break; 721 break;
637 722
638 case MEDIA_CODEC_ERROR: 723 case MEDIA_CODEC_ERROR:
639 DVLOG(0) << class_name() << "::" << __FUNCTION__ 724 DVLOG(0) << class_name() << "::" << __FUNCTION__
640 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; 725 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
641 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 726 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
642 break; 727 break;
643 728
644 default: 729 default:
645 NOTREACHED(); 730 NOTREACHED();
646 break; 731 break;
647 } 732 }
648 733
649 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER && 734 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER &&
650 status != MEDIA_CODEC_ERROR && !eos_encountered); 735 status != MEDIA_CODEC_ERROR && !eos_encountered && !preroll_done);
651 736
652 if (eos_encountered) { 737 if (eos_encountered) {
653 DVLOG(1) << class_name() << "::" << __FUNCTION__ 738 DVLOG(1) << class_name() << "::" << __FUNCTION__
654 << " EOS dequeued, stopping frame processing"; 739 << " EOS dequeued, stopping frame processing";
655 return false; 740 return false;
656 } 741 }
657 742
743 if (preroll_done) {
744 DVLOG(1) << class_name() << "::" << __FUNCTION__
745 << " preroll done, stopping frame processing";
746 return false;
747 }
748
658 if (status == MEDIA_CODEC_ERROR) { 749 if (status == MEDIA_CODEC_ERROR) {
659 DVLOG(1) << class_name() << "::" << __FUNCTION__ 750 DVLOG(1) << class_name() << "::" << __FUNCTION__
660 << " MediaCodec error, stopping frame processing"; 751 << " MediaCodec error, stopping frame processing";
661 return false; 752 return false;
662 } 753 }
663 754
664 return true; 755 return true;
665 } 756 }
666 757
667 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { 758 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const {
668 base::AutoLock lock(state_lock_); 759 base::AutoLock lock(state_lock_);
669 return state_; 760 return state_;
670 } 761 }
671 762
672 void MediaCodecDecoder::SetState(DecoderState state) { 763 void MediaCodecDecoder::SetState(DecoderState state) {
673 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << AsString(state); 764 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << AsString(state);
674 765
675 base::AutoLock lock(state_lock_); 766 base::AutoLock lock(state_lock_);
676 state_ = state; 767 state_ = state;
677 } 768 }
678 769
679 #undef RETURN_STRING 770 #undef RETURN_STRING
680 #define RETURN_STRING(x) \ 771 #define RETURN_STRING(x) \
681 case x: \ 772 case x: \
682 return #x; 773 return #x;
683 774
775 const char* MediaCodecDecoder::AsString(RenderMode render_mode) {
776 switch (render_mode) {
777 RETURN_STRING(kRenderSkip);
778 RETURN_STRING(kRenderAfterPreroll);
779 RETURN_STRING(kRenderNow);
780 }
781 return nullptr; // crash early
782 }
783
684 const char* MediaCodecDecoder::AsString(DecoderState state) { 784 const char* MediaCodecDecoder::AsString(DecoderState state) {
685 switch (state) { 785 switch (state) {
686 RETURN_STRING(kStopped); 786 RETURN_STRING(kStopped);
687 RETURN_STRING(kPrefetching); 787 RETURN_STRING(kPrefetching);
688 RETURN_STRING(kPrefetched); 788 RETURN_STRING(kPrefetched);
789 RETURN_STRING(kPrerolling);
790 RETURN_STRING(kPrerolled);
689 RETURN_STRING(kRunning); 791 RETURN_STRING(kRunning);
690 RETURN_STRING(kStopping); 792 RETURN_STRING(kStopping);
691 RETURN_STRING(kInEmergencyStop); 793 RETURN_STRING(kInEmergencyStop);
692 RETURN_STRING(kError); 794 RETURN_STRING(kError);
693 default:
694 return "Unknown DecoderState";
695 } 795 }
796 return nullptr; // crash early
696 } 797 }
697 798
698 #undef RETURN_STRING 799 #undef RETURN_STRING
699 800
700 } // namespace media 801 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698