diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-22 03:20:25 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-22 03:20:25 +0000 |
commit | aed4fd65e2faeefe32c6b139a3f1e4047f137ae1 (patch) | |
tree | 2013ef267a30c6933d64991f6626eac1e5959c4c | |
parent | db0545b0baa94fd24c8d06824dd90bbccd36dce2 (diff) | |
download | chromium_src-aed4fd65e2faeefe32c6b139a3f1e4047f137ae1.zip chromium_src-aed4fd65e2faeefe32c6b139a3f1e4047f137ae1.tar.gz chromium_src-aed4fd65e2faeefe32c6b139a3f1e4047f137ae1.tar.bz2 |
Cast: Enable use of VideoEncodeAccelerator for hardware video encoding
Cast streaming library is currently using GpuVideoAcceleratorFactories
as the interface to access a VideoEncodeAccelerator. This interface
is not actually correct since Content API in Chrome doesn't provide
that. Moreover GpuVideoAcceleratorFactories also covers accelerated
video decoding which is not needed for a cast sender.
This code removes the use of GpuVideoAcceleratorFactories. It is
replaced by two callbacks. One for allocating a VideoEncodeAccelerator
and the second one allocates base::SharedMemory to store output data.
BUG=354267
Review URL: https://codereview.chromium.org/207593002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258762 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 263 insertions, 274 deletions
diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc index de71a43..aabcbd9 100644 --- a/chrome/renderer/media/cast_rtp_stream.cc +++ b/chrome/renderer/media/cast_rtp_stream.cc @@ -18,11 +18,13 @@ #include "media/base/audio_fifo.h" #include "media/base/bind_to_current_loop.h" #include "media/base/multi_channel_resampler.h" +#include "media/base/video_frame.h" #include "media/cast/cast_config.h" #include "media/cast/cast_defines.h" #include "media/cast/cast_sender.h" #include "media/cast/transport/cast_transport_config.h" #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" +#include "ui/gfx/geometry/size.h" using media::cast::AudioSenderConfig; using media::cast::VideoSenderConfig; diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc index ed70c1e..c43d440 100644 --- a/chrome/renderer/media/cast_session_delegate.cc +++ b/chrome/renderer/media/cast_session_delegate.cc @@ -38,6 +38,20 @@ const int kMaxVideoEventEntries = kMaxSerializedBytes / 150; // Assume serialized log data for each frame will take up to 75 bytes. const int kMaxAudioEventEntries = kMaxSerializedBytes / 75; +void CreateVideoEncodeAccelerator(const base::Callback< + void(scoped_refptr<base::SingleThreadTaskRunner>, + scoped_ptr<media::VideoEncodeAccelerator>)>& callback) { + NOTIMPLEMENTED(); + // Delegate the call to content API on the render thread. +} + +void CreateVideoEncodeMemory( + size_t size, + const base::Callback<void(scoped_ptr<base::SharedMemory>)>&) { + NOTIMPLEMENTED(); + // Delegate the call to content API on the render thread. +} + } // namespace CastSessionDelegate::CastSessionDelegate() @@ -103,13 +117,12 @@ void CastSessionDelegate::StartVideo( transport_config.codec = config.codec; transport_config.base.rtp_config = config.rtp_config; cast_transport_->InitializeVideo(transport_config); - // TODO(mikhal): Pass in a valid GpuVideoAcceleratorFactories to support - // hardware video encoding. cast_sender_->InitializeVideo( config, base::Bind(&CastSessionDelegate::InitializationResultCB, weak_factory_.GetWeakPtr()), - NULL /* GPU*/); + base::Bind(&CreateVideoEncodeAccelerator), + base::Bind(&CreateVideoEncodeMemory)); } void CastSessionDelegate::StartUDP(const net::IPEndPoint& remote_endpoint) { diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp index ef67982..6aa2f83 100644 --- a/media/cast/cast.gyp +++ b/media/cast/cast.gyp @@ -66,8 +66,6 @@ 'rtp_receiver/rtp_parser/rtp_parser_unittest.cc', 'test/encode_decode_test.cc', 'test/end2end_unittest.cc', - 'test/fake_gpu_video_accelerator_factories.cc', - 'test/fake_gpu_video_accelerator_factories.h', 'test/fake_single_thread_task_runner.cc', 'test/fake_single_thread_task_runner.h', 'test/fake_video_encode_accelerator.cc', diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h index 21caea0..88bbdbc 100644 --- a/media/cast/cast_config.h +++ b/media/cast/cast_config.h @@ -12,10 +12,14 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/memory/shared_memory.h" +#include "base/single_thread_task_runner.h" #include "media/cast/cast_defines.h" #include "media/cast/transport/cast_transport_config.h" namespace media { +class VideoEncodeAccelerator; + namespace cast { enum RtcpMode { @@ -137,6 +141,18 @@ typedef transport::PacketList PacketList; typedef base::Callback<void(CastInitializationStatus)> CastInitializationCallback; +typedef base::Callback<void(scoped_refptr<base::SingleThreadTaskRunner>, + scoped_ptr<media::VideoEncodeAccelerator>)> + ReceiveVideoEncodeAcceleratorCallback; +typedef base::Callback<void(const ReceiveVideoEncodeAcceleratorCallback&)> + CreateVideoEncodeAcceleratorCallback; + +typedef base::Callback<void(scoped_ptr<base::SharedMemory>)> + ReceiveVideoEncodeMemoryCallback; +typedef base::Callback<void(size_t size, + const ReceiveVideoEncodeMemoryCallback&)> + CreateVideoEncodeMemoryCallback; + } // namespace cast } // namespace media diff --git a/media/cast/cast_sender.h b/media/cast/cast_sender.h index ae6baf3..eb3327f 100644 --- a/media/cast/cast_sender.h +++ b/media/cast/cast_sender.h @@ -20,10 +20,8 @@ #include "media/cast/cast_config.h" #include "media/cast/cast_environment.h" #include "media/cast/transport/cast_transport_sender.h" -#include "media/filters/gpu_video_accelerator_factories.h" namespace media { -class GpuVideoAcceleratorFactories; class VideoFrame; namespace cast { @@ -90,7 +88,8 @@ class CastSender { virtual void InitializeVideo( const VideoSenderConfig& video_config, const CastInitializationCallback& cast_initialization_cb, - const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) = 0; + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) = 0; }; } // namespace cast diff --git a/media/cast/cast_sender_impl.cc b/media/cast/cast_sender_impl.cc index 7a60ffc..0b5a2ac 100644 --- a/media/cast/cast_sender_impl.cc +++ b/media/cast/cast_sender_impl.cc @@ -113,14 +113,16 @@ void CastSenderImpl::InitializeAudio( void CastSenderImpl::InitializeVideo( const VideoSenderConfig& video_config, const CastInitializationCallback& cast_initialization_cb, - const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) { + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); CHECK(video_config.use_external_encoder || cast_environment_->HasVideoThread()); video_sender_.reset(new VideoSender(cast_environment_, video_config, - gpu_factories, + create_vea_cb, + create_video_encode_mem_cb, cast_initialization_cb, transport_sender_)); diff --git a/media/cast/cast_sender_impl.h b/media/cast/cast_sender_impl.h index b90bec4..d09a869 100644 --- a/media/cast/cast_sender_impl.h +++ b/media/cast/cast_sender_impl.h @@ -33,7 +33,8 @@ class CastSenderImpl : public CastSender { virtual void InitializeVideo( const VideoSenderConfig& video_config, const CastInitializationCallback& cast_initialization_cb, - const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) OVERRIDE; virtual ~CastSenderImpl(); diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index 216be89..bfdcf0c 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc @@ -28,6 +28,7 @@ #include "media/cast/logging/simple_event_subscriber.h" #include "media/cast/test/fake_single_thread_task_runner.h" #include "media/cast/test/utility/audio_utility.h" +#include "media/cast/test/utility/default_config.h" #include "media/cast/test/utility/video_utility.h" #include "media/cast/transport/cast_transport_config.h" #include "media/cast/transport/cast_transport_defines.h" @@ -514,8 +515,10 @@ class End2EndTest : public ::testing::Test { // Initializing audio and video senders. cast_sender_->InitializeAudio(audio_sender_config_, base::Bind(&AudioInitializationStatus)); - cast_sender_->InitializeVideo( - video_sender_config_, base::Bind(&VideoInitializationStatus), NULL); + cast_sender_->InitializeVideo(video_sender_config_, + base::Bind(&VideoInitializationStatus), + CreateDefaultVideoEncodeAcceleratorCallback(), + CreateDefaultVideoEncodeMemoryCallback()); receiver_to_sender_.SetPacketReceiver(cast_sender_->packet_receiver()); sender_to_receiver_.SetPacketReceiver(cast_receiver_->packet_receiver()); diff --git a/media/cast/test/fake_gpu_video_accelerator_factories.cc b/media/cast/test/fake_gpu_video_accelerator_factories.cc deleted file mode 100644 index 9718a56..0000000 --- a/media/cast/test/fake_gpu_video_accelerator_factories.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 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 "media/cast/test/fake_gpu_video_accelerator_factories.h" - -#include "base/logging.h" -#include "media/cast/test/fake_video_encode_accelerator.h" -#include "media/video/video_decode_accelerator.h" - -namespace media { -namespace cast { -namespace test { - -FakeGpuVideoAcceleratorFactories::FakeGpuVideoAcceleratorFactories( - const scoped_refptr<base::SingleThreadTaskRunner>& fake_task_runner) - : fake_task_runner_(fake_task_runner) {} - -FakeGpuVideoAcceleratorFactories::~FakeGpuVideoAcceleratorFactories() {} - -scoped_ptr<VideoEncodeAccelerator> -FakeGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() { - return scoped_ptr<VideoEncodeAccelerator>(new FakeVideoEncodeAccelerator()); -} - -base::SharedMemory* FakeGpuVideoAcceleratorFactories::CreateSharedMemory( - size_t size) { - base::SharedMemory* shm = new base::SharedMemory(); - if (!shm->CreateAndMapAnonymous(size)) { - NOTREACHED(); - } - return shm; -} - -scoped_refptr<base::SingleThreadTaskRunner> -FakeGpuVideoAcceleratorFactories::GetTaskRunner() { - return fake_task_runner_; -} - -bool FakeGpuVideoAcceleratorFactories::CreateTextures( - int32 count, - const gfx::Size& size, - std::vector<uint32>* texture_ids, - std::vector<gpu::Mailbox>* texture_mailboxes, - uint32 texture_target) { - return false; -} - -scoped_ptr<VideoDecodeAccelerator> -FakeGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator( - VideoCodecProfile profile) { - return scoped_ptr<VideoDecodeAccelerator>( - static_cast<media::VideoDecodeAccelerator*>(NULL)); -} - -} // namespace test -} // namespace cast -} // namespace media diff --git a/media/cast/test/fake_gpu_video_accelerator_factories.h b/media/cast/test/fake_gpu_video_accelerator_factories.h deleted file mode 100644 index ebcadfd..0000000 --- a/media/cast/test/fake_gpu_video_accelerator_factories.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014 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 MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_ -#define MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_ - -#include "media/filters/gpu_video_accelerator_factories.h" - -#include "base/message_loop/message_loop.h" -#include "media/cast/test/fake_single_thread_task_runner.h" - -namespace media { -namespace cast { -namespace test { - -class FakeGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories { - public: - explicit FakeGpuVideoAcceleratorFactories( - const scoped_refptr<base::SingleThreadTaskRunner>& fake_task_runner); - - virtual scoped_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator() - OVERRIDE; - - virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; - - virtual scoped_refptr<base::SingleThreadTaskRunner> - GetTaskRunner() OVERRIDE; - // - // The following functions are no-op. - // - virtual bool CreateTextures(int32 count, - const gfx::Size& size, - std::vector<uint32>* texture_ids, - std::vector<gpu::Mailbox>* texture_mailboxes, - uint32 texture_target) OVERRIDE; - - virtual void DeleteTexture(uint32 texture_id) OVERRIDE {} - - virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE {} - - virtual void ReadPixels(uint32 texture_id, - const gfx::Rect& visible_rect, - const SkBitmap& pixels) OVERRIDE {}; - - virtual scoped_ptr<VideoDecodeAccelerator> CreateVideoDecodeAccelerator( - VideoCodecProfile profile) OVERRIDE; - - private: - friend class base::RefCountedThreadSafe<FakeGpuVideoAcceleratorFactories>; - virtual ~FakeGpuVideoAcceleratorFactories(); - - const scoped_refptr<base::SingleThreadTaskRunner> fake_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(FakeGpuVideoAcceleratorFactories); -}; - -} // namespace test -} // namespace cast -} // namespace media - -#endif // MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_ diff --git a/media/cast/test/fake_video_encode_accelerator.h b/media/cast/test/fake_video_encode_accelerator.h index 20ad7c3..2e0c93a 100644 --- a/media/cast/test/fake_video_encode_accelerator.h +++ b/media/cast/test/fake_video_encode_accelerator.h @@ -18,6 +18,7 @@ namespace test { class FakeVideoEncodeAccelerator : public VideoEncodeAccelerator { public: FakeVideoEncodeAccelerator(); + virtual ~FakeVideoEncodeAccelerator(); virtual void Initialize(media::VideoFrame::Format input_format, const gfx::Size& input_visible_size, @@ -36,8 +37,6 @@ class FakeVideoEncodeAccelerator : public VideoEncodeAccelerator { virtual void Destroy() OVERRIDE; private: - virtual ~FakeVideoEncodeAccelerator(); - VideoEncodeAccelerator::Client* client_; bool first_; diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index f2ec901..15a1a8f 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc @@ -22,6 +22,7 @@ #include "media/cast/logging/logging_defines.h" #include "media/cast/logging/proto/raw_events.pb.h" #include "media/cast/test/utility/audio_utility.h" +#include "media/cast/test/utility/default_config.h" #include "media/cast/test/utility/input_builder.h" #include "media/cast/test/utility/video_utility.h" #include "media/cast/transport/cast_transport_defines.h" @@ -495,7 +496,11 @@ int main(int argc, char** argv) { media::cast::CastSender::Create(cast_environment, transport_sender.get()); cast_sender->InitializeVideo( - video_config, base::Bind(&InitializationResult), NULL); + video_config, + base::Bind(&InitializationResult), + media::cast::CreateDefaultVideoEncodeAcceleratorCallback(), + media::cast::CreateDefaultVideoEncodeMemoryCallback()); + cast_sender->InitializeAudio(audio_config, base::Bind(&InitializationResult)); transport_sender->SetPacketReceiver(cast_sender->packet_receiver()); diff --git a/media/cast/test/utility/default_config.cc b/media/cast/test/utility/default_config.cc index 34eaedc..1631bfe 100644 --- a/media/cast/test/utility/default_config.cc +++ b/media/cast/test/utility/default_config.cc @@ -4,8 +4,24 @@ #include "media/cast/test/utility/default_config.h" +#include "base/bind.h" #include "media/cast/transport/cast_transport_config.h" +namespace { + +void CreateVideoEncodeAccelerator( + const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback) { + // Do nothing. +} + +void CreateVideoEncodeMemory( + size_t size, + const media::cast::ReceiveVideoEncodeMemoryCallback& callback) { + // Do nothing. +} + +} // namespace + namespace media { namespace cast { @@ -33,5 +49,14 @@ VideoReceiverConfig GetDefaultVideoReceiverConfig() { return config; } +CreateVideoEncodeAcceleratorCallback +CreateDefaultVideoEncodeAcceleratorCallback() { + return base::Bind(&CreateVideoEncodeAccelerator); +} + +CreateVideoEncodeMemoryCallback CreateDefaultVideoEncodeMemoryCallback() { + return base::Bind(&CreateVideoEncodeMemory); +} + } // namespace cast } // namespace media diff --git a/media/cast/test/utility/default_config.h b/media/cast/test/utility/default_config.h index ef7c79a..59a24404 100644 --- a/media/cast/test/utility/default_config.h +++ b/media/cast/test/utility/default_config.h @@ -20,6 +20,13 @@ AudioReceiverConfig GetDefaultAudioReceiverConfig(); // name. VideoReceiverConfig GetDefaultVideoReceiverConfig(); +// Returns a callback that does nothing. +CreateVideoEncodeAcceleratorCallback + CreateDefaultVideoEncodeAcceleratorCallback(); + +// Returns a callback that does nothing. +CreateVideoEncodeMemoryCallback CreateDefaultVideoEncodeMemoryCallback(); + } // namespace cast } // namespace media diff --git a/media/cast/video_sender/external_video_encoder.cc b/media/cast/video_sender/external_video_encoder.cc index 4f97dace..353775a 100644 --- a/media/cast/video_sender/external_video_encoder.cc +++ b/media/cast/video_sender/external_video_encoder.cc @@ -15,10 +15,13 @@ #include "media/cast/transport/cast_transport_config.h" #include "media/video/video_encode_accelerator.h" +namespace media { +namespace cast { +class LocalVideoEncodeAcceleratorClient; +} // namespace cast +} // namespace media + namespace { -// We allocate more input buffers than what is asked for by -// RequireBitstreamBuffers() due to potential threading timing. -static const int kInputBufferExtraCount = 1; static const int kOutputBufferCount = 3; void LogFrameEncodedEvent(media::cast::CastEnvironment* const cast_environment, @@ -29,6 +32,25 @@ void LogFrameEncodedEvent(media::cast::CastEnvironment* const cast_environment, media::cast::GetVideoRtpTimestamp(capture_time), media::cast::kFrameIdUnknown); } + +// Proxy this call to ExternalVideoEncoder on the cast main thread. +void ProxyCreateVideoEncodeAccelerator( + const scoped_refptr<media::cast::CastEnvironment>& cast_environment, + const base::WeakPtr<media::cast::ExternalVideoEncoder>& weak_ptr, + const media::cast::CreateVideoEncodeMemoryCallback& + create_video_encode_mem_cb, + scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, + scoped_ptr<media::VideoEncodeAccelerator> vea) { + cast_environment->PostTask( + media::cast::CastEnvironment::MAIN, + FROM_HERE, + base::Bind( + &media::cast::ExternalVideoEncoder::OnCreateVideoEncodeAccelerator, + weak_ptr, + create_video_encode_mem_cb, + encoder_task_runner, + base::Passed(&vea))); +} } // namespace namespace media { @@ -54,11 +76,14 @@ class LocalVideoEncodeAcceleratorClient public: LocalVideoEncodeAcceleratorClient( scoped_refptr<CastEnvironment> cast_environment, - scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories, + scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, + scoped_ptr<media::VideoEncodeAccelerator> vea, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, const base::WeakPtr<ExternalVideoEncoder>& weak_owner) : cast_environment_(cast_environment), - gpu_factories_(gpu_factories), - encoder_task_runner_(gpu_factories->GetTaskRunner()), + encoder_task_runner_(encoder_task_runner), + video_encode_accelerator_(vea.Pass()), + create_video_encode_memory_cb_(create_video_encode_mem_cb), weak_owner_(weak_owner), last_encoded_frame_id_(kStartFrameId) { DCHECK(encoder_task_runner_); @@ -66,16 +91,9 @@ class LocalVideoEncodeAcceleratorClient // Initialize the real HW encoder. void Initialize(const VideoSenderConfig& video_config) { - DCHECK(gpu_factories_); DCHECK(encoder_task_runner_); - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); - video_encode_accelerator_ = - gpu_factories_->CreateVideoEncodeAccelerator().Pass(); - if (!video_encode_accelerator_) - return; - VideoCodecProfile output_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; switch (video_config.codec) { case transport::kVp8: @@ -124,55 +142,11 @@ class LocalVideoEncodeAcceleratorClient DCHECK(encoder_task_runner_); DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); - if (input_buffers_free_.empty()) { - NOTREACHED(); - VLOG(2) << "EncodeVideoFrame(): drop frame due to no hw buffers"; - return; - } - const int index = input_buffers_free_.back(); - base::SharedMemory* input_buffer = input_buffers_[index]; - - // TODO(pwestin): this allocation and copy can be removed once we don't - // pass the video frame through liblingle. - - scoped_refptr<media::VideoFrame> frame = - media::VideoFrame::WrapExternalPackedMemory( - video_frame->format(), - video_frame->coded_size(), - video_frame->visible_rect(), - video_frame->natural_size(), - reinterpret_cast<uint8*>(input_buffer->memory()), - input_buffer->mapped_size(), - input_buffer->handle(), - video_frame->GetTimestamp(), - base::Bind(&LocalVideoEncodeAcceleratorClient::FinishedWithInBuffer, - this, - index)); - - if (!frame) { - VLOG(1) << "EncodeVideoFrame(): failed to create frame"; - NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); - return; - } - // Do a stride copy of the input frame to match the input requirements. - media::CopyYPlane(video_frame->data(VideoFrame::kYPlane), - video_frame->stride(VideoFrame::kYPlane), - video_frame->natural_size().height(), - frame.get()); - media::CopyUPlane(video_frame->data(VideoFrame::kUPlane), - video_frame->stride(VideoFrame::kUPlane), - video_frame->natural_size().height(), - frame.get()); - media::CopyVPlane(video_frame->data(VideoFrame::kVPlane), - video_frame->stride(VideoFrame::kVPlane), - video_frame->natural_size().height(), - frame.get()); - encoded_frame_data_storage_.push_back( EncodedFrameReturnData(capture_time, frame_encoded_callback)); // BitstreamBufferReady will be called once the encoder is done. - video_encode_accelerator_->Encode(frame, key_frame_requested); + video_encode_accelerator_->Encode(video_frame, key_frame_requested); } protected: @@ -180,10 +154,8 @@ class LocalVideoEncodeAcceleratorClient DCHECK(encoder_task_runner_); DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); - cast_environment_->PostTask( - CastEnvironment::MAIN, - FROM_HERE, - base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_)); + // Wait until shared memory is allocated to indicate that encoder is + // initialized. } virtual void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE { @@ -208,33 +180,11 @@ class LocalVideoEncodeAcceleratorClient DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); DCHECK(video_encode_accelerator_); - for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) { - base::SharedMemory* shm = - gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize( - media::VideoFrame::I420, input_coded_size)); - if (!shm) { - VLOG(1) << "RequireBitstreamBuffers(): failed to create input buffer "; - return; - } - input_buffers_.push_back(shm); - input_buffers_free_.push_back(i); - } - for (int j = 0; j < kOutputBufferCount; ++j) { - base::SharedMemory* shm = - gpu_factories_->CreateSharedMemory(output_buffer_size); - if (!shm) { - VLOG(1) << "RequireBitstreamBuffers(): failed to create input buffer "; - return; - } - output_buffers_.push_back(shm); - } - // Immediately provide all output buffers to the VEA. - for (size_t i = 0; i < output_buffers_.size(); ++i) { - video_encode_accelerator_->UseOutputBitstreamBuffer( - media::BitstreamBuffer(static_cast<int32>(i), - output_buffers_[i]->handle(), - output_buffers_[i]->mapped_size())); + create_video_encode_memory_cb_.Run( + output_buffer_size, + base::Bind(&LocalVideoEncodeAcceleratorClient::OnCreateSharedMemory, + this)); } } @@ -309,14 +259,37 @@ class LocalVideoEncodeAcceleratorClient } private: - // Encoder is done with the provided input buffer. - void FinishedWithInBuffer(int input_index) { + // Note: This method can be called on any thread. + void OnCreateSharedMemory(scoped_ptr<base::SharedMemory> memory) { + encoder_task_runner_->PostTask( + FROM_HERE, + base::Bind(&LocalVideoEncodeAcceleratorClient::ReceivedSharedMemory, + this, + base::Passed(&memory))); + } + + void ReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) { DCHECK(encoder_task_runner_); DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); - DCHECK_GE(input_index, 0); - DCHECK_LT(input_index, static_cast<int>(input_buffers_.size())); - VLOG(2) << "EncodeFrameFinished(): index=" << input_index; - input_buffers_free_.push_back(input_index); + + output_buffers_.push_back(memory.release()); + + // Wait until all requested buffers are received. + if (output_buffers_.size() < kOutputBufferCount) + return; + + // Immediately provide all output buffers to the VEA. + for (size_t i = 0; i < output_buffers_.size(); ++i) { + video_encode_accelerator_->UseOutputBitstreamBuffer( + media::BitstreamBuffer(static_cast<int32>(i), + output_buffers_[i]->handle(), + output_buffers_[i]->mapped_size())); + } + + cast_environment_->PostTask( + CastEnvironment::MAIN, + FROM_HERE, + base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_)); } friend class base::RefCountedThreadSafe<LocalVideoEncodeAcceleratorClient>; @@ -324,23 +297,17 @@ class LocalVideoEncodeAcceleratorClient virtual ~LocalVideoEncodeAcceleratorClient() {} const scoped_refptr<CastEnvironment> cast_environment_; - scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_; - const base::WeakPtr<ExternalVideoEncoder> weak_owner_; - scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; + const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; + const base::WeakPtr<ExternalVideoEncoder> weak_owner_; int max_frame_rate_; transport::VideoCodec codec_; uint32 last_encoded_frame_id_; - // Shared memory buffers for input/output with the VideoAccelerator. - ScopedVector<base::SharedMemory> input_buffers_; + // Shared memory buffers for output with the VideoAccelerator. ScopedVector<base::SharedMemory> output_buffers_; - // Input buffers ready to be filled with input from Encode(). As a LIFO since - // we don't care about ordering. - std::vector<int> input_buffers_free_; - // FIFO list. std::list<EncodedFrameReturnData> encoded_frame_data_storage_; @@ -350,25 +317,21 @@ class LocalVideoEncodeAcceleratorClient ExternalVideoEncoder::ExternalVideoEncoder( scoped_refptr<CastEnvironment> cast_environment, const VideoSenderConfig& video_config, - scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories) + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) : video_config_(video_config), cast_environment_(cast_environment), encoder_active_(false), key_frame_requested_(false), skip_next_frame_(false), skip_count_(0), - encoder_task_runner_(gpu_factories->GetTaskRunner()), weak_factory_(this) { - DCHECK(gpu_factories); DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - video_accelerator_client_ = new LocalVideoEncodeAcceleratorClient( - cast_environment, gpu_factories, weak_factory_.GetWeakPtr()); - encoder_task_runner_->PostTask( - FROM_HERE, - base::Bind(&LocalVideoEncodeAcceleratorClient::Initialize, - video_accelerator_client_, - video_config)); + create_vea_cb.Run(base::Bind(&ProxyCreateVideoEncodeAccelerator, + cast_environment, + weak_factory_.GetWeakPtr(), + create_video_encode_mem_cb)); } ExternalVideoEncoder::~ExternalVideoEncoder() { @@ -388,6 +351,26 @@ void ExternalVideoEncoder::EncoderError() { encoder_active_ = false; } +void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, + scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, + scoped_ptr<media::VideoEncodeAccelerator> vea) { + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); + encoder_task_runner_ = encoder_task_runner; + + video_accelerator_client_ = + new LocalVideoEncodeAcceleratorClient(cast_environment_, + encoder_task_runner, + vea.Pass(), + create_video_encode_mem_cb, + weak_factory_.GetWeakPtr()); + encoder_task_runner_->PostTask( + FROM_HERE, + base::Bind(&LocalVideoEncodeAcceleratorClient::Initialize, + video_accelerator_client_, + video_config_)); +} + bool ExternalVideoEncoder::EncodeVideoFrame( const scoped_refptr<media::VideoFrame>& video_frame, const base::TimeTicks& capture_time, diff --git a/media/cast/video_sender/external_video_encoder.h b/media/cast/video_sender/external_video_encoder.h index 6c4c97e..0a71026 100644 --- a/media/cast/video_sender/external_video_encoder.h +++ b/media/cast/video_sender/external_video_encoder.h @@ -10,7 +10,7 @@ #include "media/cast/cast_config.h" #include "media/cast/cast_environment.h" #include "media/cast/video_sender/video_encoder.h" -#include "media/filters/gpu_video_accelerator_factories.h" +#include "media/video/video_encode_accelerator.h" namespace media { class VideoFrame; @@ -28,7 +28,8 @@ class ExternalVideoEncoder : public VideoEncoder { ExternalVideoEncoder( scoped_refptr<CastEnvironment> cast_environment, const VideoSenderConfig& video_config, - scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories); + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb); virtual ~ExternalVideoEncoder(); @@ -51,6 +52,12 @@ class ExternalVideoEncoder : public VideoEncoder { virtual void LatestFrameIdToReference(uint32 frame_id) OVERRIDE; virtual int NumberOfSkippedFrames() const OVERRIDE; + // Called when a VEA is created. + void OnCreateVideoEncodeAccelerator( + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, + scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, + scoped_ptr<media::VideoEncodeAccelerator> vea); + protected: void EncoderInitialized(); void EncoderError(); diff --git a/media/cast/video_sender/external_video_encoder_unittest.cc b/media/cast/video_sender/external_video_encoder_unittest.cc index 7130331..71f8779 100644 --- a/media/cast/video_sender/external_video_encoder_unittest.cc +++ b/media/cast/video_sender/external_video_encoder_unittest.cc @@ -10,7 +10,6 @@ #include "media/base/video_frame.h" #include "media/cast/cast_defines.h" #include "media/cast/cast_environment.h" -#include "media/cast/test/fake_gpu_video_accelerator_factories.h" #include "media/cast/test/fake_single_thread_task_runner.h" #include "media/cast/test/fake_video_encode_accelerator.h" #include "media/cast/test/utility/video_utility.h" @@ -23,6 +22,24 @@ namespace cast { using testing::_; namespace { + +void CreateVideoEncodeAccelerator( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + scoped_ptr<VideoEncodeAccelerator> fake_vea, + const ReceiveVideoEncodeAcceleratorCallback& callback) { + callback.Run(task_runner, fake_vea.Pass()); +} + +void CreateSharedMemory( + size_t size, const ReceiveVideoEncodeMemoryCallback& callback) { + scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + if (!shm->CreateAndMapAnonymous(size)) { + NOTREACHED(); + return; + } + callback.Run(shm.Pass()); +} + class TestVideoEncoderCallback : public base::RefCountedThreadSafe<TestVideoEncoderCallback> { public: @@ -94,10 +111,15 @@ class ExternalVideoEncoderTest : public ::testing::Test { task_runner_, task_runner_, GetDefaultCastSenderLoggingConfig()); - video_encoder_.reset(new ExternalVideoEncoder( - cast_environment_, - video_config_, - new test::FakeGpuVideoAcceleratorFactories(task_runner_))); + scoped_ptr<VideoEncodeAccelerator> fake_vea( + new test::FakeVideoEncodeAccelerator()); + video_encoder_.reset( + new ExternalVideoEncoder(cast_environment_, + video_config_, + base::Bind(&CreateVideoEncodeAccelerator, + task_runner_, + base::Passed(&fake_vea)), + base::Bind(&CreateSharedMemory))); } virtual ~ExternalVideoEncoderTest() {} diff --git a/media/cast/video_sender/video_sender.cc b/media/cast/video_sender/video_sender.cc index 4d338435..b35ce55 100644 --- a/media/cast/video_sender/video_sender.cc +++ b/media/cast/video_sender/video_sender.cc @@ -47,7 +47,8 @@ class LocalRtcpVideoSenderFeedback : public RtcpSenderFeedback { VideoSender::VideoSender( scoped_refptr<CastEnvironment> cast_environment, const VideoSenderConfig& video_config, - const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, const CastInitializationCallback& cast_initialization_cb, transport::CastTransportSender* const transport_sender) : rtp_max_delay_(base::TimeDelta::FromMilliseconds( @@ -77,9 +78,10 @@ VideoSender::VideoSender( DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument"; if (video_config.use_external_encoder) { - CHECK(gpu_factories); - video_encoder_.reset(new ExternalVideoEncoder( - cast_environment, video_config, gpu_factories)); + video_encoder_.reset(new ExternalVideoEncoder(cast_environment, + video_config, + create_vea_cb, + create_video_encode_mem_cb)); } else { video_encoder_.reset(new VideoEncoderImpl( cast_environment, video_config, max_unacked_frames_)); diff --git a/media/cast/video_sender/video_sender.h b/media/cast/video_sender/video_sender.h index 73c8510..1ef4a73 100644 --- a/media/cast/video_sender/video_sender.h +++ b/media/cast/video_sender/video_sender.h @@ -18,8 +18,6 @@ #include "media/cast/logging/logging_defines.h" #include "media/cast/rtcp/rtcp.h" #include "media/cast/rtcp/sender_rtcp_event_subscriber.h" -#include "media/filters/gpu_video_accelerator_factories.h" -#include "media/video/video_encode_accelerator.h" namespace media { class VideoFrame; @@ -44,7 +42,8 @@ class VideoSender : public base::NonThreadSafe, public: VideoSender(scoped_refptr<CastEnvironment> cast_environment, const VideoSenderConfig& video_config, - const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, const CastInitializationCallback& cast_initialization_cb, transport::CastTransportSender* const transport_sender); diff --git a/media/cast/video_sender/video_sender_unittest.cc b/media/cast/video_sender/video_sender_unittest.cc index 28c7861..8fd6cd7 100644 --- a/media/cast/video_sender/video_sender_unittest.cc +++ b/media/cast/video_sender/video_sender_unittest.cc @@ -10,8 +10,9 @@ #include "media/base/video_frame.h" #include "media/cast/cast_environment.h" #include "media/cast/logging/simple_event_subscriber.h" -#include "media/cast/test/fake_gpu_video_accelerator_factories.h" #include "media/cast/test/fake_single_thread_task_runner.h" +#include "media/cast/test/fake_video_encode_accelerator.h" +#include "media/cast/test/utility/default_config.h" #include "media/cast/test/utility/video_utility.h" #include "media/cast/transport/cast_transport_config.h" #include "media/cast/transport/cast_transport_sender_impl.h" @@ -32,6 +33,23 @@ static const int kHeight = 240; using testing::_; using testing::AtLeast; +void CreateVideoEncodeAccelerator( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + scoped_ptr<VideoEncodeAccelerator> fake_vea, + const ReceiveVideoEncodeAcceleratorCallback& callback) { + callback.Run(task_runner, fake_vea.Pass()); +} + +void CreateSharedMemory( + size_t size, const ReceiveVideoEncodeMemoryCallback& callback) { + scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + if (!shm->CreateAndMapAnonymous(size)) { + NOTREACHED(); + return; + } + callback.Run(shm.Pass()); +} + class TestPacketSender : public transport::PacketSender { public: TestPacketSender() : number_of_rtp_packets_(0), number_of_rtcp_packets_(0) {} @@ -62,12 +80,14 @@ class PeerVideoSender : public VideoSender { PeerVideoSender( scoped_refptr<CastEnvironment> cast_environment, const VideoSenderConfig& video_config, - const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, + const CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, const CastInitializationCallback& cast_initialization_cb, transport::CastTransportSender* const transport_sender) : VideoSender(cast_environment, video_config, - gpu_factories, + create_vea_cb, + create_video_encode_mem_cb, cast_initialization_cb, transport_sender) {} using VideoSender::OnReceivedCastFeedback; @@ -134,18 +154,24 @@ class VideoSenderTest : public ::testing::Test { video_config.codec = transport::kVp8; if (external) { - video_sender_.reset(new PeerVideoSender( - cast_environment_, - video_config, - new test::FakeGpuVideoAcceleratorFactories(task_runner_), - base::Bind(&VideoSenderTest::InitializationResult, - base::Unretained(this)), - transport_sender_.get())); + scoped_ptr<VideoEncodeAccelerator> fake_vea( + new test::FakeVideoEncodeAccelerator()); + video_sender_.reset( + new PeerVideoSender(cast_environment_, + video_config, + base::Bind(&CreateVideoEncodeAccelerator, + task_runner_, + base::Passed(&fake_vea)), + base::Bind(&CreateSharedMemory), + base::Bind(&VideoSenderTest::InitializationResult, + base::Unretained(this)), + transport_sender_.get())); } else { video_sender_.reset( new PeerVideoSender(cast_environment_, video_config, - NULL, + CreateDefaultVideoEncodeAcceleratorCallback(), + CreateDefaultVideoEncodeMemoryCallback(), base::Bind(&VideoSenderTest::InitializationResult, base::Unretained(this)), transport_sender_.get())); |