summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/renderer/media/audio_renderer_impl.cc20
-rw-r--r--chrome/renderer/media/audio_renderer_impl.h8
-rw-r--r--chrome/renderer/media/data_source_impl.cc74
-rw-r--r--chrome/renderer/media/data_source_impl.h26
-rw-r--r--chrome/renderer/webmediaplayer_delegate_impl.cc46
-rw-r--r--chrome/renderer/webmediaplayer_delegate_impl.h4
-rw-r--r--media/base/filter_host_impl.cc1
-rw-r--r--media/base/pipeline_impl.cc8
8 files changed, 98 insertions, 89 deletions
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc
index 9677b32..a830b40 100644
--- a/chrome/renderer/media/audio_renderer_impl.cc
+++ b/chrome/renderer/media/audio_renderer_impl.cc
@@ -57,7 +57,8 @@ bool AudioRendererImpl::OnInitialize(const media::MediaFormat& media_format) {
void AudioRendererImpl::OnStop() {
if (!resource_release_event_.IsSignaled()) {
render_loop_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &AudioRendererImpl::ReleaseRendererResources));
+ NewRunnableMethod(this,
+ &AudioRendererImpl::ReleaseResources, false));
resource_release_event_.Wait();
}
}
@@ -90,6 +91,7 @@ void AudioRendererImpl::SetVolume(float volume) {
void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle,
size_t length) {
shared_memory_.reset(new base::SharedMemory(handle, false));
+ shared_memory_->Map(length);
shared_memory_size_ = length;
// TODO(hclam): is there any better place to do this?
OnStartAudioStream();
@@ -97,6 +99,9 @@ void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle,
void AudioRendererImpl::OnRequestPacket() {
packet_requested_ = true;
+ // Post a task to render thread and try to grab a packet for sending back.
+ render_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioRendererImpl::OnNotifyAudioPacketReady));
}
void AudioRendererImpl::OnStateChanged(AudioOutputStream::State state,
@@ -120,8 +125,9 @@ void AudioRendererImpl::OnVolume(double left, double right) {
// pipeline.
}
-void AudioRendererImpl::ReleaseRendererResources() {
- OnCloseAudioStream();
+void AudioRendererImpl::ReleaseResources(bool is_render_thread_dying) {
+ if (!is_render_thread_dying)
+ OnCloseAudioStream();
resource_release_event_.Signal();
}
@@ -151,8 +157,10 @@ void AudioRendererImpl::OnNotifyAudioPacketReady() {
// Fill into the shared memory.
size_t filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()),
shared_memory_size_);
- packet_requested_ = false;
- // Then tell browser process we are done filling into the buffer.
- delegate_->view()->NotifyAudioPacketReady(stream_id_, filled);
+ if (filled > 0) {
+ packet_requested_ = false;
+ // Then tell browser process we are done filling into the buffer.
+ delegate_->view()->NotifyAudioPacketReady(stream_id_, filled);
+ }
}
}
diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h
index d062bb0..8834f4ec 100644
--- a/chrome/renderer/media/audio_renderer_impl.h
+++ b/chrome/renderer/media/audio_renderer_impl.h
@@ -63,7 +63,7 @@
// | in the browser process, called along with a SharedMemoryHandle.
// |-- OnVolume()
// | Called from RenderView about the volume of the audio output stream.
-// \-- ReleaseRendererResource()
+// \-- ReleaseResource()
// Release resources that live inside render thread.
//
// Pipeline thread
@@ -84,7 +84,7 @@
//
// Audio decoder thread (If there's one.)
// \-- OnAssignment()
-// A raw PCM audio packet buffer is recevied here, this method is called
+// A raw PCM audio packet buffer is received here, this method is called
// from pipeline thread if audio decoder thread does not exist.
#ifndef CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
@@ -118,7 +118,9 @@ class AudioRendererImpl : public media::AudioRendererBase {
void OnVolume(double left, double right);
// Release resources that lives in renderer thread, i.e. audio output streams.
- void ReleaseRendererResources();
+ // |render_thread_is_dying| tells us if render thread is being destroyed,
+ // if true it's not safe to access any object that lives inside render thread.
+ void ReleaseResources(bool render_thread_is_dying);
// Methods called on pipeline thread ----------------------------------------
// media::MediaFilter implementation.
diff --git a/chrome/renderer/media/data_source_impl.cc b/chrome/renderer/media/data_source_impl.cc
index 51efb6f..93a4f5c 100644
--- a/chrome/renderer/media/data_source_impl.cc
+++ b/chrome/renderer/media/data_source_impl.cc
@@ -22,6 +22,7 @@ DataSourceImpl::DataSourceImpl(WebMediaPlayerDelegateImpl* delegate)
downloaded_bytes_(0),
total_bytes_(0),
total_bytes_known_(false),
+ download_completed_(false),
resource_loader_bridge_(NULL),
resource_release_event_(true, false),
read_event_(false, false),
@@ -31,7 +32,6 @@ DataSourceImpl::DataSourceImpl(WebMediaPlayerDelegateImpl* delegate)
last_read_size_(0),
position_(0),
io_loop_(delegate->view()->GetMessageLoopForIO()),
- close_event_(false, false),
seek_event_(false, false) {
// Register ourselves with WebMediaPlayerDelgateImpl.
delegate_->SetDataSource(this);
@@ -45,28 +45,20 @@ void DataSourceImpl::Stop() {
return;
stopped_ = true;
- // 1. Cancel the resource request.
+ // Wakes up demuxer waiting on |read_event_| in Read().
+ read_event_.Signal();
+ // Wakes up demuxer waiting on |seek_event_| in SetPosition().
+ seek_event_.Signal();
+ // Wakes up demuxer waiting on |download_event_| in Read() or SetPosition().
+ download_event_.Signal();
+
if (!resource_release_event_.IsSignaled()) {
render_loop_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &DataSourceImpl::ReleaseRendererResources));
+ NewRunnableMethod(this, &DataSourceImpl::ReleaseResources, false));
+ // We wait until the resource is released to make sure we won't receive
+ // any call from render thread when we wake up.
resource_release_event_.Wait();
}
-
- // 2. Signal download_event_.
- download_event_.Signal();
-
- // Post a close file stream task to IO message loop, it will signal the read
- // event.
- // TODO(hclam): make sure it's safe to do this during destruction of
- // RenderThread.
- io_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &DataSourceImpl::OnCloseFileStream));
-
- // Wait for close to finish for FileStream.
- close_event_.Wait();
-
- // Make sure that when we wake up the stream is closed and destroyed.
- DCHECK(stream_.get() == NULL);
}
bool DataSourceImpl::Initialize(const std::string& url) {
@@ -84,7 +76,7 @@ size_t DataSourceImpl::Read(uint8* data, size_t size) {
while (!stopped_) {
{
AutoLock auto_lock(lock_);
- if (position_ + size <= downloaded_bytes_)
+ if (download_completed_ || position_ + size <= downloaded_bytes_)
break;
}
download_event_.Wait();
@@ -94,7 +86,7 @@ size_t DataSourceImpl::Read(uint8* data, size_t size) {
if (!stopped_) {
if (logging::DEBUG_MODE) {
AutoLock auto_lock(lock_);
- DCHECK(position_ + size <= downloaded_bytes_);
+ DCHECK(download_completed_ || position_ + size <= downloaded_bytes_);
}
// Post a task to IO message loop to perform the actual reading.
io_loop_->PostTask(FROM_HERE,
@@ -115,7 +107,7 @@ bool DataSourceImpl::SetPosition(int64 position) {
while (!stopped_) {
{
AutoLock auto_lock(lock_);
- if (position < downloaded_bytes_)
+ if (download_completed_ || position < downloaded_bytes_)
break;
}
download_event_.Wait();
@@ -123,7 +115,7 @@ bool DataSourceImpl::SetPosition(int64 position) {
if (!stopped_) {
if (logging::DEBUG_MODE) {
AutoLock auto_lock_(lock_);
- DCHECK(position < downloaded_bytes_);
+ DCHECK(download_completed_ || position < downloaded_bytes_);
}
// Perform the seek operation on IO message loop.
io_loop_->PostTask(FROM_HERE,
@@ -171,19 +163,6 @@ void DataSourceImpl::OnReadFileStream(uint8* data, size_t size) {
}
}
-void DataSourceImpl::OnCloseFileStream() {
- if (stream_.get()) {
- stream_->Close();
- stream_.reset();
- }
- // Wakes up demuxer waiting on read_event_ in Read().
- read_event_.Signal();
- // Wakes up demuxer waiting on seek_event_ in SetPosition().
- seek_event_.Signal();
- // Wakes up pipeline thread blocked in Stop() by close_event_.
- close_event_.Signal();
-}
-
void DataSourceImpl::OnSeekFileStream(net::Whence whence, int64 position) {
if (!stopped_ && stream_.get()) {
int64 new_position = stream_->Seek(whence, position);
@@ -198,12 +177,14 @@ void DataSourceImpl::OnSeekFileStream(net::Whence whence, int64 position) {
}
void DataSourceImpl::OnDidFileStreamRead(int size) {
- {
+ if (size < 0) {
+ host_->Error(media::PIPELINE_ERROR_READ);
+ } else {
AutoLock auto_lock(lock_);
- last_read_size_ = size;
// TODO(hclam): size may be an error code, handle that.
position_ += size;
}
+ last_read_size_ = size;
read_event_.Signal();
}
@@ -230,9 +211,13 @@ void DataSourceImpl::OnInitialize(std::string uri) {
resource_loader_bridge_->Start(this);
}
-void DataSourceImpl::ReleaseRendererResources() {
+void DataSourceImpl::ReleaseResources(bool render_thread_is_dying) {
DCHECK(MessageLoop::current() == render_loop_);
- if (resource_loader_bridge_) {
+ if (render_thread_is_dying) {
+ // If render thread is dying we can't call cancel on this pointer, we will
+ // just let this object leak.
+ resource_loader_bridge_ = NULL;
+ } else if (resource_loader_bridge_) {
resource_loader_bridge_->Cancel();
resource_loader_bridge_ = NULL;
}
@@ -245,6 +230,8 @@ void DataSourceImpl::OnDownloadProgress(uint64 position, uint64 size) {
downloaded_bytes_ = position;
if (!total_bytes_known_) {
if (size == kuint64max) {
+ // If we receive an invalid value for size, we keep on updating the
+ // total number of bytes.
total_bytes_ = position;
} else {
total_bytes_ = size;
@@ -297,10 +284,13 @@ void DataSourceImpl::OnReceivedData(const char* data, int len) {
void DataSourceImpl::OnCompletedRequest(const URLRequestStatus& status,
const std::string& security_info) {
+ {
+ AutoLock auto_lock(lock_);
+ total_bytes_known_ = true;
+ download_completed_ = true;
+ }
if (status.status() != URLRequestStatus::SUCCESS) {
host_->Error(media::PIPELINE_ERROR_NETWORK);
- } else {
- // TODO(hclam): notify end of stream to pipeline.
}
}
diff --git a/chrome/renderer/media/data_source_impl.h b/chrome/renderer/media/data_source_impl.h
index 6f8d688..d5326cb 100644
--- a/chrome/renderer/media/data_source_impl.h
+++ b/chrome/renderer/media/data_source_impl.h
@@ -41,7 +41,7 @@
// |-- OnReceivedData()
// |-- OnCompletedRequest()
// |-- GetURLForDebugging()
-// \-- ReleaseRendererResources();
+// \-- ReleaseResources()
//
// Pipeline thread
// +-- Initialize()
@@ -64,8 +64,6 @@
// | Callback for construction of net::FileStream in an IO message loop.
// |-- OnReadFileStream()
// | Actual read operation on FileStream performs here.
-// |-- OnCloseFileStream()
-// | Closing of FileSteram happens in this method.
// |-- OnSeekFileStream()
// | Actual seek operation happens here.
// \-- OnDidFileStreamRead()
@@ -116,13 +114,18 @@ class DataSourceImpl : public media::DataSource,
// Release all resources associated with RenderView, particularly
// ResourceLoaderBridge created by ResourceDispatcher. This method should only
- // be executed on render thread, we have this method standalone and public
- // here because WebMediaPlayerDelegateImpl will be calling this method when
- // render thread is being destroyed, and in that case we can't post tasks to
- // render thread from pipeline thread anymore so we have to release resources
- // manually from WebMediaPlayerDelegateImpl and we will not do the same thing
- // in Stop().
- void ReleaseRendererResources();
+ // be executed on render thread.
+ // There are three cases for this method to be called:
+ // 1. Posted as a task from DataSourceImpl::Stop() caused by an error in the
+ // pipeline.
+ // 2. WebMediaPlayerDelegateImpl is being destroyed and all resources
+ // associated with the pipeline should go away. In this case we can call
+ // to objects that live inside render thread to cleanup,
+ // e.g. ResourceDispatcher.
+ // 3. RenderThread is being destroyed, in this case we can't access any
+ // object that lives inside render thread and should let the resources
+ // leak.
+ void ReleaseResources(bool is_render_thread_dying);
// Methods called from pipeline thread --------------------------------------
virtual bool Initialize(const std::string& url);
@@ -154,7 +157,6 @@ class DataSourceImpl : public media::DataSource,
// Handlers for file reading.
void OnCreateFileStream(base::PlatformFile file);
void OnReadFileStream(uint8* data, size_t size);
- void OnCloseFileStream();
void OnSeekFileStream(net::Whence whence, int64 position);
void OnDidFileStreamRead(int size);
@@ -181,6 +183,7 @@ class DataSourceImpl : public media::DataSource,
int64 downloaded_bytes_;
int64 total_bytes_;
bool total_bytes_known_;
+ bool download_completed_;
// Members related to resource loading with RenderView.
webkit_glue::ResourceLoaderBridge* resource_loader_bridge_;
@@ -195,7 +198,6 @@ class DataSourceImpl : public media::DataSource,
MessageLoop* io_loop_;
// Events for other operations on stream_.
- base::WaitableEvent close_event_;
base::WaitableEvent seek_event_;
DISALLOW_COPY_AND_ASSIGN(DataSourceImpl);
diff --git a/chrome/renderer/webmediaplayer_delegate_impl.cc b/chrome/renderer/webmediaplayer_delegate_impl.cc
index 5f16cf3..b7d087d 100644
--- a/chrome/renderer/webmediaplayer_delegate_impl.cc
+++ b/chrome/renderer/webmediaplayer_delegate_impl.cc
@@ -68,7 +68,7 @@ WebMediaPlayerDelegateImpl::WebMediaPlayerDelegateImpl(RenderView* view)
WebMediaPlayerDelegateImpl::~WebMediaPlayerDelegateImpl() {
// Stop the pipeline in the first place so we won't receive any more method
// calls from it.
- pipeline_.Stop();
+ StopPipeline(false);
// Cancel all tasks posted on the main_loop_.
CancelAllTasks();
@@ -131,7 +131,7 @@ void WebMediaPlayerDelegateImpl::Stop() {
DCHECK(main_loop_ && MessageLoop::current() == main_loop_);
// We can fire Stop() multiple times.
- pipeline_.Stop();
+ StopPipeline(false);
}
void WebMediaPlayerDelegateImpl::Seek(float time) {
@@ -283,31 +283,15 @@ void WebMediaPlayerDelegateImpl::Paint(skia::PlatformCanvas *canvas,
}
void WebMediaPlayerDelegateImpl::WillDestroyCurrentMessageLoop() {
- // Instruct the renderers and data source to release all Renderer related
- // resources during destruction of render thread, because they won't have any
- // chance to release these resources on render thread by posting tasks on it.
- if (audio_renderer_) {
- audio_renderer_->ReleaseRendererResources();
- audio_renderer_ = NULL;
- }
-
- if (data_source_) {
- data_source_->ReleaseRendererResources();
- data_source_ = NULL;
- }
-
- // Stop the pipeline when the render thread is being destroyed so we won't be
- // posting any more messages onto it. And we just let this object and
- // associated WebMediaPlayer to leak.
- pipeline_.Stop();
+ StopPipeline(true);
}
void WebMediaPlayerDelegateImpl::DidInitializePipeline(bool successful) {
if (successful) {
// Since we have initialized the pipeline, we should be able to play it.
// And we skip LOADED_METADATA state and starting with LOADED_FIRST_FRAME.
- ready_state_ = webkit_glue::WebMediaPlayer::CAN_PLAY;
- network_state_ = webkit_glue::WebMediaPlayer::LOADED_FIRST_FRAME;
+ ready_state_ = webkit_glue::WebMediaPlayer::CAN_PLAY_THROUGH;
+ network_state_ = webkit_glue::WebMediaPlayer::LOADED;
} else {
// TODO(hclam): should use pipeline_.GetError() to determine the state
// properly and reports error using MediaError.
@@ -374,3 +358,23 @@ void WebMediaPlayerDelegateImpl::PostTask(int index,
void WebMediaPlayerDelegateImpl::PostRepaintTask() {
PostTask(kRepaintTaskIndex, &webkit_glue::WebMediaPlayer::Repaint);
}
+
+void WebMediaPlayerDelegateImpl::StopPipeline(bool render_thread_is_dying) {
+ // Instruct the renderers and data source to release all Renderer related
+ // resources during destruction of render thread, because they won't have any
+ // chance to release these resources on render thread by posting tasks on it.
+ if (audio_renderer_) {
+ audio_renderer_->ReleaseResources(render_thread_is_dying);
+ audio_renderer_ = NULL;
+ }
+
+ if (data_source_) {
+ data_source_->ReleaseResources(render_thread_is_dying);
+ data_source_ = NULL;
+ }
+
+ // Stop the pipeline when the render thread is being destroyed so we won't be
+ // posting any more messages onto it. And we just let this object and
+ // associated WebMediaPlayer to leak.
+ pipeline_.Stop();
+}
diff --git a/chrome/renderer/webmediaplayer_delegate_impl.h b/chrome/renderer/webmediaplayer_delegate_impl.h
index b557393..1f0c726 100644
--- a/chrome/renderer/webmediaplayer_delegate_impl.h
+++ b/chrome/renderer/webmediaplayer_delegate_impl.h
@@ -160,6 +160,10 @@ class WebMediaPlayerDelegateImpl : public webkit_glue::WebMediaPlayerDelegate,
// Cancel all tasks currently lives in |main_loop_|.
void CancelAllTasks();
+ // Calls to renderers and data source to release all resources that live in
+ // render thread and stop the pipeline.
+ void StopPipeline(bool render_thread_is_dying);
+
// Indexes for tasks.
enum {
kRepaintTaskIndex = 0,
diff --git a/media/base/filter_host_impl.cc b/media/base/filter_host_impl.cc
index 74eaa16..cba2eb1 100644
--- a/media/base/filter_host_impl.cc
+++ b/media/base/filter_host_impl.cc
@@ -61,7 +61,6 @@ void FilterHostImpl::InitializationComplete() {
}
void FilterHostImpl::PostTask(Task* task) {
- DCHECK(!stopped_);
if (stopped_) {
delete task;
} else {
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index a36da6c..5bc3faa 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -401,10 +401,10 @@ void PipelineThread::StopTask() {
if (PipelineOk()) {
pipeline_->error_ = PIPELINE_STOPPING;
}
- FilterHostVector::reverse_iterator riter = filter_hosts_.rbegin();
- while (riter != filter_hosts_.rend()) {
- (*riter)->Stop();
- ++riter;
+ FilterHostVector::iterator iter = filter_hosts_.begin();
+ while (iter != filter_hosts_.end()) {
+ (*iter)->Stop();
+ ++iter;
}
if (host_initializing_) {
host_initializing_ = NULL;