Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 CONFIG_FAILURE; |
| 184 } | 189 } |
| 185 | 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 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? | |
|
wolenetz
2015/07/29 22:37:02
Seems there should be either a TODO or a CR commen
Tima Vaisburd
2015/07/30 20:28:35
Yes, but now I tend to think that having a method
wolenetz
2015/07/30 21:10:39
Acknowledged.
| |
| 201 ClearDelayedBuffers(false); | |
| 202 } | |
| 203 | |
| 186 MediaCodecDecoder::ConfigStatus result; | 204 MediaCodecDecoder::ConfigStatus result; |
| 187 if (media_codec_bridge_) { | 205 if (media_codec_bridge_) { |
| 188 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 206 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
| 189 << ": reconfiguration is not required, ignoring"; | 207 << ": reconfiguration is not required, ignoring"; |
| 190 result = CONFIG_OK; | 208 result = CONFIG_OK; |
| 191 } else { | 209 } else { |
| 192 result = ConfigureInternal(); | 210 result = ConfigureInternal(); |
| 193 | 211 |
| 194 #ifndef NDEBUG | 212 #ifndef NDEBUG |
| 195 // We check and reset |verify_next_frame_is_key_| on Decoder thread. | 213 // We check and reset |verify_next_frame_is_key_| on Decoder thread. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 277 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
| 260 | 278 |
| 261 if (GetState() == kError) { | 279 if (GetState() == kError) { |
| 262 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 280 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
| 263 << ": wrong state kError, ignoring"; | 281 << ": wrong state kError, ignoring"; |
| 264 return; | 282 return; |
| 265 } | 283 } |
| 266 | 284 |
| 267 // After this method returns, decoder thread will not be running. | 285 // After this method returns, decoder thread will not be running. |
| 268 | 286 |
| 287 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). | |
| 288 SetState(kInEmergencyStop); | |
| 289 | |
| 269 decoder_thread_.Stop(); // synchronous | 290 decoder_thread_.Stop(); // synchronous |
| 270 state_ = kStopped; | 291 |
| 292 SetState(kStopped); | |
| 271 | 293 |
| 272 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? | 294 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? |
|
wolenetz
2015/07/29 22:37:02
ditto
Tima Vaisburd
2015/07/30 20:28:35
Same as above, removed the comment in the code as
wolenetz
2015/07/30 21:10:39
Acknowledged.
| |
| 273 ReleaseDelayedBuffers(); | 295 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|. |
| 274 } | 296 } |
| 275 | 297 |
| 276 void MediaCodecDecoder::RequestToStop() { | 298 void MediaCodecDecoder::RequestToStop() { |
| 277 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 299 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 278 | 300 |
| 279 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 301 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
| 280 | 302 |
| 281 DecoderState state = GetState(); | 303 DecoderState state = GetState(); |
| 282 switch (state) { | 304 switch (state) { |
| 283 case kError: | 305 case kError: |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 303 } | 325 } |
| 304 } | 326 } |
| 305 | 327 |
| 306 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { | 328 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { |
| 307 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 329 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 308 | 330 |
| 309 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 331 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
| 310 << " completed:" << completed; | 332 << " completed:" << completed; |
| 311 | 333 |
| 312 decoder_thread_.Stop(); // synchronous | 334 decoder_thread_.Stop(); // synchronous |
| 313 state_ = kStopped; | 335 |
| 336 SetState(kStopped); | |
| 314 completed_ = completed; | 337 completed_ = completed; |
| 315 | 338 |
| 316 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 339 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
| 317 } | 340 } |
| 318 | 341 |
| 319 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { | 342 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { |
| 320 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 343 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 321 | 344 |
| 322 // If |data| contains an aborted data, the last AU will have kAborted status. | 345 // If |data| contains an aborted data, the last AU will have kAborted status. |
| 323 bool aborted_data = | 346 bool aborted_data = |
| 324 !data.access_units.empty() && | 347 !data.access_units.empty() && |
| 325 data.access_units.back().status == DemuxerStream::kAborted; | 348 data.access_units.back().status == DemuxerStream::kAborted; |
| 326 | 349 |
| 327 #ifndef NDEBUG | 350 #ifndef NDEBUG |
| 328 const char* explain_if_skipped = | 351 const char* explain_if_skipped = |
| 329 is_incoming_data_invalid_ ? " skipped as invalid" | 352 is_incoming_data_invalid_ ? " skipped as invalid" |
| 330 : (aborted_data ? " skipped as aborted" : ""); | 353 : (aborted_data ? " skipped as aborted" : ""); |
| 331 | 354 |
| 332 for (const auto& unit : data.access_units) | 355 for (const auto& unit : data.access_units) |
| 333 DVLOG(1) << class_name() << "::" << __FUNCTION__ << explain_if_skipped | 356 DVLOG(2) << class_name() << "::" << __FUNCTION__ << explain_if_skipped |
| 334 << " au: " << unit; | 357 << " au: " << unit; |
| 335 for (const auto& configs : data.demuxer_configs) | 358 for (const auto& configs : data.demuxer_configs) |
| 336 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " configs: " << configs; | 359 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " configs: " << configs; |
| 337 #endif | 360 #endif |
| 338 | 361 |
| 339 if (!is_incoming_data_invalid_ && !aborted_data) | 362 if (!is_incoming_data_invalid_ && !aborted_data) |
| 340 au_queue_.PushBack(data); | 363 au_queue_.PushBack(data); |
| 341 | 364 |
| 342 is_incoming_data_invalid_ = false; | 365 is_incoming_data_invalid_ = false; |
| 343 is_data_request_in_progress_ = false; | 366 is_data_request_in_progress_ = false; |
| 344 | 367 |
| 345 // Do not request data if we got kAborted. There is no point to request the | 368 // Do not request data if we got kAborted. There is no point to request the |
| 346 // data after kAborted and before the OnDemuxerSeekDone. | 369 // data after kAborted and before the OnDemuxerSeekDone. |
| 347 if (state_ == kPrefetching && !aborted_data) | 370 if (GetState() == kPrefetching && !aborted_data) |
| 348 PrefetchNextChunk(); | 371 PrefetchNextChunk(); |
| 349 } | 372 } |
| 350 | 373 |
| 351 int MediaCodecDecoder::NumDelayedRenderTasks() const { | 374 int MediaCodecDecoder::NumDelayedRenderTasks() const { |
| 352 return 0; | 375 return 0; |
| 353 } | 376 } |
| 354 | 377 |
| 355 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, | 378 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, |
| 356 bool has_delayed_tasks) { | 379 bool has_delayed_tasks) { |
| 357 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 380 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 358 | 381 |
| 359 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; | 382 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; |
| 360 | 383 |
| 361 if (last_frame_when_stopping || eos_encountered) { | 384 if (last_frame_when_stopping || eos_encountered) { |
| 362 media_task_runner_->PostTask( | 385 media_task_runner_->PostTask( |
| 363 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, | 386 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, |
| 364 weak_factory_.GetWeakPtr(), eos_encountered)); | 387 weak_factory_.GetWeakPtr(), eos_encountered)); |
| 365 last_frame_posted_ = true; | 388 last_frame_posted_ = true; |
| 366 } | 389 } |
| 367 } | 390 } |
| 368 | 391 |
| 369 void MediaCodecDecoder::OnCodecError() { | 392 void MediaCodecDecoder::OnCodecError() { |
| 370 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 393 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 371 | 394 |
| 395 // Ignore codec errors from the moment surface is changed till the | |
| 396 // |media_codec_bridge_| is deleted. | |
| 397 if (needs_reconfigure_) { | |
| 398 DVLOG(1) << class_name() << "::" << __FUNCTION__ | |
| 399 << ": needs reconfigure, ignoring"; | |
| 400 return; | |
| 401 } | |
| 402 | |
| 372 SetState(kError); | 403 SetState(kError); |
| 373 error_cb_.Run(); | 404 error_cb_.Run(); |
| 374 } | 405 } |
| 375 | 406 |
| 376 void MediaCodecDecoder::RequestData() { | 407 void MediaCodecDecoder::RequestData() { |
| 377 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 408 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 378 | 409 |
| 379 // Ensure one data request at a time. | 410 // Ensure one data request at a time. |
| 380 if (!is_data_request_in_progress_) { | 411 if (!is_data_request_in_progress_) { |
| 381 is_data_request_in_progress_ = true; | 412 is_data_request_in_progress_ = true; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. | 458 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. |
| 428 // We only need to let finish the delayed rendering tasks. | 459 // We only need to let finish the delayed rendering tasks. |
| 429 return; | 460 return; |
| 430 } | 461 } |
| 431 | 462 |
| 432 DCHECK(state == kRunning); | 463 DCHECK(state == kRunning); |
| 433 | 464 |
| 434 if (!EnqueueInputBuffer()) | 465 if (!EnqueueInputBuffer()) |
| 435 return; | 466 return; |
| 436 | 467 |
| 437 bool eos_encountered = false; | 468 if (!DepleteOutputBufferQueue()) |
| 438 if (!DepleteOutputBufferQueue(&eos_encountered)) | |
| 439 return; | 469 return; |
| 440 | 470 |
| 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 | 471 // We need a small delay if we want to stop this thread by |
| 448 // decoder_thread_.Stop() reliably. | 472 // decoder_thread_.Stop() reliably. |
| 449 // The decoder thread message loop processes all pending | 473 // The decoder thread message loop processes all pending |
| 450 // (but not delayed) tasks before it can quit; without a delay | 474 // (but not delayed) tasks before it can quit; without a delay |
| 451 // the message loop might be forever processing the pendng tasks. | 475 // the message loop might be forever processing the pendng tasks. |
| 452 decoder_thread_.task_runner()->PostDelayedTask( | 476 decoder_thread_.task_runner()->PostDelayedTask( |
| 453 FROM_HERE, | 477 FROM_HERE, |
| 454 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)), | 478 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)), |
| 455 base::TimeDelta::FromMilliseconds(kNextFrameDelay)); | 479 base::TimeDelta::FromMilliseconds(kNextFrameDelay)); |
| 456 } | 480 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); | 583 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); |
| 560 return false; | 584 return false; |
| 561 } | 585 } |
| 562 | 586 |
| 563 // Have successfully queued input buffer, go to next access unit. | 587 // Have successfully queued input buffer, go to next access unit. |
| 564 au_queue_.Advance(); | 588 au_queue_.Advance(); |
| 565 return true; | 589 return true; |
| 566 } | 590 } |
| 567 | 591 |
| 568 // Returns false if there was MediaCodec error. | 592 // Returns false if there was MediaCodec error. |
| 569 bool MediaCodecDecoder::DepleteOutputBufferQueue(bool* eos_encountered) { | 593 bool MediaCodecDecoder::DepleteOutputBufferQueue() { |
| 570 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 594 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 571 | 595 |
| 572 DVLOG(2) << class_name() << "::" << __FUNCTION__; | 596 DVLOG(2) << class_name() << "::" << __FUNCTION__; |
| 573 | 597 |
| 574 int buffer_index = 0; | 598 int buffer_index = 0; |
| 575 size_t offset = 0; | 599 size_t offset = 0; |
| 576 size_t size = 0; | 600 size_t size = 0; |
| 577 base::TimeDelta pts; | 601 base::TimeDelta pts; |
| 578 MediaCodecStatus status; | 602 MediaCodecStatus status; |
| 603 bool eos_encountered = false; | |
| 579 | 604 |
| 580 base::TimeDelta timeout = | 605 base::TimeDelta timeout = |
| 581 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); | 606 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); |
| 582 | 607 |
| 583 // Extract all output buffers that are available. | 608 // Extract all output buffers that are available. |
| 584 // Usually there will be only one, but sometimes it is preceeded by | 609 // Usually there will be only one, but sometimes it is preceeded by |
| 585 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. | 610 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. |
| 586 do { | 611 do { |
| 587 status = media_codec_bridge_->DequeueOutputBuffer( | 612 status = media_codec_bridge_->DequeueOutputBuffer( |
| 588 timeout, &buffer_index, &offset, &size, &pts, eos_encountered, nullptr); | 613 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, |
| 614 nullptr); | |
| 589 | 615 |
| 590 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls | 616 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls |
| 591 // to quickly break the loop after we got all currently available buffers. | 617 // to quickly break the loop after we got all currently available buffers. |
| 592 timeout = base::TimeDelta::FromMilliseconds(0); | 618 timeout = base::TimeDelta::FromMilliseconds(0); |
| 593 | 619 |
| 594 switch (status) { | 620 switch (status) { |
| 595 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 621 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
| 596 // Output buffers are replaced in MediaCodecBridge, nothing to do. | 622 // Output buffers are replaced in MediaCodecBridge, nothing to do. |
| 597 break; | 623 break; |
| 598 | 624 |
| 599 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 625 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
| 600 DVLOG(2) << class_name() << "::" << __FUNCTION__ | 626 DVLOG(2) << class_name() << "::" << __FUNCTION__ |
| 601 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; | 627 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; |
| 602 OnOutputFormatChanged(); | 628 OnOutputFormatChanged(); |
| 603 break; | 629 break; |
| 604 | 630 |
| 605 case MEDIA_CODEC_OK: | 631 case MEDIA_CODEC_OK: |
| 606 // We got the decoded frame | 632 // We got the decoded frame |
| 607 Render(buffer_index, size, true, pts, *eos_encountered); | 633 Render(buffer_index, size, true, pts, eos_encountered); |
| 608 break; | 634 break; |
| 609 | 635 |
| 610 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 636 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 611 // Nothing to do. | 637 // Nothing to do. |
| 612 break; | 638 break; |
| 613 | 639 |
| 614 case MEDIA_CODEC_ERROR: | 640 case MEDIA_CODEC_ERROR: |
| 615 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 641 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
| 616 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; | 642 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; |
| 617 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); | 643 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); |
| 618 break; | 644 break; |
| 619 | 645 |
| 620 default: | 646 default: |
| 621 NOTREACHED(); | 647 NOTREACHED(); |
| 622 break; | 648 break; |
| 623 } | 649 } |
| 624 | 650 |
| 625 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER && | 651 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER && |
| 626 status != MEDIA_CODEC_ERROR && !*eos_encountered); | 652 status != MEDIA_CODEC_ERROR && !eos_encountered); |
| 627 | 653 |
| 628 return status != MEDIA_CODEC_ERROR; | 654 if (eos_encountered) { |
| 655 DVLOG(1) << class_name() << "::" << __FUNCTION__ | |
| 656 << " EOS dequeued, stopping frame processing"; | |
| 657 return false; | |
| 658 } | |
| 659 | |
| 660 if (status == MEDIA_CODEC_ERROR) { | |
| 661 DVLOG(1) << class_name() << "::" << __FUNCTION__ | |
| 662 << " MediaCodec error, stopping frame processing"; | |
| 663 return false; | |
| 664 } | |
| 665 | |
| 666 return true; | |
| 629 } | 667 } |
| 630 | 668 |
| 631 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { | 669 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { |
| 632 base::AutoLock lock(state_lock_); | 670 base::AutoLock lock(state_lock_); |
| 633 return state_; | 671 return state_; |
| 634 } | 672 } |
| 635 | 673 |
| 636 void MediaCodecDecoder::SetState(DecoderState state) { | 674 void MediaCodecDecoder::SetState(DecoderState state) { |
| 637 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << state; | 675 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << AsString(state); |
| 638 | 676 |
| 639 base::AutoLock lock(state_lock_); | 677 base::AutoLock lock(state_lock_); |
| 640 state_ = state; | 678 state_ = state; |
| 641 } | 679 } |
| 642 | 680 |
| 643 #undef RETURN_STRING | 681 #undef RETURN_STRING |
| 644 #define RETURN_STRING(x) \ | 682 #define RETURN_STRING(x) \ |
| 645 case x: \ | 683 case x: \ |
| 646 return #x; | 684 return #x; |
| 647 | 685 |
| 648 const char* MediaCodecDecoder::AsString(DecoderState state) { | 686 const char* MediaCodecDecoder::AsString(DecoderState state) { |
| 649 switch (state) { | 687 switch (state) { |
| 650 RETURN_STRING(kStopped); | 688 RETURN_STRING(kStopped); |
| 651 RETURN_STRING(kPrefetching); | 689 RETURN_STRING(kPrefetching); |
| 652 RETURN_STRING(kPrefetched); | 690 RETURN_STRING(kPrefetched); |
| 653 RETURN_STRING(kRunning); | 691 RETURN_STRING(kRunning); |
| 654 RETURN_STRING(kStopping); | 692 RETURN_STRING(kStopping); |
| 693 RETURN_STRING(kInEmergencyStop); | |
| 655 RETURN_STRING(kError); | 694 RETURN_STRING(kError); |
| 656 default: | 695 default: |
| 657 return "Unknown DecoderState"; | 696 return "Unknown DecoderState"; |
| 658 } | 697 } |
| 659 } | 698 } |
| 660 | 699 |
| 661 #undef RETURN_STRING | 700 #undef RETURN_STRING |
| 662 | 701 |
| 663 } // namespace media | 702 } // namespace media |
| OLD | NEW |