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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 |
186 // Here I assume that OnDemuxerConfigsAvailable won't come | 191 // Here I assume that OnDemuxerConfigsAvailable won't come |
187 // in the middle of demuxer data. | 192 // in the middle of demuxer data. |
188 | 193 |
194 if (needs_reconfigure_) { | |
195 DVLOG(1) << class_name() << "::" << __FUNCTION__ | |
196 << ": needs reconfigure, deleting MediaCodec"; | |
197 needs_reconfigure_ = false; | |
198 media_codec_bridge_.reset(); | |
199 | |
200 // No need to release these buffers since the MediaCodec is deleted, just | |
201 // remove their indexes from |delayed_buffers_|. | |
202 | |
203 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? | |
204 ClearDelayedBuffers(false); | |
205 } | |
206 | |
189 MediaCodecDecoder::ConfigStatus result; | 207 MediaCodecDecoder::ConfigStatus result; |
190 if (media_codec_bridge_) { | 208 if (media_codec_bridge_) { |
191 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 209 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
192 << ": reconfiguration is not required, ignoring"; | 210 << ": reconfiguration is not required, ignoring"; |
193 result = CONFIG_OK; | 211 result = CONFIG_OK; |
194 } else { | 212 } else { |
195 result = ConfigureInternal(); | 213 result = ConfigureInternal(); |
196 | 214 |
197 #ifndef NDEBUG | 215 #ifndef NDEBUG |
198 // We check and reset |verify_next_frame_is_key_| on Decoder thread. | 216 // 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... | |
262 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 280 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
263 | 281 |
264 if (GetState() == kError) { | 282 if (GetState() == kError) { |
265 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 283 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
266 << ": wrong state kError, ignoring"; | 284 << ": wrong state kError, ignoring"; |
267 return; | 285 return; |
268 } | 286 } |
269 | 287 |
270 // After this method returns, decoder thread will not be running. | 288 // After this method returns, decoder thread will not be running. |
271 | 289 |
290 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). | |
291 SetState(kInEmergencyStop); | |
292 | |
272 decoder_thread_.Stop(); // synchronous | 293 decoder_thread_.Stop(); // synchronous |
273 state_ = kStopped; | 294 |
295 SetState(kStopped); | |
274 | 296 |
275 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? | 297 // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class? |
276 ReleaseDelayedBuffers(); | 298 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|. |
277 } | 299 } |
278 | 300 |
279 void MediaCodecDecoder::RequestToStop() { | 301 void MediaCodecDecoder::RequestToStop() { |
280 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 302 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
281 | 303 |
282 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 304 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
283 | 305 |
284 DecoderState state = GetState(); | 306 DecoderState state = GetState(); |
285 switch (state) { | 307 switch (state) { |
286 case kError: | 308 case kError: |
(...skipping 19 matching lines...) Expand all Loading... | |
306 } | 328 } |
307 } | 329 } |
308 | 330 |
309 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { | 331 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { |
310 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 332 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
311 | 333 |
312 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 334 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
313 << " completed:" << completed; | 335 << " completed:" << completed; |
314 | 336 |
315 decoder_thread_.Stop(); // synchronous | 337 decoder_thread_.Stop(); // synchronous |
316 state_ = kStopped; | 338 |
339 SetState(kStopped); | |
317 completed_ = completed; | 340 completed_ = completed; |
318 | 341 |
319 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 342 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
320 } | 343 } |
321 | 344 |
322 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { | 345 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { |
323 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 346 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
324 | 347 |
325 // If |data| contains an aborted data, the last AU will have kAborted status. | 348 // If |data| contains an aborted data, the last AU will have kAborted status. |
326 bool aborted_data = | 349 bool aborted_data = |
327 !data.access_units.empty() && | 350 !data.access_units.empty() && |
328 data.access_units.back().status == DemuxerStream::kAborted; | 351 data.access_units.back().status == DemuxerStream::kAborted; |
329 | 352 |
330 #ifndef NDEBUG | 353 #ifndef NDEBUG |
331 const char* explain_if_skipped = | 354 const char* explain_if_skipped = |
332 is_incoming_data_invalid_ ? " skipped as invalid" | 355 is_incoming_data_invalid_ ? " skipped as invalid" |
333 : (aborted_data ? " skipped as aborted" : ""); | 356 : (aborted_data ? " skipped as aborted" : ""); |
334 | 357 |
335 for (const auto& unit : data.access_units) | 358 for (const auto& unit : data.access_units) |
336 DVLOG(1) << class_name() << "::" << __FUNCTION__ << explain_if_skipped | 359 DVLOG(2) << class_name() << "::" << __FUNCTION__ << explain_if_skipped |
337 << " au: " << unit; | 360 << " au: " << unit; |
338 for (const auto& configs : data.demuxer_configs) | 361 for (const auto& configs : data.demuxer_configs) |
339 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " configs: " << configs; | 362 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " configs: " << configs; |
340 #endif | 363 #endif |
341 | 364 |
342 if (!is_incoming_data_invalid_ && !aborted_data) | 365 if (!is_incoming_data_invalid_ && !aborted_data) |
343 au_queue_.PushBack(data); | 366 au_queue_.PushBack(data); |
344 | 367 |
345 is_incoming_data_invalid_ = false; | 368 is_incoming_data_invalid_ = false; |
346 is_data_request_in_progress_ = false; | 369 is_data_request_in_progress_ = false; |
347 | 370 |
348 // Do not request data if we got kAborted. There is no point to request the | 371 // Do not request data if we got kAborted. There is no point to request the |
349 // data after kAborted and before the OnDemuxerSeekDone. | 372 // data after kAborted and before the OnDemuxerSeekDone. |
350 if (state_ == kPrefetching && !aborted_data) | 373 if (GetState() == kPrefetching && !aborted_data) |
351 PrefetchNextChunk(); | 374 PrefetchNextChunk(); |
352 } | 375 } |
353 | 376 |
354 int MediaCodecDecoder::NumDelayedRenderTasks() const { | 377 int MediaCodecDecoder::NumDelayedRenderTasks() const { |
355 return 0; | 378 return 0; |
356 } | 379 } |
357 | 380 |
358 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, | 381 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, |
359 bool has_delayed_tasks) { | 382 bool has_delayed_tasks) { |
360 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 383 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
361 | 384 |
362 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; | 385 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; |
363 | 386 |
364 if (last_frame_when_stopping || eos_encountered) { | 387 if (last_frame_when_stopping || eos_encountered) { |
365 media_task_runner_->PostTask( | 388 media_task_runner_->PostTask( |
366 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, | 389 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, |
367 weak_factory_.GetWeakPtr(), eos_encountered)); | 390 weak_factory_.GetWeakPtr(), eos_encountered)); |
368 last_frame_posted_ = true; | 391 last_frame_posted_ = true; |
369 } | 392 } |
370 } | 393 } |
371 | 394 |
372 void MediaCodecDecoder::OnCodecError() { | 395 void MediaCodecDecoder::OnCodecError() { |
373 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 396 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
374 | 397 |
398 // Ignore codec errors from the moment surface is changed till the | |
Tima Vaisburd
2015/07/23 00:37:49
Also added this check.
| |
399 // |media_codec_bridge_| is deleted. | |
400 if (needs_reconfigure_) { | |
401 DVLOG(1) << class_name() << "::" << __FUNCTION__ | |
402 << ": needs reconfigure, ignoring"; | |
403 return; | |
404 } | |
405 | |
375 SetState(kError); | 406 SetState(kError); |
376 error_cb_.Run(); | 407 error_cb_.Run(); |
377 } | 408 } |
378 | 409 |
379 void MediaCodecDecoder::RequestData() { | 410 void MediaCodecDecoder::RequestData() { |
380 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 411 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
381 | 412 |
382 // Ensure one data request at a time. | 413 // Ensure one data request at a time. |
383 if (!is_data_request_in_progress_) { | 414 if (!is_data_request_in_progress_) { |
384 is_data_request_in_progress_ = true; | 415 is_data_request_in_progress_ = true; |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 | 661 |
631 return status != MEDIA_CODEC_ERROR; | 662 return status != MEDIA_CODEC_ERROR; |
632 } | 663 } |
633 | 664 |
634 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { | 665 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { |
635 base::AutoLock lock(state_lock_); | 666 base::AutoLock lock(state_lock_); |
636 return state_; | 667 return state_; |
637 } | 668 } |
638 | 669 |
639 void MediaCodecDecoder::SetState(DecoderState state) { | 670 void MediaCodecDecoder::SetState(DecoderState state) { |
640 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << state; | 671 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << AsString(state); |
641 | 672 |
642 base::AutoLock lock(state_lock_); | 673 base::AutoLock lock(state_lock_); |
643 state_ = state; | 674 state_ = state; |
644 } | 675 } |
645 | 676 |
646 #undef RETURN_STRING | 677 #undef RETURN_STRING |
647 #define RETURN_STRING(x) \ | 678 #define RETURN_STRING(x) \ |
648 case x: \ | 679 case x: \ |
649 return #x; | 680 return #x; |
650 | 681 |
651 const char* MediaCodecDecoder::AsString(DecoderState state) { | 682 const char* MediaCodecDecoder::AsString(DecoderState state) { |
652 switch (state) { | 683 switch (state) { |
653 RETURN_STRING(kStopped); | 684 RETURN_STRING(kStopped); |
654 RETURN_STRING(kPrefetching); | 685 RETURN_STRING(kPrefetching); |
655 RETURN_STRING(kPrefetched); | 686 RETURN_STRING(kPrefetched); |
656 RETURN_STRING(kRunning); | 687 RETURN_STRING(kRunning); |
657 RETURN_STRING(kStopping); | 688 RETURN_STRING(kStopping); |
689 RETURN_STRING(kInEmergencyStop); | |
658 RETURN_STRING(kError); | 690 RETURN_STRING(kError); |
659 default: | 691 default: |
660 return "Unknown DecoderState"; | 692 return "Unknown DecoderState"; |
661 } | 693 } |
662 } | 694 } |
663 | 695 |
664 #undef RETURN_STRING | 696 #undef RETURN_STRING |
665 | 697 |
666 } // namespace media | 698 } // namespace media |
OLD | NEW |