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

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

Issue 1242913004: MediaCodecPlayer implementation (stage 3 - browser seek and surface change) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-seek
Patch Set: Rebased, changed DCHECKs. 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 22 matching lines...) Expand all
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& stop_done_cb, 38 const base::Closure& stop_done_cb,
39 const base::Closure& error_cb, 39 const base::Closure& error_cb,
40 const char* decoder_thread_name) 40 const char* decoder_thread_name)
41 : media_task_runner_(media_task_runner), 41 : media_task_runner_(media_task_runner),
42 decoder_thread_(decoder_thread_name), 42 decoder_thread_(decoder_thread_name),
43 needs_reconfigure_(false),
43 external_request_data_cb_(external_request_data_cb), 44 external_request_data_cb_(external_request_data_cb),
44 starvation_cb_(starvation_cb), 45 starvation_cb_(starvation_cb),
45 stop_done_cb_(stop_done_cb), 46 stop_done_cb_(stop_done_cb),
46 error_cb_(error_cb), 47 error_cb_(error_cb),
47 state_(kStopped), 48 state_(kStopped),
48 eos_enqueued_(false), 49 eos_enqueued_(false),
49 completed_(false), 50 completed_(false),
50 last_frame_posted_(false), 51 last_frame_posted_(false),
51 is_data_request_in_progress_(false), 52 is_data_request_in_progress_(false),
52 is_incoming_data_invalid_(false), 53 is_incoming_data_invalid_(false),
(...skipping 22 matching lines...) Expand all
75 76
76 const char* MediaCodecDecoder::class_name() const { 77 const char* MediaCodecDecoder::class_name() const {
77 return "Decoder"; 78 return "Decoder";
78 } 79 }
79 80
80 void MediaCodecDecoder::ReleaseDecoderResources() { 81 void MediaCodecDecoder::ReleaseDecoderResources() {
81 DCHECK(media_task_runner_->BelongsToCurrentThread()); 82 DCHECK(media_task_runner_->BelongsToCurrentThread());
82 83
83 DVLOG(1) << class_name() << "::" << __FUNCTION__; 84 DVLOG(1) << class_name() << "::" << __FUNCTION__;
84 85
86 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
87 SetState(kInEmergencyStop);
88
85 decoder_thread_.Stop(); // synchronous 89 decoder_thread_.Stop(); // synchronous
86 state_ = kStopped; 90
91 SetState(kStopped);
87 media_codec_bridge_.reset(); 92 media_codec_bridge_.reset();
88 } 93 }
89 94
90 void MediaCodecDecoder::Flush() { 95 void MediaCodecDecoder::Flush() {
91 DCHECK(media_task_runner_->BelongsToCurrentThread()); 96 DCHECK(media_task_runner_->BelongsToCurrentThread());
92 97
93 DVLOG(1) << class_name() << "::" << __FUNCTION__; 98 DVLOG(1) << class_name() << "::" << __FUNCTION__;
94 99
95 DCHECK_EQ(GetState(), kStopped); 100 DCHECK_EQ(GetState(), kStopped);
96 101
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 PrefetchNextChunk(); 178 PrefetchNextChunk();
174 } 179 }
175 180
176 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure() { 181 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure() {
177 DCHECK(media_task_runner_->BelongsToCurrentThread()); 182 DCHECK(media_task_runner_->BelongsToCurrentThread());
178 183
179 DVLOG(1) << class_name() << "::" << __FUNCTION__; 184 DVLOG(1) << class_name() << "::" << __FUNCTION__;
180 185
181 if (GetState() == kError) { 186 if (GetState() == kError) {
182 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; 187 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
183 return CONFIG_FAILURE; 188 return kConfigFailure;
189 }
190
191 if (needs_reconfigure_) {
192 DVLOG(1) << class_name() << "::" << __FUNCTION__
193 << ": needs reconfigure, deleting MediaCodec";
194 needs_reconfigure_ = false;
195 media_codec_bridge_.reset();
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);
184 } 201 }
185 202
186 MediaCodecDecoder::ConfigStatus result; 203 MediaCodecDecoder::ConfigStatus result;
187 if (media_codec_bridge_) { 204 if (media_codec_bridge_) {
188 DVLOG(1) << class_name() << "::" << __FUNCTION__ 205 DVLOG(1) << class_name() << "::" << __FUNCTION__
189 << ": reconfiguration is not required, ignoring"; 206 << ": reconfiguration is not required, ignoring";
190 result = CONFIG_OK; 207 result = kConfigOk;
191 } else { 208 } else {
192 result = ConfigureInternal(); 209 result = ConfigureInternal();
193 210
194 #ifndef NDEBUG 211 #ifndef NDEBUG
195 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 212 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
196 // This DCHECK ensures we won't need to lock this variable. 213 // This DCHECK ensures we won't need to lock this variable.
197 DCHECK(!decoder_thread_.IsRunning()); 214 DCHECK(!decoder_thread_.IsRunning());
198 215
199 // For video the first frame after reconfiguration must be key frame. 216 // For video the first frame after reconfiguration must be key frame.
200 if (result == CONFIG_OK) 217 if (result == kConfigOk)
201 verify_next_frame_is_key_ = true; 218 verify_next_frame_is_key_ = true;
202 #endif 219 #endif
203 } 220 }
204 221
205 return result; 222 return result;
206 } 223 }
207 224
208 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { 225 bool MediaCodecDecoder::Start(base::TimeDelta current_time) {
209 DCHECK(media_task_runner_->BelongsToCurrentThread()); 226 DCHECK(media_task_runner_->BelongsToCurrentThread());
210 227
211 DVLOG(1) << class_name() << "::" << __FUNCTION__ 228 DVLOG(1) << class_name() << "::" << __FUNCTION__
212 << " current_time:" << current_time; 229 << " current_time:" << current_time;
213 230
214 DecoderState state = GetState(); 231 DecoderState state = GetState();
215 if (state == kRunning) { 232 if (state == kRunning) {
216 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; 233 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started";
217 return true; // already started 234 return true; // already started
218 } 235 }
219 236
220 if (state != kPrefetched) { 237 if (state != kPrefetched) {
221 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " 238 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
222 << AsString(state) << " ignoring"; 239 << AsString(state) << ", ignoring";
223 return false; 240 return false;
224 } 241 }
225 242
226 if (!media_codec_bridge_) { 243 if (!media_codec_bridge_) {
227 DVLOG(0) << class_name() << "::" << __FUNCTION__ 244 DVLOG(0) << class_name() << "::" << __FUNCTION__
228 << ": not configured, ignoring"; 245 << ": not configured, ignoring";
229 return false; 246 return false;
230 } 247 }
231 248
232 DCHECK(!decoder_thread_.IsRunning()); 249 DCHECK(!decoder_thread_.IsRunning());
(...skipping 26 matching lines...) Expand all
259 DVLOG(1) << class_name() << "::" << __FUNCTION__; 276 DVLOG(1) << class_name() << "::" << __FUNCTION__;
260 277
261 if (GetState() == kError) { 278 if (GetState() == kError) {
262 DVLOG(0) << class_name() << "::" << __FUNCTION__ 279 DVLOG(0) << class_name() << "::" << __FUNCTION__
263 << ": wrong state kError, ignoring"; 280 << ": wrong state kError, ignoring";
264 return; 281 return;
265 } 282 }
266 283
267 // After this method returns, decoder thread will not be running. 284 // After this method returns, decoder thread will not be running.
268 285
286 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
287 SetState(kInEmergencyStop);
288
269 decoder_thread_.Stop(); // synchronous 289 decoder_thread_.Stop(); // synchronous
270 state_ = kStopped;
271 290
272 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? 291 SetState(kStopped);
273 ReleaseDelayedBuffers(); 292
293 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|.
274 } 294 }
275 295
276 void MediaCodecDecoder::RequestToStop() { 296 void MediaCodecDecoder::RequestToStop() {
277 DCHECK(media_task_runner_->BelongsToCurrentThread()); 297 DCHECK(media_task_runner_->BelongsToCurrentThread());
278 298
279 DVLOG(1) << class_name() << "::" << __FUNCTION__; 299 DVLOG(1) << class_name() << "::" << __FUNCTION__;
280 300
281 DecoderState state = GetState(); 301 DecoderState state = GetState();
282 switch (state) { 302 switch (state) {
283 case kError: 303 case kError:
(...skipping 19 matching lines...) Expand all
303 } 323 }
304 } 324 }
305 325
306 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { 326 void MediaCodecDecoder::OnLastFrameRendered(bool completed) {
307 DCHECK(media_task_runner_->BelongsToCurrentThread()); 327 DCHECK(media_task_runner_->BelongsToCurrentThread());
308 328
309 DVLOG(1) << class_name() << "::" << __FUNCTION__ 329 DVLOG(1) << class_name() << "::" << __FUNCTION__
310 << " completed:" << completed; 330 << " completed:" << completed;
311 331
312 decoder_thread_.Stop(); // synchronous 332 decoder_thread_.Stop(); // synchronous
313 state_ = kStopped; 333
334 SetState(kStopped);
314 completed_ = completed; 335 completed_ = completed;
315 336
316 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 337 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
317 } 338 }
318 339
319 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { 340 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
320 DCHECK(media_task_runner_->BelongsToCurrentThread()); 341 DCHECK(media_task_runner_->BelongsToCurrentThread());
321 342
322 // If |data| contains an aborted data, the last AU will have kAborted status. 343 // If |data| contains an aborted data, the last AU will have kAborted status.
323 bool aborted_data = 344 bool aborted_data =
324 !data.access_units.empty() && 345 !data.access_units.empty() &&
325 data.access_units.back().status == DemuxerStream::kAborted; 346 data.access_units.back().status == DemuxerStream::kAborted;
326 347
327 #ifndef NDEBUG 348 #ifndef NDEBUG
328 const char* explain_if_skipped = 349 const char* explain_if_skipped =
329 is_incoming_data_invalid_ ? " skipped as invalid" 350 is_incoming_data_invalid_ ? " skipped as invalid"
330 : (aborted_data ? " skipped as aborted" : ""); 351 : (aborted_data ? " skipped as aborted" : "");
331 352
332 for (const auto& unit : data.access_units) 353 for (const auto& unit : data.access_units)
333 DVLOG(1) << class_name() << "::" << __FUNCTION__ << explain_if_skipped 354 DVLOG(2) << class_name() << "::" << __FUNCTION__ << explain_if_skipped
334 << " au: " << unit; 355 << " au: " << unit;
335 for (const auto& configs : data.demuxer_configs) 356 for (const auto& configs : data.demuxer_configs)
336 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " configs: " << configs; 357 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " configs: " << configs;
337 #endif 358 #endif
338 359
339 if (!is_incoming_data_invalid_ && !aborted_data) 360 if (!is_incoming_data_invalid_ && !aborted_data)
340 au_queue_.PushBack(data); 361 au_queue_.PushBack(data);
341 362
342 is_incoming_data_invalid_ = false; 363 is_incoming_data_invalid_ = false;
343 is_data_request_in_progress_ = false; 364 is_data_request_in_progress_ = false;
344 365
345 // Do not request data if we got kAborted. There is no point to request the 366 // Do not request data if we got kAborted. There is no point to request the
346 // data after kAborted and before the OnDemuxerSeekDone. 367 // data after kAborted and before the OnDemuxerSeekDone.
347 if (state_ == kPrefetching && !aborted_data) 368 if (GetState() == kPrefetching && !aborted_data)
348 PrefetchNextChunk(); 369 PrefetchNextChunk();
349 } 370 }
350 371
351 int MediaCodecDecoder::NumDelayedRenderTasks() const { 372 int MediaCodecDecoder::NumDelayedRenderTasks() const {
352 return 0; 373 return 0;
353 } 374 }
354 375
355 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, 376 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
356 bool has_delayed_tasks) { 377 bool has_delayed_tasks) {
357 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 378 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
358 379
359 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; 380 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
360 381
361 if (last_frame_when_stopping || eos_encountered) { 382 if (last_frame_when_stopping || eos_encountered) {
362 media_task_runner_->PostTask( 383 media_task_runner_->PostTask(
363 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, 384 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
364 weak_factory_.GetWeakPtr(), eos_encountered)); 385 weak_factory_.GetWeakPtr(), eos_encountered));
365 last_frame_posted_ = true; 386 last_frame_posted_ = true;
366 } 387 }
367 } 388 }
368 389
369 void MediaCodecDecoder::OnCodecError() { 390 void MediaCodecDecoder::OnCodecError() {
370 DCHECK(media_task_runner_->BelongsToCurrentThread()); 391 DCHECK(media_task_runner_->BelongsToCurrentThread());
371 392
393 // Ignore codec errors from the moment surface is changed till the
394 // |media_codec_bridge_| is deleted.
395 if (needs_reconfigure_) {
396 DVLOG(1) << class_name() << "::" << __FUNCTION__
397 << ": needs reconfigure, ignoring";
398 return;
399 }
400
372 SetState(kError); 401 SetState(kError);
373 error_cb_.Run(); 402 error_cb_.Run();
374 } 403 }
375 404
376 void MediaCodecDecoder::RequestData() { 405 void MediaCodecDecoder::RequestData() {
377 DCHECK(media_task_runner_->BelongsToCurrentThread()); 406 DCHECK(media_task_runner_->BelongsToCurrentThread());
378 407
379 // Ensure one data request at a time. 408 // Ensure one data request at a time.
380 if (!is_data_request_in_progress_) { 409 if (!is_data_request_in_progress_) {
381 is_data_request_in_progress_ = true; 410 is_data_request_in_progress_ = true;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. 456 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
428 // We only need to let finish the delayed rendering tasks. 457 // We only need to let finish the delayed rendering tasks.
429 return; 458 return;
430 } 459 }
431 460
432 DCHECK(state == kRunning); 461 DCHECK(state == kRunning);
433 462
434 if (!EnqueueInputBuffer()) 463 if (!EnqueueInputBuffer())
435 return; 464 return;
436 465
437 bool eos_encountered = false; 466 if (!DepleteOutputBufferQueue())
438 if (!DepleteOutputBufferQueue(&eos_encountered))
439 return; 467 return;
440 468
441 if (eos_encountered) {
442 DVLOG(1) << class_name() << "::" << __FUNCTION__
443 << " EOS dequeued, stopping frame processing";
444 return;
445 }
446
447 // We need a small delay if we want to stop this thread by 469 // We need a small delay if we want to stop this thread by
448 // decoder_thread_.Stop() reliably. 470 // decoder_thread_.Stop() reliably.
449 // The decoder thread message loop processes all pending 471 // The decoder thread message loop processes all pending
450 // (but not delayed) tasks before it can quit; without a delay 472 // (but not delayed) tasks before it can quit; without a delay
451 // the message loop might be forever processing the pendng tasks. 473 // the message loop might be forever processing the pendng tasks.
452 decoder_thread_.task_runner()->PostDelayedTask( 474 decoder_thread_.task_runner()->PostDelayedTask(
453 FROM_HERE, 475 FROM_HERE,
454 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)), 476 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)),
455 base::TimeDelta::FromMilliseconds(kNextFrameDelay)); 477 base::TimeDelta::FromMilliseconds(kNextFrameDelay));
456 } 478 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 581 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
560 return false; 582 return false;
561 } 583 }
562 584
563 // Have successfully queued input buffer, go to next access unit. 585 // Have successfully queued input buffer, go to next access unit.
564 au_queue_.Advance(); 586 au_queue_.Advance();
565 return true; 587 return true;
566 } 588 }
567 589
568 // Returns false if there was MediaCodec error. 590 // Returns false if there was MediaCodec error.
569 bool MediaCodecDecoder::DepleteOutputBufferQueue(bool* eos_encountered) { 591 bool MediaCodecDecoder::DepleteOutputBufferQueue() {
570 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 592 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
571 593
572 DVLOG(2) << class_name() << "::" << __FUNCTION__; 594 DVLOG(2) << class_name() << "::" << __FUNCTION__;
573 595
574 int buffer_index = 0; 596 int buffer_index = 0;
575 size_t offset = 0; 597 size_t offset = 0;
576 size_t size = 0; 598 size_t size = 0;
577 base::TimeDelta pts; 599 base::TimeDelta pts;
578 MediaCodecStatus status; 600 MediaCodecStatus status;
601 bool eos_encountered = false;
579 602
580 base::TimeDelta timeout = 603 base::TimeDelta timeout =
581 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); 604 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
582 605
583 // Extract all output buffers that are available. 606 // Extract all output buffers that are available.
584 // Usually there will be only one, but sometimes it is preceeded by 607 // Usually there will be only one, but sometimes it is preceeded by
585 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. 608 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
586 do { 609 do {
587 status = media_codec_bridge_->DequeueOutputBuffer( 610 status = media_codec_bridge_->DequeueOutputBuffer(
588 timeout, &buffer_index, &offset, &size, &pts, eos_encountered, nullptr); 611 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered,
612 nullptr);
589 613
590 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls 614 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
591 // to quickly break the loop after we got all currently available buffers. 615 // to quickly break the loop after we got all currently available buffers.
592 timeout = base::TimeDelta::FromMilliseconds(0); 616 timeout = base::TimeDelta::FromMilliseconds(0);
593 617
594 switch (status) { 618 switch (status) {
595 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 619 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
596 // Output buffers are replaced in MediaCodecBridge, nothing to do. 620 // Output buffers are replaced in MediaCodecBridge, nothing to do.
597 break; 621 break;
598 622
599 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: 623 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
600 DVLOG(2) << class_name() << "::" << __FUNCTION__ 624 DVLOG(2) << class_name() << "::" << __FUNCTION__
601 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; 625 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
602 OnOutputFormatChanged(); 626 OnOutputFormatChanged();
603 break; 627 break;
604 628
605 case MEDIA_CODEC_OK: 629 case MEDIA_CODEC_OK:
606 // We got the decoded frame 630 // We got the decoded frame
607 Render(buffer_index, size, true, pts, *eos_encountered); 631 Render(buffer_index, size, true, pts, eos_encountered);
608 break; 632 break;
609 633
610 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 634 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
611 // Nothing to do. 635 // Nothing to do.
612 break; 636 break;
613 637
614 case MEDIA_CODEC_ERROR: 638 case MEDIA_CODEC_ERROR:
615 DVLOG(0) << class_name() << "::" << __FUNCTION__ 639 DVLOG(0) << class_name() << "::" << __FUNCTION__
616 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; 640 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
617 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 641 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
618 break; 642 break;
619 643
620 default: 644 default:
621 NOTREACHED(); 645 NOTREACHED();
622 break; 646 break;
623 } 647 }
624 648
625 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER && 649 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER &&
626 status != MEDIA_CODEC_ERROR && !*eos_encountered); 650 status != MEDIA_CODEC_ERROR && !eos_encountered);
627 651
628 return status != MEDIA_CODEC_ERROR; 652 if (eos_encountered) {
653 DVLOG(1) << class_name() << "::" << __FUNCTION__
654 << " EOS dequeued, stopping frame processing";
655 return false;
656 }
657
658 if (status == MEDIA_CODEC_ERROR) {
659 DVLOG(1) << class_name() << "::" << __FUNCTION__
660 << " MediaCodec error, stopping frame processing";
661 return false;
662 }
663
664 return true;
629 } 665 }
630 666
631 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { 667 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const {
632 base::AutoLock lock(state_lock_); 668 base::AutoLock lock(state_lock_);
633 return state_; 669 return state_;
634 } 670 }
635 671
636 void MediaCodecDecoder::SetState(DecoderState state) { 672 void MediaCodecDecoder::SetState(DecoderState state) {
637 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << state; 673 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << AsString(state);
638 674
639 base::AutoLock lock(state_lock_); 675 base::AutoLock lock(state_lock_);
640 state_ = state; 676 state_ = state;
641 } 677 }
642 678
643 #undef RETURN_STRING 679 #undef RETURN_STRING
644 #define RETURN_STRING(x) \ 680 #define RETURN_STRING(x) \
645 case x: \ 681 case x: \
646 return #x; 682 return #x;
647 683
648 const char* MediaCodecDecoder::AsString(DecoderState state) { 684 const char* MediaCodecDecoder::AsString(DecoderState state) {
649 switch (state) { 685 switch (state) {
650 RETURN_STRING(kStopped); 686 RETURN_STRING(kStopped);
651 RETURN_STRING(kPrefetching); 687 RETURN_STRING(kPrefetching);
652 RETURN_STRING(kPrefetched); 688 RETURN_STRING(kPrefetched);
653 RETURN_STRING(kRunning); 689 RETURN_STRING(kRunning);
654 RETURN_STRING(kStopping); 690 RETURN_STRING(kStopping);
691 RETURN_STRING(kInEmergencyStop);
655 RETURN_STRING(kError); 692 RETURN_STRING(kError);
656 default: 693 default:
657 return "Unknown DecoderState"; 694 return "Unknown DecoderState";
658 } 695 }
659 } 696 }
660 697
661 #undef RETURN_STRING 698 #undef RETURN_STRING
662 699
663 } // namespace media 700 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698