diff options
author | qinmin@chromium.org <qinmin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-01 04:12:03 +0000 |
---|---|---|
committer | qinmin@chromium.org <qinmin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-01 04:12:03 +0000 |
commit | c01f1e52b28f3edd57a67691e7c90a8fc0b5d645 (patch) | |
tree | da65f97519a3bf931bbabf3a9884e36c9cc31b27 /media | |
parent | 17571649651d6120d076184d69b57995ac35cd5f (diff) | |
download | chromium_src-c01f1e52b28f3edd57a67691e7c90a8fc0b5d645.zip chromium_src-c01f1e52b28f3edd57a67691e7c90a8fc0b5d645.tar.gz chromium_src-c01f1e52b28f3edd57a67691e7c90a8fc0b5d645.tar.bz2 |
Fix a DCHECK error that a/v threads are not stopped on the UI thread
There are some DCHECK issue when decoding audio/video in browser process:
1. Threads has to be stopped on the thread where they are created.
2. Threads cannot be stopped on the UI thread because it does not allow IO.
Since these 2 conditions are conflicting with each other, we are unable to dynamically create/destroy a thread without causing DCHECK errors.
So this change makes audio/video decoding threads lazy instances. And we don't need to recreate them each time when a decoder is created.
BUG=245486
Review URL: https://chromiumcodereview.appspot.com/15715026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203563 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/android/media_source_player.cc | 58 | ||||
-rw-r--r-- | media/base/android/media_source_player.h | 7 |
2 files changed, 42 insertions, 23 deletions
diff --git a/media/base/android/media_source_player.cc b/media/base/android/media_source_player.cc index 24117c4..a305ca8 100644 --- a/media/base/android/media_source_player.cc +++ b/media/base/android/media_source_player.cc @@ -8,6 +8,7 @@ #include "base/android/jni_string.h" #include "base/basictypes.h" #include "base/bind.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/threading/thread.h" @@ -15,15 +16,43 @@ #include "media/base/android/media_player_manager.h" namespace { + // Timeout value for media codec operations. const int kMediaCodecTimeoutInMicroseconds = 5000; + +class DecoderThread : public base::Thread { + public: + virtual ~DecoderThread() {} + protected: + DecoderThread(const char* name) : base::Thread(name) { Start(); } +}; + +class AudioDecoderThread : public DecoderThread { + public: + AudioDecoderThread() : DecoderThread("MediaSource_AudioDecoderThread") {} +}; + +class VideoDecoderThread : public DecoderThread { + public: + VideoDecoderThread() : DecoderThread("MediaSource_VideoDecoderThread") {} +}; + +// TODO(qinmin): Check if it is tolerable to use worker pool to handle all the +// decoding tasks so that we don't need the global threads here. +// http://crbug.com/245750 +base::LazyInstance<AudioDecoderThread>::Leaky + g_audio_decoder_thread = LAZY_INSTANCE_INITIALIZER; + +base::LazyInstance<VideoDecoderThread>::Leaky + g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER; + } namespace media { -MediaDecoderJob::MediaDecoderJob( - bool is_audio, const scoped_refptr<base::MessageLoopProxy>& message_loop) - : message_loop_(message_loop), +MediaDecoderJob::MediaDecoderJob(base::Thread* thread, bool is_audio) + : message_loop_(base::MessageLoopProxy::current()), + thread_(thread), needs_flush_(false), is_audio_(is_audio), weak_this_(this) { @@ -35,9 +64,8 @@ MediaDecoderJob::~MediaDecoderJob() {} class AudioDecoderJob : public MediaDecoderJob { public: AudioDecoderJob( - const scoped_refptr<base::MessageLoopProxy>& message_loop, - const AudioCodec audio_codec, int sample_rate, int channel_count, - const uint8* extra_data, size_t extra_data_size); + const AudioCodec audio_codec, int sample_rate, + int channel_count, const uint8* extra_data, size_t extra_data_size); virtual ~AudioDecoderJob() {} }; @@ -45,7 +73,6 @@ class AudioDecoderJob : public MediaDecoderJob { class VideoDecoderJob : public MediaDecoderJob { public: VideoDecoderJob( - const scoped_refptr<base::MessageLoopProxy>& message_loop, const VideoCodec video_codec, const gfx::Size& size, jobject surface); virtual ~VideoDecoderJob() {} @@ -58,8 +85,6 @@ void MediaDecoderJob::Decode( const base::Time& start_wallclock_time, const base::TimeDelta& start_presentation_timestamp, const MediaDecoderJob::DecoderCallback& callback) { - if (!thread_->IsRunning()) - thread_->Start(); thread_->message_loop()->PostTask(FROM_HERE, base::Bind( &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit, start_wallclock_time, start_presentation_timestamp, needs_flush_, @@ -169,28 +194,24 @@ void MediaDecoderJob::Release() { } VideoDecoderJob::VideoDecoderJob( - const scoped_refptr<base::MessageLoopProxy>& message_loop, const VideoCodec video_codec, const gfx::Size& size, jobject surface) - : MediaDecoderJob(false, message_loop) { + : MediaDecoderJob(g_video_decoder_thread.Pointer(), false) { scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec)); codec->Start(video_codec, size, surface); media_codec_bridge_.reset(codec.release()); - thread_.reset(new base::Thread("MediaSource_VideoDecoderThread")); } AudioDecoderJob::AudioDecoderJob( - const scoped_refptr<base::MessageLoopProxy>& message_loop, const AudioCodec audio_codec, int sample_rate, int channel_count, const uint8* extra_data, size_t extra_data_size) - : MediaDecoderJob(true, message_loop) { + : MediaDecoderJob(g_audio_decoder_thread.Pointer(), true) { scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec)); codec->Start(audio_codec, sample_rate, channel_count, extra_data, extra_data_size, true); media_codec_bridge_.reset(codec.release()); - thread_.reset(new base::Thread("MediaSource_AudioDecoderThread")); } MediaSourcePlayer::MediaSourcePlayer( @@ -236,8 +257,7 @@ void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { if (HasVideo()) { video_decoder_job_.reset(new VideoDecoderJob( - base::MessageLoopProxy::current(), video_codec_, - gfx::Size(width_, height_), surface.j_surface().obj())); + video_codec_, gfx::Size(width_, height_), surface.j_surface().obj())); } // Inform the fullscreen view the player is ready. @@ -263,8 +283,8 @@ void MediaSourcePlayer::Start() { playing_ = true; if (HasAudio() && !audio_decoder_job_) { audio_decoder_job_.reset(new AudioDecoderJob( - base::MessageLoopProxy::current(), audio_codec_, sampling_rate_, - num_channels_, &audio_extra_data_[0], audio_extra_data_.size())); + audio_codec_, sampling_rate_, num_channels_, + &audio_extra_data_[0], audio_extra_data_.size())); } if (HasVideo() && !video_decoder_job_) { diff --git a/media/base/android/media_source_player.h b/media/base/android/media_source_player.h index 26e9e10..0163eaa 100644 --- a/media/base/android/media_source_player.h +++ b/media/base/android/media_source_player.h @@ -60,8 +60,7 @@ class MediaDecoderJob { void Release(); protected: - MediaDecoderJob( - bool is_audio, const scoped_refptr<base::MessageLoopProxy>& message_loop); + MediaDecoderJob(base::Thread* thread, bool is_audio); // Release the output buffer and render it. void ReleaseOutputBuffer( @@ -89,7 +88,7 @@ class MediaDecoderJob { scoped_refptr<base::MessageLoopProxy> message_loop_; // Thread the decode task runs on. - scoped_ptr<base::Thread> thread_; + base::Thread* thread_; // Whether the decoder needs to be flushed. bool needs_flush_; @@ -209,7 +208,7 @@ class MEDIA_EXPORT MediaSourcePlayer : public MediaPlayerAndroid { base::Time start_wallclock_time_; base::TimeDelta start_presentation_timestamp_; - // Decoder jobs + // Decoder jobs. ScopedMediaDecoderJob audio_decoder_job_; ScopedMediaDecoderJob video_decoder_job_; |