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

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: Addressed Min comments, added unit tests. Created 5 years, 5 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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