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 |