| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |