diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-16 20:40:37 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-16 20:40:37 +0000 |
commit | ccc70d8efc4981925423ffa1390c0b4783ea1add (patch) | |
tree | 8cfe460075607074359b7f5556705c0ff173e7be /chrome/renderer/media | |
parent | 9dc1379851640ce5bd544862ce86f44258159ca9 (diff) | |
download | chromium_src-ccc70d8efc4981925423ffa1390c0b4783ea1add.zip chromium_src-ccc70d8efc4981925423ffa1390c0b4783ea1add.tar.gz chromium_src-ccc70d8efc4981925423ffa1390c0b4783ea1add.tar.bz2 |
Move core renderer subdirectories to content.
TBR=avi
Review URL: http://codereview.chromium.org/6673090
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78422 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/media')
-rw-r--r-- | chrome/renderer/media/audio_renderer_impl.cc | 362 | ||||
-rw-r--r-- | chrome/renderer/media/audio_renderer_impl.h | 157 | ||||
-rw-r--r-- | chrome/renderer/media/audio_renderer_impl_unittest.cc | 146 | ||||
-rw-r--r-- | chrome/renderer/media/gles2_video_decode_context.cc | 122 | ||||
-rw-r--r-- | chrome/renderer/media/gles2_video_decode_context.h | 113 | ||||
-rw-r--r-- | chrome/renderer/media/ipc_video_decoder.cc | 207 | ||||
-rw-r--r-- | chrome/renderer/media/ipc_video_decoder.h | 92 |
7 files changed, 0 insertions, 1199 deletions
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc deleted file mode 100644 index de41c2a..0000000 --- a/chrome/renderer/media/audio_renderer_impl.cc +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/renderer/media/audio_renderer_impl.h" - -#include <math.h> - -#include "chrome/common/render_messages.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/renderer/audio_message_filter.h" -#include "chrome/renderer/render_view.h" -#include "chrome/renderer/render_thread.h" -#include "media/base/filter_host.h" - -namespace { - -// We will try to fill 200 ms worth of audio samples in each packet. A round -// trip latency for IPC messages are typically 10 ms, this should give us -// plenty of time to avoid clicks. -const int kMillisecondsPerPacket = 200; - -// We have at most 3 packets in browser, i.e. 600 ms. This is a reasonable -// amount to avoid clicks. -const int kPacketsInBuffer = 3; - -} // namespace - -AudioRendererImpl::AudioRendererImpl(AudioMessageFilter* filter) - : AudioRendererBase(), - bytes_per_second_(0), - filter_(filter), - stream_id_(0), - shared_memory_(NULL), - shared_memory_size_(0), - io_loop_(filter->message_loop()), - stopped_(false), - pending_request_(false), - prerolling_(false), - preroll_bytes_(0) { - DCHECK(io_loop_); -} - -AudioRendererImpl::~AudioRendererImpl() { -} - -base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { - if (bytes_per_second_) { - return base::TimeDelta::FromMicroseconds( - base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); - } - return base::TimeDelta(); -} - -bool AudioRendererImpl::OnInitialize(const media::MediaFormat& media_format) { - // Parse integer values in MediaFormat. - if (!ParseMediaFormat(media_format, - ¶ms_.channels, - ¶ms_.sample_rate, - ¶ms_.bits_per_sample)) { - return false; - } - params_.format = AudioParameters::AUDIO_PCM_LINEAR; - - // Calculate the number of bytes per second using information of the stream. - bytes_per_second_ = params_.sample_rate * params_.channels * - params_.bits_per_sample / 8; - - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::CreateStreamTask, params_)); - return true; -} - -void AudioRendererImpl::OnStop() { - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - stopped_ = true; - - // We should never touch |io_loop_| after being stopped, so post our final - // task to clean up. - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::DestroyTask)); -} - -void AudioRendererImpl::ConsumeAudioSamples( - scoped_refptr<media::Buffer> buffer_in) { - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - // TODO(hclam): handle end of stream here. - - // Use the base class to queue the buffer. - AudioRendererBase::ConsumeAudioSamples(buffer_in); - - // Post a task to render thread to notify a packet reception. - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); -} - -void AudioRendererImpl::SetPlaybackRate(float rate) { - DCHECK(rate >= 0.0f); - - base::AutoLock auto_lock(lock_); - // Handle the case where we stopped due to |io_loop_| dying. - if (stopped_) { - AudioRendererBase::SetPlaybackRate(rate); - return; - } - - // We have two cases here: - // Play: GetPlaybackRate() == 0.0 && rate != 0.0 - // Pause: GetPlaybackRate() != 0.0 && rate == 0.0 - if (GetPlaybackRate() == 0.0f && rate != 0.0f) { - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::PlayTask)); - } else if (GetPlaybackRate() != 0.0f && rate == 0.0f) { - // Pause is easy, we can always pause. - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); - } - AudioRendererBase::SetPlaybackRate(rate); - - // If we are playing, give a kick to try fulfilling the packet request as - // the previous packet request may be stalled by a pause. - if (rate > 0.0f) { - io_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); - } -} - -void AudioRendererImpl::Pause(media::FilterCallback* callback) { - AudioRendererBase::Pause(callback); - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); -} - -void AudioRendererImpl::Seek(base::TimeDelta time, - media::FilterCallback* callback) { - AudioRendererBase::Seek(time, callback); - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::SeekTask)); -} - - -void AudioRendererImpl::Play(media::FilterCallback* callback) { - AudioRendererBase::Play(callback); - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - if (GetPlaybackRate() != 0.0f) { - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::PlayTask)); - } else { - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); - } -} - -void AudioRendererImpl::SetVolume(float volume) { - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - io_loop_->PostTask(FROM_HERE, - NewRunnableMethod( - this, &AudioRendererImpl::SetVolumeTask, volume)); -} - -void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle, - uint32 length) { - DCHECK(MessageLoop::current() == io_loop_); - - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - shared_memory_.reset(new base::SharedMemory(handle, false)); - shared_memory_->Map(length); - shared_memory_size_ = length; -} - -void AudioRendererImpl::OnLowLatencyCreated(base::SharedMemoryHandle, - base::SyncSocket::Handle, uint32) { - // AudioRenderer should not have a low-latency audio channel. - NOTREACHED(); -} - -void AudioRendererImpl::OnRequestPacket(AudioBuffersState buffers_state) { - DCHECK(MessageLoop::current() == io_loop_); - - { - base::AutoLock auto_lock(lock_); - DCHECK(!pending_request_); - pending_request_ = true; - request_buffers_state_ = buffers_state; - } - - // Try to fill in the fulfill the packet request. - NotifyPacketReadyTask(); -} - -void AudioRendererImpl::OnStateChanged( - const ViewMsg_AudioStreamState_Params& state) { - DCHECK(MessageLoop::current() == io_loop_); - - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - switch (state.state) { - case ViewMsg_AudioStreamState_Params::kError: - // We receive this error if we counter an hardware error on the browser - // side. We can proceed with ignoring the audio stream. - // TODO(hclam): We need more handling of these kind of error. For example - // re-try creating the audio output stream on the browser side or fail - // nicely and report to demuxer that the whole audio stream is discarded. - host()->DisableAudioRenderer(); - break; - // TODO(hclam): handle these events. - case ViewMsg_AudioStreamState_Params::kPlaying: - case ViewMsg_AudioStreamState_Params::kPaused: - break; - default: - NOTREACHED(); - break; - } -} - -void AudioRendererImpl::OnVolume(double volume) { - // TODO(hclam): decide whether we need to report the current volume to - // pipeline. -} - -void AudioRendererImpl::CreateStreamTask(const AudioParameters& audio_params) { - DCHECK(MessageLoop::current() == io_loop_); - - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - // Make sure we don't call create more than once. - DCHECK_EQ(0, stream_id_); - stream_id_ = filter_->AddDelegate(this); - io_loop_->AddDestructionObserver(this); - - ViewHostMsg_Audio_CreateStream_Params params; - params.params = audio_params; - - // Let the browser choose packet size. - params.params.samples_per_packet = 0; - - filter_->Send(new ViewHostMsg_CreateAudioStream(0, stream_id_, params, - false)); -} - -void AudioRendererImpl::PlayTask() { - DCHECK(MessageLoop::current() == io_loop_); - - filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_)); -} - -void AudioRendererImpl::PauseTask() { - DCHECK(MessageLoop::current() == io_loop_); - - filter_->Send(new ViewHostMsg_PauseAudioStream(0, stream_id_)); -} - -void AudioRendererImpl::SeekTask() { - DCHECK(MessageLoop::current() == io_loop_); - - // We have to pause the audio stream before we can flush. - filter_->Send(new ViewHostMsg_PauseAudioStream(0, stream_id_)); - filter_->Send(new ViewHostMsg_FlushAudioStream(0, stream_id_)); -} - -void AudioRendererImpl::DestroyTask() { - DCHECK(MessageLoop::current() == io_loop_); - - // Make sure we don't call destroy more than once. - DCHECK_NE(0, stream_id_); - filter_->RemoveDelegate(stream_id_); - filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); - io_loop_->RemoveDestructionObserver(this); - stream_id_ = 0; -} - -void AudioRendererImpl::SetVolumeTask(double volume) { - DCHECK(MessageLoop::current() == io_loop_); - - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); -} - -void AudioRendererImpl::NotifyPacketReadyTask() { - DCHECK(MessageLoop::current() == io_loop_); - - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - if (pending_request_ && GetPlaybackRate() > 0.0f) { - DCHECK(shared_memory_.get()); - - // Adjust the playback delay. - base::Time current_time = base::Time::Now(); - - base::TimeDelta request_delay = - ConvertToDuration(request_buffers_state_.total_bytes()); - - // Add message delivery delay. - if (current_time > request_buffers_state_.timestamp) { - base::TimeDelta receive_latency = - current_time - request_buffers_state_.timestamp; - - // If the receive latency is too much it may offset all the delay. - if (receive_latency >= request_delay) { - request_delay = base::TimeDelta(); - } else { - request_delay -= receive_latency; - } - } - - // Finally we need to adjust the delay according to playback rate. - if (GetPlaybackRate() != 1.0f) { - request_delay = base::TimeDelta::FromMicroseconds( - static_cast<int64>(ceil(request_delay.InMicroseconds() * - GetPlaybackRate()))); - } - - uint32 filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()), - shared_memory_size_, request_delay, - request_buffers_state_.pending_bytes == 0); - pending_request_ = false; - // Then tell browser process we are done filling into the buffer. - filter_->Send( - new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); - } -} - -void AudioRendererImpl::WillDestroyCurrentMessageLoop() { - DCHECK(MessageLoop::current() == io_loop_); - - // We treat the IO loop going away the same as stopping. - base::AutoLock auto_lock(lock_); - if (stopped_) - return; - - stopped_ = true; - DestroyTask(); -} diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h deleted file mode 100644 index 9e8b93d..0000000 --- a/chrome/renderer/media/audio_renderer_impl.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Audio rendering unit utilizing audio output stream provided by browser -// process through IPC. -// -// Relationship of classes. -// -// AudioRendererHost AudioRendererImpl -// ^ ^ -// | | -// v IPC v -// RenderMessageFilter <---------> AudioMessageFilter -// -// Implementation of interface with audio device is in AudioRendererHost and -// it provides services and entry points in RenderMessageFilter, allowing -// usage of IPC calls to interact with audio device. AudioMessageFilter acts -// as a portal for IPC calls and does no more than delegation. -// -// Transportation of audio buffer is done by using shared memory, after -// OnCreateStream is executed, OnCreated would be called along with a -// SharedMemoryHandle upon successful creation of audio output stream in the -// browser process. The same piece of shared memory would be used during the -// lifetime of this unit. -// -// This class lives inside three threads during it's lifetime, namely: -// 1. IO thread. -// The thread within which this class receives all the IPC messages and -// IPC communications can only happen in this thread. -// 2. Pipeline thread -// Initialization of filter and proper stopping of filters happens here. -// Properties of this filter is also set in this thread. -// 3. Audio decoder thread (If there's one.) -// Responsible for decoding audio data and gives raw PCM data to this object. - -#ifndef CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ -#define CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ -#pragma once - -#include "base/gtest_prod_util.h" -#include "base/message_loop.h" -#include "base/scoped_ptr.h" -#include "base/shared_memory.h" -#include "base/synchronization/lock.h" -#include "chrome/renderer/audio_message_filter.h" -#include "media/audio/audio_io.h" -#include "media/audio/audio_manager.h" -#include "media/base/filters.h" -#include "media/filters/audio_renderer_base.h" - -class AudioMessageFilter; - -class AudioRendererImpl : public media::AudioRendererBase, - public AudioMessageFilter::Delegate, - public MessageLoop::DestructionObserver { - public: - // Methods called on Render thread ------------------------------------------ - explicit AudioRendererImpl(AudioMessageFilter* filter); - virtual ~AudioRendererImpl(); - - // Methods called on IO thread ---------------------------------------------- - // AudioMessageFilter::Delegate methods, called by AudioMessageFilter. - virtual void OnRequestPacket(AudioBuffersState buffers_state); - virtual void OnStateChanged(const ViewMsg_AudioStreamState_Params& state); - virtual void OnCreated(base::SharedMemoryHandle handle, uint32 length); - virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle, - base::SyncSocket::Handle socket_handle, - uint32 length); - virtual void OnVolume(double volume); - - // Methods called on pipeline thread ---------------------------------------- - // media::Filter implementation. - virtual void SetPlaybackRate(float rate); - virtual void Pause(media::FilterCallback* callback); - virtual void Seek(base::TimeDelta time, media::FilterCallback* callback); - virtual void Play(media::FilterCallback* callback); - - // media::AudioRenderer implementation. - virtual void SetVolume(float volume); - - protected: - // Methods called on audio renderer thread ---------------------------------- - // These methods are called from AudioRendererBase. - virtual bool OnInitialize(const media::MediaFormat& media_format); - virtual void OnStop(); - - // Called when the decoder completes a Read(). - virtual void ConsumeAudioSamples(scoped_refptr<media::Buffer> buffer_in); - - private: - // For access to constructor and IO thread methods. - friend class AudioRendererImplTest; - FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, Stop); - FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, - DestroyedMessageLoop_ConsumeAudioSamples); - // Helper methods. - // Convert number of bytes to duration of time using information about the - // number of channels, sample rate and sample bits. - base::TimeDelta ConvertToDuration(int bytes); - - // Methods call on IO thread ------------------------------------------------ - // The following methods are tasks posted on the IO thread that needs to - // be executed on that thread. They interact with AudioMessageFilter and - // sends IPC messages on that thread. - void CreateStreamTask(const AudioParameters& params); - void PlayTask(); - void PauseTask(); - void SeekTask(); - void SetVolumeTask(double volume); - void NotifyPacketReadyTask(); - void DestroyTask(); - - // Called on IO thread when message loop is dying. - virtual void WillDestroyCurrentMessageLoop(); - - // Information about the audio stream. - AudioParameters params_; - uint32 bytes_per_second_; - - scoped_refptr<AudioMessageFilter> filter_; - - // ID of the stream created in the browser process. - int32 stream_id_; - - // Memory shared by the browser process for audio buffer. - scoped_ptr<base::SharedMemory> shared_memory_; - uint32 shared_memory_size_; - - // Message loop for the IO thread. - MessageLoop* io_loop_; - - // Protects: - // - |stopped_| - // - |pending_request_| - // - |request_buffers_state_| - base::Lock lock_; - - // A flag that indicates this filter is called to stop. - bool stopped_; - - // A flag that indicates an outstanding packet request. - bool pending_request_; - - // State of the audio buffers at time of the last request. - AudioBuffersState request_buffers_state_; - - // State variables for prerolling. - bool prerolling_; - - // Remaining bytes for prerolling to complete. - uint32 preroll_bytes_; - - DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); -}; - -#endif // CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ diff --git a/chrome/renderer/media/audio_renderer_impl_unittest.cc b/chrome/renderer/media/audio_renderer_impl_unittest.cc deleted file mode 100644 index 754c60d..0000000 --- a/chrome/renderer/media/audio_renderer_impl_unittest.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/process_util.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/renderer/media/audio_renderer_impl.h" -#include "media/base/data_buffer.h" -#include "media/base/media_format.h" -#include "media/base/mock_callback.h" -#include "media/base/mock_filter_host.h" -#include "media/base/mock_filters.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::ReturnRef; - -class AudioRendererImplTest : public ::testing::Test { - public: - static const int kRouteId = 0; - static const int kSize = 1024; - - AudioRendererImplTest() { - message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); - - // TODO(scherkus): use gmock with AudioMessageFilter to verify - // AudioRendererImpl calls or doesn't call Send(). - filter_ = new AudioMessageFilter(kRouteId); - filter_->message_loop_ = message_loop_.get(); - - // Create temporary shared memory. - CHECK(shared_mem_.CreateAnonymous(kSize)); - - // Setup expectations for initialization. - decoder_ = new media::MockAudioDecoder(); - - // Associate media format with decoder - decoder_media_format_.SetAsInteger(media::MediaFormat::kChannels, 2); - decoder_media_format_.SetAsInteger(media::MediaFormat::kSampleRate, 48000); - decoder_media_format_.SetAsInteger(media::MediaFormat::kSampleBits, 16); - EXPECT_CALL(*decoder_, media_format()) - .WillRepeatedly(ReturnRef(decoder_media_format_)); - - // Create and initialize audio renderer. - renderer_ = new AudioRendererImpl(filter_); - renderer_->set_host(&host_); - renderer_->Initialize(decoder_, media::NewExpectedCallback()); - - // Run pending tasks and simulate responding with a created audio stream. - message_loop_->RunAllPending(); - - // Duplicate the shared memory handle so both the test and the callee can - // close their copy. - base::SharedMemoryHandle duplicated_handle; - EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(), - &duplicated_handle)); - - renderer_->OnCreated(duplicated_handle, kSize); - } - - virtual ~AudioRendererImplTest() { - } - - protected: - // Fixtures. - scoped_ptr<MessageLoop> message_loop_; - scoped_refptr<AudioMessageFilter> filter_; - base::SharedMemory shared_mem_; - media::MockFilterHost host_; - scoped_refptr<media::MockAudioDecoder> decoder_; - scoped_refptr<AudioRendererImpl> renderer_; - media::MediaFormat decoder_media_format_; - - private: - DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); -}; - -TEST_F(AudioRendererImplTest, SetPlaybackRate) { - // Execute SetPlaybackRate() codepath to create an IPC message. - - // Toggle play/pause to generate some IPC messages. - renderer_->SetPlaybackRate(0.0f); - renderer_->SetPlaybackRate(1.0f); - renderer_->SetPlaybackRate(0.0f); - - renderer_->Stop(media::NewExpectedCallback()); - message_loop_->RunAllPending(); -} - -TEST_F(AudioRendererImplTest, SetVolume) { - // Execute SetVolume() codepath to create an IPC message. - renderer_->SetVolume(0.5f); - renderer_->Stop(media::NewExpectedCallback()); - message_loop_->RunAllPending(); -} - -TEST_F(AudioRendererImplTest, Stop) { - // Declare some state messages. - const ViewMsg_AudioStreamState_Params kError( - ViewMsg_AudioStreamState_Params::kError); - const ViewMsg_AudioStreamState_Params kPlaying( - ViewMsg_AudioStreamState_Params::kPlaying); - const ViewMsg_AudioStreamState_Params kPaused( - ViewMsg_AudioStreamState_Params::kPaused); - - // Execute Stop() codepath to create an IPC message. - renderer_->Stop(media::NewExpectedCallback()); - message_loop_->RunAllPending(); - - // Run AudioMessageFilter::Delegate methods, which can be executed after being - // stopped. AudioRendererImpl shouldn't create any messages. - renderer_->OnRequestPacket(AudioBuffersState(kSize, 0)); - renderer_->OnStateChanged(kError); - renderer_->OnStateChanged(kPlaying); - renderer_->OnStateChanged(kPaused); - renderer_->OnCreated(shared_mem_.handle(), kSize); - renderer_->OnVolume(0.5); - - // It's possible that the upstream decoder replies right after being stopped. - scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); - renderer_->ConsumeAudioSamples(buffer); -} - -TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) { - // Kill the message loop and verify SetPlaybackRate() still works. - message_loop_.reset(); - renderer_->SetPlaybackRate(0.0f); - renderer_->SetPlaybackRate(1.0f); - renderer_->SetPlaybackRate(0.0f); - renderer_->Stop(media::NewExpectedCallback()); -} - -TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) { - // Kill the message loop and verify SetVolume() still works. - message_loop_.reset(); - renderer_->SetVolume(0.5f); - renderer_->Stop(media::NewExpectedCallback()); -} - -TEST_F(AudioRendererImplTest, DestroyedMessageLoop_ConsumeAudioSamples) { - // Kill the message loop and verify OnReadComplete() still works. - message_loop_.reset(); - scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); - renderer_->ConsumeAudioSamples(buffer); - renderer_->Stop(media::NewExpectedCallback()); -} diff --git a/chrome/renderer/media/gles2_video_decode_context.cc b/chrome/renderer/media/gles2_video_decode_context.cc deleted file mode 100644 index 9712313..0000000 --- a/chrome/renderer/media/gles2_video_decode_context.cc +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <GLES2/gl2.h> - -#include "base/message_loop.h" -#include "chrome/renderer/ggl/ggl.h" -#include "chrome/renderer/media/gles2_video_decode_context.h" - -Gles2VideoDecodeContext::Gles2VideoDecodeContext( - MessageLoop* message_loop, bool memory_mapped, ggl::Context* context) - : message_loop_(message_loop), - memory_mapped_(memory_mapped), - context_(context) { -} - -Gles2VideoDecodeContext::~Gles2VideoDecodeContext() { -} - -void* Gles2VideoDecodeContext::GetDevice() { - // This decode context is used inside the renderer and so hardware decoder - // device handler should not be used. - return NULL; -} - -void Gles2VideoDecodeContext::AllocateVideoFrames( - int num_frames, size_t width, size_t height, - media::VideoFrame::Format format, - std::vector<scoped_refptr<media::VideoFrame> >* frames_out, Task* task) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &Gles2VideoDecodeContext::AllocateVideoFrames, - num_frames, width, height, format, frames_out, - task)); - return; - } - - // In this method we need to make the ggl context current and then generate - // textures for each video frame. We also need to allocate memory for each - // texture generated. - bool ret = ggl::MakeCurrent(context_); - CHECK(ret) << "Failed to switch context"; - - frames_.resize(num_frames); - for (int i = 0; i < num_frames; ++i) { - int planes = media::VideoFrame::GetNumberOfPlanes(format); - media::VideoFrame::GlTexture textures[media::VideoFrame::kMaxPlanes]; - - // Set the color format of the textures. - DCHECK(format == media::VideoFrame::RGBA || - format == media::VideoFrame::YV12); - int gl_format = format == media::VideoFrame::RGBA ? GL_RGBA : GL_LUMINANCE; - - glGenTextures(planes, textures); - for (int j = 0; j < planes; ++j) { - glBindTexture(GL_TEXTURE_2D, textures[j]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, gl_format, width, height, 0, gl_format, - GL_UNSIGNED_BYTE, NULL); - } - glFlush(); - - scoped_refptr<media::VideoFrame> frame; - media::VideoFrame::CreateFrameGlTexture(format, width, height, textures, - &frame); - frames_[i] = frame; - } - *frames_out = frames_; - - task->Run(); - delete task; -} - -void Gles2VideoDecodeContext::ReleaseAllVideoFrames() { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, - &Gles2VideoDecodeContext::ReleaseAllVideoFrames)); - return; - } - - // Make the context current and then release the video frames. - bool ret = ggl::MakeCurrent(context_); - CHECK(ret) << "Failed to switch context"; - - for (size_t i = 0; i < frames_.size(); ++i) { - for (size_t j = 0; j < frames_[i]->planes(); ++j) { - media::VideoFrame::GlTexture texture = frames_[i]->gl_texture(j); - glDeleteTextures(1, &texture); - } - } - frames_.clear(); -} - -void Gles2VideoDecodeContext::ConvertToVideoFrame( - void* buffer, scoped_refptr<media::VideoFrame> frame, Task* task) { - DCHECK(memory_mapped_); - // TODO(hclam): Implement. -} - -void Gles2VideoDecodeContext::Destroy(Task* task) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &Gles2VideoDecodeContext::Destroy, task)); - return; - } - - ReleaseAllVideoFrames(); - DCHECK_EQ(0u, frames_.size()); - - task->Run(); - delete task; -} - -DISABLE_RUNNABLE_METHOD_REFCOUNT(Gles2VideoDecodeContext); diff --git a/chrome/renderer/media/gles2_video_decode_context.h b/chrome/renderer/media/gles2_video_decode_context.h deleted file mode 100644 index 3fe9889..0000000 --- a/chrome/renderer/media/gles2_video_decode_context.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_RENDERER_MEDIA_GLES2_VIDEO_DECODE_CONTEXT_H_ -#define CHROME_RENDERER_MEDIA_GLES2_VIDEO_DECODE_CONTEXT_H_ - -#include <vector> - -#include "media/video/video_decode_context.h" - -class MessageLoop; - -namespace ggl { -class Context; -} // namespace ggl - -// FUNCTIONS -// -// This is a class that provides a video decode context using a ggl::Context -// backend. -// -// It provides resources for a VideoDecodeEngine to store decoded video frames. -// -// This class is aware of the command buffer implementation of GLES2 inside the -// Chrome renderer and keeps a reference of ggl::Context. It might use GLES2 -// commands specific to Chrome's renderer process to provide needed resources. -// -// There are two different kinds of video frame storage provided by this class: -// 1. Memory mapped textures (aka software decoding mode). -// Each texture is memory mapped and appears to the VideoDecodeEngine as -// system memory. -// -// The usage of the textures is that the VideoDecodeEngine is performing -// software video decoding and use them as if they are allocated in plain -// system memory (in fact they are allocated in system memory and shared -// bwith the GPU process). An additional step of uploading the content to -// video memory is needed. Since VideoDecodeEngine is unaware of the video -// memory, this upload operation is performed by calling -// ConvertToVideoFrame(). -// -// After the content is uploaded to video memory, WebKit will see the video -// frame as textures and will perform the necessary operations for -// rendering. -// -// 2. Opaque textures (aka hardware decoding mode). -// In this mode of operation each video frame is backed by some opaque -// textures. This is used only when hardware video decoding is used. The -// textures needs to be generated and allocated inside the renderer process -// first. This will establish a translation between texture ID in the -// renderer process and the GPU process. -// -// The texture ID generated is used by IpcVideoDecodeEngine only to be sent -// the GPU process. Inside the GPU process the texture ID is translated to -// a real texture ID inside the actual context. The real texture ID is then -// assigned to the hardware video decoder for storing the video frame. -// -// WebKit will see the video frame as a normal textures and perform -// necessary render operations. -// -// In both operation modes, the objective is to have WebKit see the video frames -// as regular textures. -// -// THREAD SEMANTICS -// -// All methods of this class can be called on any thread. GLES2 context and all -// OpenGL method calls are accessed on the Render Thread. As as result all Tasks -// given to this object are executed on the Render Thread. -// -// Since this class is not refcounted, it is important to destroy objects of -// this class only when the Task given to Destroy() is called. -// -class Gles2VideoDecodeContext : public media::VideoDecodeContext { - public: - // |message_loop| is the message of the Render Thread. - // |memory_mapped| determines if textures allocated are memory mapped. - // |context| is the graphics context for generating textures. - Gles2VideoDecodeContext(MessageLoop* message_loop, - bool memory_mapped, ggl::Context* context); - virtual ~Gles2VideoDecodeContext(); - - // media::VideoDecodeContext implementation. - virtual void* GetDevice(); - virtual void AllocateVideoFrames( - int frames_num, size_t width, size_t height, - media::VideoFrame::Format format, - std::vector<scoped_refptr<media::VideoFrame> >* frames_out, Task* task); - virtual void ReleaseAllVideoFrames(); - virtual void ConvertToVideoFrame(void* buffer, - scoped_refptr<media::VideoFrame> frame, - Task* task); - virtual void Destroy(Task* task); - - // Accessor of the current mode of this decode context. - bool IsMemoryMapped() const { return memory_mapped_; } - - private: - // Message loop for Render Thread. - MessageLoop* message_loop_; - - // Type of storage provided by this class. - bool memory_mapped_; - - // Pointer to the GLES2 context. - ggl::Context* context_; - - // VideoFrames allocated. - std::vector<scoped_refptr<media::VideoFrame> > frames_; - - DISALLOW_COPY_AND_ASSIGN(Gles2VideoDecodeContext); -}; - -#endif // CHROME_RENDERER_MEDIA_GLES2_VIDEO_DECODE_CONTEXT_H_ diff --git a/chrome/renderer/media/ipc_video_decoder.cc b/chrome/renderer/media/ipc_video_decoder.cc deleted file mode 100644 index 361642b..0000000 --- a/chrome/renderer/media/ipc_video_decoder.cc +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/renderer/media/ipc_video_decoder.h" - -#include "base/task.h" -#include "chrome/renderer/ggl/ggl.h" -#include "content/common/child_process.h" -#include "media/base/callback.h" -#include "media/base/filters.h" -#include "media/base/filter_host.h" -#include "media/base/limits.h" -#include "media/base/media_format.h" -#include "media/base/video_frame.h" -#include "media/ffmpeg/ffmpeg_common.h" -#include "media/filters/ffmpeg_interfaces.h" -#include "media/video/video_decode_engine.h" - -IpcVideoDecoder::IpcVideoDecoder(MessageLoop* message_loop, - ggl::Context* ggl_context) - : decode_context_message_loop_(message_loop), - ggl_context_(ggl_context) { -} - -IpcVideoDecoder::~IpcVideoDecoder() { -} - -void IpcVideoDecoder::Initialize(media::DemuxerStream* demuxer_stream, - media::FilterCallback* callback, - media::StatisticsCallback* statsCallback) { - // It doesn't matter which thread we perform initialization because - // all this method does is create objects and delegate the initialize - // messsage. - - DCHECK(!demuxer_stream_); - demuxer_stream_ = demuxer_stream; - initialize_callback_.reset(callback); - statistics_callback_.reset(statsCallback); - - // We require bit stream converter for hardware decoder. - demuxer_stream->EnableBitstreamConverter(); - - // Get the AVStream by querying for the provider interface. - media::AVStreamProvider* av_stream_provider; - if (!demuxer_stream->QueryInterface(&av_stream_provider)) { - media::VideoCodecInfo info = {0}; - OnInitializeComplete(info); - return; - } - - AVStream* av_stream = av_stream_provider->GetAVStream(); - - int width = av_stream->codec->coded_width; - int height = av_stream->codec->coded_height; - if (width > media::Limits::kMaxDimension || - height > media::Limits::kMaxDimension || - (width * height) > media::Limits::kMaxCanvas) { - media::VideoCodecInfo info = {0}; - OnInitializeComplete(info); - return; - } - - // Create a video decode context that assocates with the graphics - // context. - decode_context_.reset( - ggl::CreateVideoDecodeContext( - ggl_context_, decode_context_message_loop_, true)); - - // Create a hardware video decoder handle. - decode_engine_.reset(ggl::CreateVideoDecodeEngine(ggl_context_)); - - media::VideoCodecConfig config( - media::CodecIDToVideoCodec(av_stream->codec->codec_id), - width, height, - av_stream->r_frame_rate.num, - av_stream->r_frame_rate.den, - av_stream->codec->extradata, - av_stream->codec->extradata_size); - - // VideoDecodeEngine will perform initialization on the message loop - // given to it so it doesn't matter on which thread we are calling this. - decode_engine_->Initialize(ChildProcess::current()->io_message_loop(), this, - decode_context_.get(), config); -} - -const media::MediaFormat& IpcVideoDecoder::media_format() { - return media_format_; -} - -void IpcVideoDecoder::Stop(media::FilterCallback* callback) { - stop_callback_.reset(callback); - decode_engine_->Uninitialize(); -} - -void IpcVideoDecoder::Pause(media::FilterCallback* callback) { - // TODO(hclam): It looks like that pause is not necessary so implement this - // later. - callback->Run(); - delete callback; -} - -void IpcVideoDecoder::Flush(media::FilterCallback* callback) { - flush_callback_.reset(callback); - decode_engine_->Flush(); -} - -void IpcVideoDecoder::Seek(base::TimeDelta time, - media::FilterCallback* callback) { - seek_callback_.reset(callback); - decode_engine_->Seek(); -} - -void IpcVideoDecoder::OnInitializeComplete(const media::VideoCodecInfo& info) { - DCHECK_EQ(ChildProcess::current()->io_message_loop(), MessageLoop::current()); - - if (info.success) { - media_format_.SetAsInteger(media::MediaFormat::kSurfaceType, - media::VideoFrame::TYPE_GL_TEXTURE); - media_format_.SetAsInteger(media::MediaFormat::kSurfaceFormat, - info.stream_info.surface_format); - media_format_.SetAsInteger(media::MediaFormat::kWidth, - info.stream_info.surface_width); - media_format_.SetAsInteger(media::MediaFormat::kHeight, - info.stream_info.surface_height); - media_format_.SetAsInteger( - media::MediaFormat::kSurfaceType, - static_cast<int>(media::VideoFrame::TYPE_GL_TEXTURE)); - } else { - LOG(ERROR) << "IpcVideoDecoder initialization failed!"; - host()->SetError(media::PIPELINE_ERROR_DECODE); - } - - initialize_callback_->Run(); - initialize_callback_.reset(); -} - -void IpcVideoDecoder::OnUninitializeComplete() { - DCHECK_EQ(ChildProcess::current()->io_message_loop(), MessageLoop::current()); - - // After the decode engine is uninitialized we are safe to destroy the decode - // context. The task will add a refcount to this object so don't need to worry - // about objects lifetime. - decode_context_->Destroy( - NewRunnableMethod(this, &IpcVideoDecoder::OnDestroyComplete)); - - // We don't need to wait for destruction of decode context to complete because - // it can happen asynchronously. This object and decode context will live - // until the destruction task is called. - stop_callback_->Run(); - stop_callback_.reset(); -} - -void IpcVideoDecoder::OnFlushComplete() { - DCHECK_EQ(ChildProcess::current()->io_message_loop(), MessageLoop::current()); - flush_callback_->Run(); - flush_callback_.reset(); -} - -void IpcVideoDecoder::OnSeekComplete() { - DCHECK_EQ(ChildProcess::current()->io_message_loop(), MessageLoop::current()); - seek_callback_->Run(); - seek_callback_.reset(); -} - -void IpcVideoDecoder::OnError() { - DCHECK_EQ(ChildProcess::current()->io_message_loop(), MessageLoop::current()); - host()->SetError(media::PIPELINE_ERROR_DECODE); -} - -// This methid is called by Demuxer after a demuxed packet is produced. -void IpcVideoDecoder::OnReadComplete(media::Buffer* buffer) { - decode_engine_->ConsumeVideoSample(buffer); -} - -void IpcVideoDecoder::OnDestroyComplete() { - // We don't need to do anything in this method. Destruction of objects will - // occur as soon as refcount goes to 0. -} - -// This method is called by VideoRenderer. We delegate the method call to -// VideoDecodeEngine. -void IpcVideoDecoder::ProduceVideoFrame( - scoped_refptr<media::VideoFrame> video_frame) { - decode_engine_->ProduceVideoFrame(video_frame); -} - -bool IpcVideoDecoder::ProvidesBuffer() { - return true; -} - -// This method is called by VideoDecodeEngine that a video frame is produced. -// This is then passed to VideoRenderer. -void IpcVideoDecoder::ConsumeVideoFrame( - scoped_refptr<media::VideoFrame> video_frame, - const media::PipelineStatistics& statistics) { - DCHECK(video_frame); - statistics_callback_->Run(statistics); - - VideoFrameReady(video_frame); -} - -// This method is called by VideoDecodeEngine to request a video frame. The -// request is passed to demuxer. -void IpcVideoDecoder::ProduceVideoSample(scoped_refptr<media::Buffer> buffer) { - demuxer_stream_->Read(NewCallback(this, &IpcVideoDecoder::OnReadComplete)); -} diff --git a/chrome/renderer/media/ipc_video_decoder.h b/chrome/renderer/media/ipc_video_decoder.h deleted file mode 100644 index 63702fa..0000000 --- a/chrome/renderer/media/ipc_video_decoder.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_RENDERER_MEDIA_IPC_VIDEO_DECODER_H_ -#define CHROME_RENDERER_MEDIA_IPC_VIDEO_DECODER_H_ - -#include "base/time.h" -#include "media/base/pts_heap.h" -#include "media/base/video_frame.h" -#include "media/filters/decoder_base.h" -#include "media/video/video_decode_engine.h" -#include "media/video/video_decode_context.h" - -struct AVRational; - -namespace ggl { -class Context; -} // namespace ggl - -class IpcVideoDecoder : public media::VideoDecoder, - public media::VideoDecodeEngine::EventHandler { - public: - IpcVideoDecoder(MessageLoop* message_loop, ggl::Context* ggl_context); - virtual ~IpcVideoDecoder(); - - // media::Filter implementation. - virtual void Stop(media::FilterCallback* callback); - virtual void Seek(base::TimeDelta time, media::FilterCallback* callback); - virtual void Pause(media::FilterCallback* callback); - virtual void Flush(media::FilterCallback* callback); - - // media::VideoDecoder implementation. - virtual void Initialize(media::DemuxerStream* demuxer_stream, - media::FilterCallback* callback, - media::StatisticsCallback* statsCallback); - virtual const media::MediaFormat& media_format(); - virtual void ProduceVideoFrame(scoped_refptr<media::VideoFrame> video_frame); - - // TODO(hclam): Remove this method. - virtual bool ProvidesBuffer(); - - // media::VideoDecodeEngine::EventHandler implementation. - virtual void OnInitializeComplete(const media::VideoCodecInfo& info); - virtual void OnUninitializeComplete(); - virtual void OnFlushComplete(); - virtual void OnSeekComplete(); - virtual void OnError(); - - // TODO(hclam): Remove this method. - virtual void OnFormatChange(media::VideoStreamInfo stream_info) {} - virtual void ProduceVideoSample(scoped_refptr<media::Buffer> buffer); - virtual void ConsumeVideoFrame(scoped_refptr<media::VideoFrame> frame, - const media::PipelineStatistics& statistics); - - private: - void OnReadComplete(media::Buffer* buffer); - void OnDestroyComplete(); - - media::MediaFormat media_format_; - - scoped_ptr<media::FilterCallback> flush_callback_; - scoped_ptr<media::FilterCallback> seek_callback_; - scoped_ptr<media::FilterCallback> initialize_callback_; - scoped_ptr<media::FilterCallback> stop_callback_; - scoped_ptr<media::StatisticsCallback> statistics_callback_; - - // Pointer to the demuxer stream that will feed us compressed buffers. - scoped_refptr<media::DemuxerStream> demuxer_stream_; - - // This is the message loop that we should assign to VideoDecodeContext. - MessageLoop* decode_context_message_loop_; - - // A context for allocating textures and issuing GLES2 commands. - // TODO(hclam): A ggl::Context lives on the Render Thread while this object - // lives on the Video Decoder Thread, we need to take care of context lost - // and destruction of the context. - ggl::Context* ggl_context_; - - // This VideoDecodeEngine translate our requests to IPC commands to the - // GPU process. - // VideoDecodeEngine should run on IO Thread instead of Render Thread to - // avoid dead lock during tear down of the media pipeline. - scoped_ptr<media::VideoDecodeEngine> decode_engine_; - - // Decoding context to be used by VideoDecodeEngine. - scoped_ptr<media::VideoDecodeContext> decode_context_; - - DISALLOW_COPY_AND_ASSIGN(IpcVideoDecoder); -}; - -#endif // CHROME_RENDERER_MEDIA_IPC_VIDEO_DECODER_H_ |