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

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: Added unit test for video-only preroll 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 10 matching lines...) Expand all
21 // Request new data in the kRunning state if the queue size is less than this. 21 // Request new data in the kRunning state if the queue size is less than this.
22 const int kPlaybackLowLimit = 4; 22 const int kPlaybackLowLimit = 4;
23 23
24 // Posting delay of the next frame processing, in milliseconds 24 // Posting delay of the next frame processing, in milliseconds
25 const int kNextFrameDelay = 1; 25 const int kNextFrameDelay = 1;
26 26
27 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds. 27 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds.
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 = 10;
Tima Vaisburd 2015/08/03 19:44:34 Upon more detailed examination of unit tests I fou
qinmin 2015/08/03 21:25:15 these values are too small, some devices will alwa
Tima Vaisburd 2015/08/03 22:49:05 Restored to 20 ms
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),
51 needs_preroll_(true),
49 eos_enqueued_(false), 52 eos_enqueued_(false),
50 completed_(false), 53 completed_(false),
51 last_frame_posted_(false), 54 last_frame_posted_(false),
52 is_data_request_in_progress_(false), 55 is_data_request_in_progress_(false),
53 is_incoming_data_invalid_(false), 56 is_incoming_data_invalid_(false),
54 #ifndef NDEBUG 57 #ifndef NDEBUG
55 verify_next_frame_is_key_(false), 58 verify_next_frame_is_key_(false),
56 #endif 59 #endif
57 weak_factory_(this) { 60 weak_factory_(this) {
58 DCHECK(media_task_runner_->BelongsToCurrentThread()); 61 DCHECK(media_task_runner_->BelongsToCurrentThread());
59 62
60 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; 63 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name;
61 64
62 internal_error_cb_ = 65 internal_error_cb_ =
63 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); 66 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr());
67 internal_preroll_done_cb_ =
68 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr());
64 request_data_cb_ = 69 request_data_cb_ =
65 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); 70 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr());
66 } 71 }
67 72
68 MediaCodecDecoder::~MediaCodecDecoder() { 73 MediaCodecDecoder::~MediaCodecDecoder() {
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); 74 DCHECK(media_task_runner_->BelongsToCurrentThread());
70 75
71 DVLOG(1) << "Decoder::~Decoder()"; 76 DVLOG(1) << "Decoder::~Decoder()";
72 77
73 // NB: ReleaseDecoderResources() is virtual 78 // NB: ReleaseDecoderResources() is virtual
74 ReleaseDecoderResources(); 79 ReleaseDecoderResources();
75 } 80 }
76 81
77 const char* MediaCodecDecoder::class_name() const { 82 const char* MediaCodecDecoder::class_name() const {
78 return "Decoder"; 83 return "Decoder";
79 } 84 }
80 85
81 void MediaCodecDecoder::ReleaseDecoderResources() { 86 void MediaCodecDecoder::ReleaseDecoderResources() {
82 DCHECK(media_task_runner_->BelongsToCurrentThread()); 87 DCHECK(media_task_runner_->BelongsToCurrentThread());
83 88
84 DVLOG(1) << class_name() << "::" << __FUNCTION__; 89 DVLOG(1) << class_name() << "::" << __FUNCTION__;
85 90
86 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 91 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
87 SetState(kInEmergencyStop); 92 SetState(kInEmergencyStop);
88 93
89 decoder_thread_.Stop(); // synchronous 94 decoder_thread_.Stop(); // synchronous
90 95
91 SetState(kStopped); 96 SetState(kStopped);
92 media_codec_bridge_.reset(); 97 ReleaseMediaCodec();
98
99 needs_preroll_ = true;
93 } 100 }
94 101
95 void MediaCodecDecoder::Flush() { 102 void MediaCodecDecoder::Flush() {
96 DCHECK(media_task_runner_->BelongsToCurrentThread()); 103 DCHECK(media_task_runner_->BelongsToCurrentThread());
97 104
98 DVLOG(1) << class_name() << "::" << __FUNCTION__; 105 DVLOG(1) << class_name() << "::" << __FUNCTION__;
99 106
100 DCHECK_EQ(GetState(), kStopped); 107 DCHECK_EQ(GetState(), kStopped);
101 108
102 // Flush() is a part of the Seek request. Whenever we request a seek we need 109 // Flush() is a part of the Seek request. Whenever we request a seek we need
(...skipping 29 matching lines...) Expand all
132 DCHECK(media_task_runner_->BelongsToCurrentThread()); 139 DCHECK(media_task_runner_->BelongsToCurrentThread());
133 140
134 DVLOG(1) << class_name() << "::" << __FUNCTION__; 141 DVLOG(1) << class_name() << "::" << __FUNCTION__;
135 142
136 media_codec_bridge_.reset(); 143 media_codec_bridge_.reset();
137 } 144 }
138 145
139 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { 146 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
140 DCHECK(media_task_runner_->BelongsToCurrentThread()); 147 DCHECK(media_task_runner_->BelongsToCurrentThread());
141 148
149 // Whether decoder needs to be stopped.
142 base::AutoLock lock(state_lock_); 150 base::AutoLock lock(state_lock_);
143 return state_ == kPrefetching || state_ == kRunning; 151 switch (state_) {
152 case kPrefetching:
153 case kPrefetched:
154 case kPrerolling:
155 case kPrerolled:
156 case kRunning:
157 return true;
158 case kStopped:
159 case kStopping:
160 case kInEmergencyStop:
161 case kError:
162 return false;
163 }
164 NOTREACHED();
165 return false;
166 }
167
168 bool MediaCodecDecoder::IsPrerollDone() const {
169 DCHECK(media_task_runner_->BelongsToCurrentThread());
170
171 return !HasStream() || IsCompleted() || GetState() == kPrerolled;
144 } 172 }
145 173
146 bool MediaCodecDecoder::IsStopped() const { 174 bool MediaCodecDecoder::IsStopped() const {
147 DCHECK(media_task_runner_->BelongsToCurrentThread()); 175 DCHECK(media_task_runner_->BelongsToCurrentThread());
148 176
149 return GetState() == kStopped; 177 return GetState() == kStopped;
150 } 178 }
151 179
152 bool MediaCodecDecoder::IsCompleted() const { 180 bool MediaCodecDecoder::IsCompleted() const {
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); 181 DCHECK(media_task_runner_->BelongsToCurrentThread());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 213
186 if (GetState() == kError) { 214 if (GetState() == kError) {
187 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; 215 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
188 return kConfigFailure; 216 return kConfigFailure;
189 } 217 }
190 218
191 if (needs_reconfigure_) { 219 if (needs_reconfigure_) {
192 DVLOG(1) << class_name() << "::" << __FUNCTION__ 220 DVLOG(1) << class_name() << "::" << __FUNCTION__
193 << ": needs reconfigure, deleting MediaCodec"; 221 << ": needs reconfigure, deleting MediaCodec";
194 needs_reconfigure_ = false; 222 needs_reconfigure_ = false;
195 media_codec_bridge_.reset(); 223 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 } 224 }
202 225
203 MediaCodecDecoder::ConfigStatus result; 226 MediaCodecDecoder::ConfigStatus result;
204 if (media_codec_bridge_) { 227 if (media_codec_bridge_) {
205 DVLOG(1) << class_name() << "::" << __FUNCTION__ 228 DVLOG(1) << class_name() << "::" << __FUNCTION__
206 << ": reconfiguration is not required, ignoring"; 229 << ": reconfiguration is not required, ignoring";
207 result = kConfigOk; 230 result = kConfigOk;
208 } else { 231 } else {
209 result = ConfigureInternal(); 232 result = ConfigureInternal();
210 233
211 #ifndef NDEBUG 234 #ifndef NDEBUG
212 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 235 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
213 // This DCHECK ensures we won't need to lock this variable. 236 // This DCHECK ensures we won't need to lock this variable.
214 DCHECK(!decoder_thread_.IsRunning()); 237 DCHECK(!decoder_thread_.IsRunning());
215 238
216 // For video the first frame after reconfiguration must be key frame. 239 // For video the first frame after reconfiguration must be key frame.
217 if (result == kConfigOk) 240 if (result == kConfigOk)
218 verify_next_frame_is_key_ = true; 241 verify_next_frame_is_key_ = true;
219 #endif 242 #endif
220 } 243 }
221 244
222 return result; 245 return result;
223 } 246 }
224 247
225 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { 248 void MediaCodecDecoder::SetNeedsPreroll(bool value) {
249 DCHECK(media_task_runner_->BelongsToCurrentThread());
250
251 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ":" << value;
252
253 needs_preroll_ = value;
254 }
255
256 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) {
226 DCHECK(media_task_runner_->BelongsToCurrentThread()); 257 DCHECK(media_task_runner_->BelongsToCurrentThread());
227 258
228 DVLOG(1) << class_name() << "::" << __FUNCTION__ 259 DVLOG(1) << class_name() << "::" << __FUNCTION__
229 << " current_time:" << current_time; 260 << " start_timestamp:" << start_timestamp;
230 261
231 DecoderState state = GetState(); 262 DecoderState state = GetState();
232 if (state == kRunning) { 263 if (state == kPrerolling || state == kRunning) {
233 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; 264 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started";
234 return true; // already started 265 return true; // already started
235 } 266 }
236 267
237 if (state != kPrefetched) { 268 if (state != kPrefetched) {
238 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " 269 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
239 << AsString(state) << ", ignoring"; 270 << AsString(state) << ", ignoring";
240 return false; 271 return false;
241 } 272 }
242 273
243 if (!media_codec_bridge_) { 274 if (!media_codec_bridge_) {
244 DVLOG(0) << class_name() << "::" << __FUNCTION__ 275 DVLOG(0) << class_name() << "::" << __FUNCTION__
245 << ": not configured, ignoring"; 276 << ": not configured, ignoring";
246 return false; 277 return false;
247 } 278 }
248 279
249 DCHECK(!decoder_thread_.IsRunning()); 280 DCHECK(!decoder_thread_.IsRunning());
250 281
251 // We only synchronize video stream. 282 // We only synchronize video stream.
252 // When audio is present, the |current_time| is audio time. 283 if (needs_preroll_) {
253 SynchronizePTSWithTime(current_time); 284 DissociatePTSFromTime(); // associaton will happen after preroll is done.
285 preroll_timestamp_ = start_timestamp;
286 } else {
287 AssociateCurrentTimeWithPTS(start_timestamp);
288 preroll_timestamp_ = base::TimeDelta();
289 }
254 290
255 last_frame_posted_ = false; 291 last_frame_posted_ = false;
256 292
257 // Start the decoder thread 293 // Start the decoder thread
258 if (!decoder_thread_.Start()) { 294 if (!decoder_thread_.Start()) {
259 DVLOG(1) << class_name() << "::" << __FUNCTION__ 295 DVLOG(1) << class_name() << "::" << __FUNCTION__
260 << ": cannot start decoder thread"; 296 << ": cannot start decoder thread";
261 return false; 297 return false;
262 } 298 }
263 299
264 SetState(kRunning); 300 SetState(needs_preroll_ ? kPrerolling : kRunning);
301 needs_preroll_ = false;
265 302
266 decoder_thread_.task_runner()->PostTask( 303 decoder_thread_.task_runner()->PostTask(
267 FROM_HERE, 304 FROM_HERE,
268 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); 305 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
269 306
270 return true; 307 return true;
271 } 308 }
272 309
310 void MediaCodecDecoder::ResumeAfterPreroll() {
311 DCHECK(media_task_runner_->BelongsToCurrentThread());
312
313 DVLOG(1) << class_name() << "::" << __FUNCTION__;
314
315 DCHECK(GetState() == kPrerolled);
316 DCHECK(decoder_thread_.IsRunning());
317
318 SetState(kRunning);
319
320 AssociateCurrentTimeWithPTS(preroll_timestamp_);
321 preroll_timestamp_ = base::TimeDelta();
322
323 decoder_thread_.task_runner()->PostTask(
324 FROM_HERE,
325 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
326 }
327
273 void MediaCodecDecoder::SyncStop() { 328 void MediaCodecDecoder::SyncStop() {
274 DCHECK(media_task_runner_->BelongsToCurrentThread()); 329 DCHECK(media_task_runner_->BelongsToCurrentThread());
275 330
276 DVLOG(1) << class_name() << "::" << __FUNCTION__; 331 DVLOG(1) << class_name() << "::" << __FUNCTION__;
277 332
278 if (GetState() == kError) { 333 if (GetState() == kError) {
279 DVLOG(0) << class_name() << "::" << __FUNCTION__ 334 DVLOG(0) << class_name() << "::" << __FUNCTION__
280 << ": wrong state kError, ignoring"; 335 << ": wrong state kError, ignoring";
281 return; 336 return;
282 } 337 }
283 338
284 // After this method returns, decoder thread will not be running. 339 // After this method returns, decoder thread will not be running.
285 340
286 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 341 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
287 SetState(kInEmergencyStop); 342 SetState(kInEmergencyStop);
288 343
289 decoder_thread_.Stop(); // synchronous 344 decoder_thread_.Stop(); // synchronous
290 345
291 SetState(kStopped); 346 SetState(kStopped);
292 347
293 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|. 348 ReleaseDelayedBuffers();
294 } 349 }
295 350
296 void MediaCodecDecoder::RequestToStop() { 351 void MediaCodecDecoder::RequestToStop() {
297 DCHECK(media_task_runner_->BelongsToCurrentThread()); 352 DCHECK(media_task_runner_->BelongsToCurrentThread());
298 353
299 DVLOG(1) << class_name() << "::" << __FUNCTION__; 354 DVLOG(1) << class_name() << "::" << __FUNCTION__;
300 355
301 DecoderState state = GetState(); 356 DecoderState state = GetState();
302 switch (state) { 357 switch (state) {
303 case kError: 358 case kError:
304 DVLOG(0) << class_name() << "::" << __FUNCTION__ 359 DVLOG(0) << class_name() << "::" << __FUNCTION__
305 << ": wrong state kError, ignoring"; 360 << ": wrong state kError, ignoring";
306 break; 361 break;
307 case kRunning: 362 case kRunning:
308 SetState(kStopping); 363 SetState(kStopping);
309 break; 364 break;
365 case kPrerolling:
366 case kPrerolled:
367 DCHECK(decoder_thread_.IsRunning());
368 // Synchronous stop.
369 decoder_thread_.Stop();
370 SetState(kStopped);
371 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
372 break;
310 case kStopping: 373 case kStopping:
311 break; // ignore 374 break; // ignore
312 case kStopped: 375 case kStopped:
313 case kPrefetching: 376 case kPrefetching:
314 case kPrefetched: 377 case kPrefetched:
315 // There is nothing to wait for, we can sent nofigication right away. 378 // There is nothing to wait for, we can sent nofigication right away.
316 DCHECK(!decoder_thread_.IsRunning()); 379 DCHECK(!decoder_thread_.IsRunning());
317 SetState(kStopped); 380 SetState(kStopped);
318 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 381 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
319 break; 382 break;
(...skipping 10 matching lines...) Expand all
330 << " completed:" << completed; 393 << " completed:" << completed;
331 394
332 decoder_thread_.Stop(); // synchronous 395 decoder_thread_.Stop(); // synchronous
333 396
334 SetState(kStopped); 397 SetState(kStopped);
335 completed_ = completed; 398 completed_ = completed;
336 399
337 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 400 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
338 } 401 }
339 402
403 void MediaCodecDecoder::OnPrerollDone() {
404 DCHECK(media_task_runner_->BelongsToCurrentThread());
405
406 DVLOG(1) << class_name() << "::" << __FUNCTION__;
407
408 if (GetState() == kPrerolling) {
409 SetState(kPrerolled);
410 media_task_runner_->PostTask(FROM_HERE, preroll_done_cb_);
411 }
412 }
413
340 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { 414 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
341 DCHECK(media_task_runner_->BelongsToCurrentThread()); 415 DCHECK(media_task_runner_->BelongsToCurrentThread());
342 416
343 // If |data| contains an aborted data, the last AU will have kAborted status. 417 // If |data| contains an aborted data, the last AU will have kAborted status.
344 bool aborted_data = 418 bool aborted_data =
345 !data.access_units.empty() && 419 !data.access_units.empty() &&
346 data.access_units.back().status == DemuxerStream::kAborted; 420 data.access_units.back().status == DemuxerStream::kAborted;
347 421
348 #ifndef NDEBUG 422 #ifndef NDEBUG
349 const char* explain_if_skipped = 423 const char* explain_if_skipped =
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 request_data_cb_.Run(); 505 request_data_cb_.Run();
432 } 506 }
433 507
434 void MediaCodecDecoder::ProcessNextFrame() { 508 void MediaCodecDecoder::ProcessNextFrame() {
435 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 509 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
436 510
437 DVLOG(2) << class_name() << "::" << __FUNCTION__; 511 DVLOG(2) << class_name() << "::" << __FUNCTION__;
438 512
439 DecoderState state = GetState(); 513 DecoderState state = GetState();
440 514
441 if (state != kRunning && state != kStopping) { 515 if (state != kPrerolling && state != kRunning && state != kStopping) {
442 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; 516 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running";
443 return; 517 return;
444 } 518 }
445 519
446 if (state == kStopping) { 520 if (state == kStopping) {
447 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { 521 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) {
448 DVLOG(1) << class_name() << "::" << __FUNCTION__ 522 DVLOG(1) << class_name() << "::" << __FUNCTION__
449 << ": kStopping, posting OnLastFrameRendered"; 523 << ": kStopping, posting OnLastFrameRendered";
450 media_task_runner_->PostTask( 524 media_task_runner_->PostTask(
451 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, 525 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
452 weak_factory_.GetWeakPtr(), false)); 526 weak_factory_.GetWeakPtr(), false));
453 last_frame_posted_ = true; 527 last_frame_posted_ = true;
454 } 528 }
455 529
456 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. 530 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
457 // We only need to let finish the delayed rendering tasks. 531 // We only need to let finish the delayed rendering tasks.
458 return; 532 return;
459 } 533 }
460 534
461 DCHECK(state == kRunning); 535 DCHECK(state == kPrerolling || state == kRunning);
462 536
463 if (!EnqueueInputBuffer()) 537 if (!EnqueueInputBuffer())
464 return; 538 return;
465 539
466 if (!DepleteOutputBufferQueue()) 540 if (!DepleteOutputBufferQueue())
467 return; 541 return;
468 542
469 // We need a small delay if we want to stop this thread by 543 // We need a small delay if we want to stop this thread by
470 // decoder_thread_.Stop() reliably. 544 // decoder_thread_.Stop() reliably.
471 // The decoder thread message loop processes all pending 545 // The decoder thread message loop processes all pending
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 667
594 DVLOG(2) << class_name() << "::" << __FUNCTION__; 668 DVLOG(2) << class_name() << "::" << __FUNCTION__;
595 669
596 int buffer_index = 0; 670 int buffer_index = 0;
597 size_t offset = 0; 671 size_t offset = 0;
598 size_t size = 0; 672 size_t size = 0;
599 base::TimeDelta pts; 673 base::TimeDelta pts;
600 MediaCodecStatus status; 674 MediaCodecStatus status;
601 bool eos_encountered = false; 675 bool eos_encountered = false;
602 676
677 RenderMode render_mode;
678
603 base::TimeDelta timeout = 679 base::TimeDelta timeout =
604 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); 680 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
605 681
606 // Extract all output buffers that are available. 682 // Extract all output buffers that are available.
607 // Usually there will be only one, but sometimes it is preceeded by 683 // Usually there will be only one, but sometimes it is preceeded by
608 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. 684 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
609 do { 685 do {
610 status = media_codec_bridge_->DequeueOutputBuffer( 686 status = media_codec_bridge_->DequeueOutputBuffer(
611 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, 687 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered,
612 nullptr); 688 nullptr);
613 689
614 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls 690 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
615 // to quickly break the loop after we got all currently available buffers. 691 // to quickly break the loop after we got all currently available buffers.
616 timeout = base::TimeDelta::FromMilliseconds(0); 692 timeout = base::TimeDelta::FromMilliseconds(0);
617 693
618 switch (status) { 694 switch (status) {
619 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 695 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
620 // Output buffers are replaced in MediaCodecBridge, nothing to do. 696 // Output buffers are replaced in MediaCodecBridge, nothing to do.
621 break; 697 break;
622 698
623 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: 699 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
624 DVLOG(2) << class_name() << "::" << __FUNCTION__ 700 DVLOG(2) << class_name() << "::" << __FUNCTION__
625 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; 701 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
626 OnOutputFormatChanged(); 702 OnOutputFormatChanged();
627 break; 703 break;
628 704
629 case MEDIA_CODEC_OK: 705 case MEDIA_CODEC_OK:
630 // We got the decoded frame 706 // We got the decoded frame.
631 Render(buffer_index, size, true, pts, eos_encountered); 707
708 if (pts < preroll_timestamp_)
709 render_mode = kRenderSkip;
710 else if (GetState() == kPrerolling)
711 render_mode = kRenderAfterPreroll;
712 else
713 render_mode = kRenderNow;
714
715 Render(buffer_index, size, render_mode, pts, eos_encountered);
716
717 if (render_mode == kRenderAfterPreroll) {
718 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts:" << pts
719 << " preroll done, stopping frame processing";
720 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
721 return false;
722 }
632 break; 723 break;
633 724
634 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 725 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
635 // Nothing to do. 726 // Nothing to do.
636 break; 727 break;
637 728
638 case MEDIA_CODEC_ERROR: 729 case MEDIA_CODEC_ERROR:
639 DVLOG(0) << class_name() << "::" << __FUNCTION__ 730 DVLOG(0) << class_name() << "::" << __FUNCTION__
640 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; 731 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
641 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 732 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
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