Commit 0b15c8c3 authored by pwestin@google.com's avatar pwestin@google.com

Cast: Adding support for GPU accelerated encode

Removed the old VideoEncoderController interface and
made video_encoder a pure virtual class that
ExternalVideoEncoder and VideoEncoderImpl implements. 
This CL also remove the possibility to send in
pre-encoded video frames.

BUG=325998

Review URL: https://codereview.chromium.org/116623002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243589 0039d316-1c4b-4281-b951-d872f2087c98
parent 7065c505
...@@ -84,6 +84,12 @@ ...@@ -84,6 +84,12 @@
'test/crypto_utility.h', 'test/crypto_utility.h',
'test/encode_decode_test.cc', 'test/encode_decode_test.cc',
'test/end2end_unittest.cc', 'test/end2end_unittest.cc',
'test/fake_gpu_video_accelerator_factories.cc',
'test/fake_gpu_video_accelerator_factories.h',
'test/fake_task_runner.cc',
'test/fake_task_runner.h',
'test/fake_video_encode_accelerator.cc',
'test/fake_video_encode_accelerator.h',
'transport/pacing/mock_paced_packet_sender.cc', 'transport/pacing/mock_paced_packet_sender.cc',
'transport/pacing/mock_paced_packet_sender.h', 'transport/pacing/mock_paced_packet_sender.h',
'transport/pacing/paced_sender_unittest.cc', 'transport/pacing/paced_sender_unittest.cc',
...@@ -93,9 +99,8 @@ ...@@ -93,9 +99,8 @@
'transport/rtp_sender/rtp_packetizer/test/rtp_header_parser.h', 'transport/rtp_sender/rtp_packetizer/test/rtp_header_parser.h',
'video_receiver/video_decoder_unittest.cc', 'video_receiver/video_decoder_unittest.cc',
'video_receiver/video_receiver_unittest.cc', 'video_receiver/video_receiver_unittest.cc',
'video_sender/mock_video_encoder_controller.cc', 'video_sender/external_video_encoder_unittest.cc',
'video_sender/mock_video_encoder_controller.h', 'video_sender/video_encoder_impl_unittest.cc',
'video_sender/video_encoder_unittest.cc',
'video_sender/video_sender_unittest.cc', 'video_sender/video_sender_unittest.cc',
], # source ], # source
}, },
......
...@@ -25,7 +25,6 @@ enum RtcpMode { ...@@ -25,7 +25,6 @@ enum RtcpMode {
enum VideoCodec { enum VideoCodec {
kVp8, kVp8,
kH264, kH264,
kExternalVideo,
}; };
enum AudioCodec { enum AudioCodec {
...@@ -205,28 +204,6 @@ class PacketReceiver : public base::RefCountedThreadSafe<PacketReceiver> { ...@@ -205,28 +204,6 @@ class PacketReceiver : public base::RefCountedThreadSafe<PacketReceiver> {
friend class base::RefCountedThreadSafe<PacketReceiver>; friend class base::RefCountedThreadSafe<PacketReceiver>;
}; };
class VideoEncoderController {
public:
// Inform the encoder about the new target bit rate.
virtual void SetBitRate(int new_bit_rate) = 0;
// Inform the encoder to not encode the next frame.
// Note: this setting is sticky and should last until called with false.
virtual void SkipNextFrame(bool skip_next_frame) = 0;
// Inform the encoder to encode the next frame as a key frame.
virtual void GenerateKeyFrame() = 0;
// Inform the encoder to only reference frames older or equal to frame_id;
virtual void LatestFrameIdToReference(uint32 frame_id) = 0;
// Query the codec about how many frames it has skipped due to slow ACK.
virtual int NumberOfSkippedFrames() const = 0;
protected:
virtual ~VideoEncoderController() {}
};
} // namespace cast } // namespace cast
} // namespace media } // namespace media
......
...@@ -32,8 +32,8 @@ CastEnvironment::CastEnvironment( ...@@ -32,8 +32,8 @@ CastEnvironment::CastEnvironment(
CastEnvironment::~CastEnvironment() {} CastEnvironment::~CastEnvironment() {}
bool CastEnvironment::PostTask(ThreadId identifier, bool CastEnvironment::PostTask(ThreadId identifier,
const tracked_objects::Location& from_here, const tracked_objects::Location& from_here,
const base::Closure& task) { const base::Closure& task) {
scoped_refptr<TaskRunner> task_runner = scoped_refptr<TaskRunner> task_runner =
GetMessageTaskRunnerForThread(identifier); GetMessageTaskRunnerForThread(identifier);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "media/cast/cast_config.h" #include "media/cast/cast_config.h"
#include "media/cast/cast_environment.h" #include "media/cast/cast_environment.h"
#include "media/filters/gpu_video_accelerator_factories.h"
namespace media { namespace media {
class AudioBus; class AudioBus;
...@@ -38,14 +39,6 @@ class FrameInput : public base::RefCountedThreadSafe<FrameInput> { ...@@ -38,14 +39,6 @@ class FrameInput : public base::RefCountedThreadSafe<FrameInput> {
const scoped_refptr<media::VideoFrame>& video_frame, const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time) = 0; const base::TimeTicks& capture_time) = 0;
// The video_frame must be valid until the callback is called.
// The callback is called from the main cast thread as soon as
// the cast sender is done with the frame; it does not mean that the encoded
// frame has been sent out.
virtual void InsertCodedVideoFrame(const EncodedVideoFrame* video_frame,
const base::TimeTicks& capture_time,
const base::Closure callback) = 0;
// The |audio_bus| must be valid until the |done_callback| is called. // The |audio_bus| must be valid until the |done_callback| is called.
// The callback is called from the main cast thread as soon as the encoder is // The callback is called from the main cast thread as soon as the encoder is
// done with |audio_bus|; it does not mean that the encoded data has been // done with |audio_bus|; it does not mean that the encoded data has been
...@@ -78,8 +71,9 @@ class CastSender { ...@@ -78,8 +71,9 @@ class CastSender {
scoped_refptr<CastEnvironment> cast_environment, scoped_refptr<CastEnvironment> cast_environment,
const AudioSenderConfig& audio_config, const AudioSenderConfig& audio_config,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
VideoEncoderController* const video_encoder_controller, const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
PacketSender* const packet_sender); PacketSender* const packet_sender);
// TODO(pwestin): Add callback for status messages; initialized, errors etc.
virtual ~CastSender() {} virtual ~CastSender() {}
......
...@@ -32,14 +32,6 @@ class LocalFrameInput : public FrameInput { ...@@ -32,14 +32,6 @@ class LocalFrameInput : public FrameInput {
video_frame, capture_time)); video_frame, capture_time));
} }
virtual void InsertCodedVideoFrame(const EncodedVideoFrame* video_frame,
const base::TimeTicks& capture_time,
const base::Closure callback) OVERRIDE {
cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
base::Bind(&VideoSender::InsertCodedVideoFrame, video_sender_,
video_frame, capture_time, callback));
}
virtual void InsertAudio(const AudioBus* audio_bus, virtual void InsertAudio(const AudioBus* audio_bus,
const base::TimeTicks& recorded_time, const base::TimeTicks& recorded_time,
const base::Closure& done_callback) OVERRIDE { const base::Closure& done_callback) OVERRIDE {
...@@ -153,25 +145,21 @@ CastSender* CastSender::CreateCastSender( ...@@ -153,25 +145,21 @@ CastSender* CastSender::CreateCastSender(
scoped_refptr<CastEnvironment> cast_environment, scoped_refptr<CastEnvironment> cast_environment,
const AudioSenderConfig& audio_config, const AudioSenderConfig& audio_config,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
VideoEncoderController* const video_encoder_controller, const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
PacketSender* const packet_sender) { PacketSender* const packet_sender) {
return new CastSenderImpl(cast_environment, return new CastSenderImpl(cast_environment, audio_config, video_config,
audio_config, gpu_factories, packet_sender);
video_config,
video_encoder_controller,
packet_sender);
} }
CastSenderImpl::CastSenderImpl( CastSenderImpl::CastSenderImpl(
scoped_refptr<CastEnvironment> cast_environment, scoped_refptr<CastEnvironment> cast_environment,
const AudioSenderConfig& audio_config, const AudioSenderConfig& audio_config,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
VideoEncoderController* const video_encoder_controller, const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
PacketSender* const packet_sender) PacketSender* const packet_sender)
: pacer_(cast_environment, packet_sender), : pacer_(cast_environment, packet_sender),
audio_sender_(cast_environment, audio_config, &pacer_), audio_sender_(cast_environment, audio_config, &pacer_),
video_sender_(cast_environment, video_config, video_encoder_controller, video_sender_(cast_environment, video_config, gpu_factories, &pacer_),
&pacer_),
frame_input_(new LocalFrameInput(cast_environment, frame_input_(new LocalFrameInput(cast_environment,
audio_sender_.AsWeakPtr(), audio_sender_.AsWeakPtr(),
video_sender_.AsWeakPtr())), video_sender_.AsWeakPtr())),
......
...@@ -28,11 +28,12 @@ class VideoSender; ...@@ -28,11 +28,12 @@ class VideoSender;
// together such as pacer, packet receiver, frame input, audio and video sender. // together such as pacer, packet receiver, frame input, audio and video sender.
class CastSenderImpl : public CastSender { class CastSenderImpl : public CastSender {
public: public:
CastSenderImpl(scoped_refptr<CastEnvironment> cast_environment, CastSenderImpl(
const AudioSenderConfig& audio_config, scoped_refptr<CastEnvironment> cast_environment,
const VideoSenderConfig& video_config, const AudioSenderConfig& audio_config,
VideoEncoderController* const video_encoder_controller, const VideoSenderConfig& video_config,
PacketSender* const packet_sender); const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
PacketSender* const packet_sender);
virtual ~CastSenderImpl(); virtual ~CastSenderImpl();
......
// 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"
namespace media {
namespace cast {
namespace test {
FakeGpuVideoAcceleratorFactories::FakeGpuVideoAcceleratorFactories(
const scoped_refptr<base::TaskRunner>& fake_task_runner)
: fake_task_runner_(fake_task_runner) {
}
FakeGpuVideoAcceleratorFactories::~FakeGpuVideoAcceleratorFactories() {
}
scoped_ptr<VideoEncodeAccelerator>
FakeGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator(
VideoEncodeAccelerator::Client* client) {
return scoped_ptr<VideoEncodeAccelerator>(
new FakeVideoEncodeAccelerator(client));
}
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 scoped_refptr<base::SingleThreadTaskRunner>(
static_cast<base::SingleThreadTaskRunner*>(fake_task_runner_.get()));
}
uint32 FakeGpuVideoAcceleratorFactories::CreateTextures(
int32 count,
const gfx::Size& size,
std::vector<uint32>* texture_ids,
std::vector<gpu::Mailbox>* texture_mailboxes,
uint32 texture_target) {
return 0;
}
scoped_ptr<VideoDecodeAccelerator>
FakeGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator(
VideoCodecProfile profile,
VideoDecodeAccelerator::Client* client) {
return scoped_ptr<VideoDecodeAccelerator>(
static_cast<media::VideoDecodeAccelerator*>(NULL));
}
bool FakeGpuVideoAcceleratorFactories::IsAborted() {
return false;
}
} // namespace test
} // namespace cast
} // namespace media
// 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_task_runner.h"
namespace media {
namespace cast {
namespace test {
class FakeGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories {
public:
explicit FakeGpuVideoAcceleratorFactories(
const scoped_refptr<base::TaskRunner>& fake_task_runner);
virtual scoped_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator(
VideoEncodeAccelerator::Client* client) OVERRIDE;
virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() OVERRIDE;
//
// The following functions are no-op.
//
virtual uint32 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::Size& size,
const SkBitmap& pixels) OVERRIDE {};
virtual scoped_ptr<VideoDecodeAccelerator> CreateVideoDecodeAccelerator(
VideoCodecProfile profile,
VideoDecodeAccelerator::Client* client) OVERRIDE;
virtual void Abort() OVERRIDE {}
virtual bool IsAborted() OVERRIDE;
private:
friend class base::RefCountedThreadSafe<FakeGpuVideoAcceleratorFactories>;
virtual ~FakeGpuVideoAcceleratorFactories();
const scoped_refptr<base::TaskRunner> fake_task_runner_;
DISALLOW_COPY_AND_ASSIGN(FakeGpuVideoAcceleratorFactories);
};
} // namespace test
} // namespace cast
} // namespace media
#endif // MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
// 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_video_encode_accelerator.h"
#include "base/logging.h"
namespace media {
namespace cast {
namespace test {
static const unsigned int kMinimumInputCount = 1;
static const size_t kMinimumOutputBufferSize = 123456;
FakeVideoEncodeAccelerator::FakeVideoEncodeAccelerator(
VideoEncodeAccelerator::Client* client)
: client_(client),
first_(true) {
DCHECK(client);
}
FakeVideoEncodeAccelerator::~FakeVideoEncodeAccelerator() {
}
void FakeVideoEncodeAccelerator::Initialize(
media::VideoFrame::Format input_format,
const gfx::Size& input_visible_size,
VideoCodecProfile output_profile,
uint32 initial_bitrate) {
DCHECK(client_);
if (output_profile != media::VP8PROFILE_MAIN &&
output_profile != media::H264PROFILE_MAIN) {
client_->NotifyError(kInvalidArgumentError);
return;
}
client_->NotifyInitializeDone();
client_->RequireBitstreamBuffers(kMinimumInputCount,
input_visible_size,
kMinimumOutputBufferSize);
}
void FakeVideoEncodeAccelerator::Encode(const scoped_refptr<VideoFrame>& frame,
bool force_keyframe) {
DCHECK(client_);
DCHECK(!available_buffer_ids_.empty());
// Fake that we have encoded the frame; resulting in using the full output
// buffer.
int32 id = available_buffer_ids_.front();
available_buffer_ids_.pop_front();
bool is_key_fame = force_keyframe;
if (first_) {
is_key_fame = true;
first_ = false;
}
client_->BitstreamBufferReady(id, kMinimumOutputBufferSize, is_key_fame);
}
void FakeVideoEncodeAccelerator::UseOutputBitstreamBuffer(
const BitstreamBuffer& buffer) {
available_buffer_ids_.push_back(buffer.id());
}
void FakeVideoEncodeAccelerator::RequestEncodingParametersChange(
uint32 bitrate, uint32 framerate) {
// No-op.
}
void FakeVideoEncodeAccelerator::Destroy() {
delete this;
}
} // namespace test
} // namespace cast
} // namespace media
// 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_MOCK_VIDEO_ENCODE_ACCELERATOR_H_
#define MEDIA_CAST_TEST_FAKE_MOCK_VIDEO_ENCODE_ACCELERATOR_H_
#include "media/video/video_encode_accelerator.h"
#include <list>
#include "media/base/bitstream_buffer.h"
namespace media {
namespace cast {
namespace test {
class FakeVideoEncodeAccelerator : public VideoEncodeAccelerator {
public:
explicit FakeVideoEncodeAccelerator(VideoEncodeAccelerator::Client* client);
virtual void Initialize(media::VideoFrame::Format input_format,
const gfx::Size& input_visible_size,
VideoCodecProfile output_profile,
uint32 initial_bitrate) OVERRIDE;
virtual void Encode(const scoped_refptr<VideoFrame>& frame,
bool force_keyframe) OVERRIDE;
virtual void UseOutputBitstreamBuffer(const BitstreamBuffer& buffer) OVERRIDE;
virtual void RequestEncodingParametersChange(uint32 bitrate,
uint32 framerate) OVERRIDE;
virtual void Destroy() OVERRIDE;
private:
virtual ~FakeVideoEncodeAccelerator();
VideoEncodeAccelerator::Client* client_;
bool first_;
std::list<int32> available_buffer_ids_;
DISALLOW_COPY_AND_ASSIGN(FakeVideoEncodeAccelerator);
};
} // namespace test
} // namespace cast
} // namespace media
#endif // MEDIA_CAST_TEST_FAKE_MOCK_VIDEO_ENCODE_ACCELERATOR_H_
...@@ -23,9 +23,6 @@ VideoDecoder::VideoDecoder(const VideoReceiverConfig& video_config, ...@@ -23,9 +23,6 @@ VideoDecoder::VideoDecoder(const VideoReceiverConfig& video_config,
case kH264: case kH264:
NOTIMPLEMENTED(); NOTIMPLEMENTED();
break; break;
case kExternalVideo:
DCHECK(false) << "Invalid codec";
break;
} }
} }
......
...@@ -20,7 +20,6 @@ namespace cast { ...@@ -20,7 +20,6 @@ namespace cast {
using testing::_; using testing::_;
// Random frame size for testing. // Random frame size for testing.
const int kFrameSize = 2345;
static const int64 kStartMillisecond = GG_INT64_C(1245); static const int64 kStartMillisecond = GG_INT64_C(1245);
namespace { namespace {
...@@ -76,18 +75,6 @@ TEST_F(VideoDecoderTest, DISABLED_SizeZero) { ...@@ -76,18 +75,6 @@ TEST_F(VideoDecoderTest, DISABLED_SizeZero) {
"Empty frame"); "Empty frame");
} }
// TODO(pwestin): EXPECT_DEATH tests can not pass valgrind.
TEST_F(VideoDecoderTest, DISABLED_InvalidCodec) {
EncodedVideoFrame encoded_frame;
base::TimeTicks render_time;
encoded_frame.data.assign(kFrameSize, 0);
encoded_frame.codec = kExternalVideo;
EXPECT_DEATH(
decoder_->DecodeVideoFrame(&encoded_frame, render_time, base::Bind(
&DecodeTestFrameCallback::DecodeComplete, test_callback_)),
"Invalid codec");
}
// TODO(pwestin): Test decoding a real frame. // TODO(pwestin): Test decoding a real frame.
} // namespace cast } // namespace cast
......
...@@ -147,8 +147,7 @@ bool Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, ...@@ -147,8 +147,7 @@ bool Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame,
if (key_frame_requested_) { if (key_frame_requested_) {
flags = VPX_EFLAG_FORCE_KF; flags = VPX_EFLAG_FORCE_KF;
// Self reference. // Self reference.
latest_frame_id_to_reference = latest_frame_id_to_reference = last_encoded_frame_id_ + 1;
static_cast<uint8>(last_encoded_frame_id_ + 1);
// We can pick any buffer as buffer_to_update since we update // We can pick any buffer as buffer_to_update since we update
// them all. // them all.
buffer_to_update = kLastBuffer; buffer_to_update = kLastBuffer;
......
This diff is collapsed.
// 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_VIDEO_SENDER_EXTERNAL_VIDEO_ENCODER_H_
#define MEDIA_CAST_VIDEO_SENDER_EXTERNAL_VIDEO_ENCODER_H_
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#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"
namespace media {
class VideoFrame;
}
namespace media {
namespace cast {
class LocalVideoEncodeAcceleratorClient;
// This object is called external from the main cast thread and internally from
// the video encoder thread.
class ExternalVideoEncoder : public VideoEncoder {
public:
ExternalVideoEncoder(
scoped_refptr<CastEnvironment> cast_environment,
const VideoSenderConfig& video_config,
scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories);
virtual ~ExternalVideoEncoder();
// Called from the main cast thread. This function post the encode task to the
// video encoder thread;
// The video_frame must be valid until the closure callback is called.
// The closure callback is called from the video encoder thread as soon as
// the encoder is done with the frame; it does not mean that the encoded frame
// has been sent out.
// Once the encoded frame is ready the frame_encoded_callback is called.
virtual bool EncodeVideoFrame(
const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time,
const FrameEncodedCallback& frame_encoded_callback) OVERRIDE;
// The following functions are called from the main cast thread.
virtual void SetBitRate(int new_bit_rate) OVERRIDE;
virtual void SkipNextFrame(bool skip_next_frame) OVERRIDE;
virtual void GenerateKeyFrame() OVERRIDE;
virtual void LatestFrameIdToReference(uint32 frame_id) OVERRIDE;
virtual int NumberOfSkippedFrames() const OVERRIDE;
protected:
void EncoderInitialized();
void EncoderError();
private:
friend class LocalVideoEncodeAcceleratorClient;
const VideoSenderConfig video_config_;
scoped_refptr<CastEnvironment> cast_environment_;
bool encoder_active_;
bool key_frame_requested_;
bool skip_next_frame_;
int skip_count_;
scoped_refptr<LocalVideoEncodeAcceleratorClient> video_accelerator_client_;
scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
// Weak pointer factory for posting back LocalVideoEncodeAcceleratorClient
// notifications to ExternalVideoEncoder.
base::WeakPtrFactory<ExternalVideoEncoder> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ExternalVideoEncoder);
};
} // namespace cast
} // namespace media
#endif // MEDIA_CAST_VIDEO_SENDER_EXTERNAL_VIDEO_ENCODER_H_
// 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 <vector>
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#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_task_runner.h"
#include "media/cast/test/fake_video_encode_accelerator.h"
#include "media/cast/test/video_utility.h"
#include "media/cast/video_sender/external_video_encoder.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
namespace cast {
using testing::_;
namespace {
class TestVideoEncoderCallback :
public base::RefCountedThreadSafe<TestVideoEncoderCallback> {
public:
TestVideoEncoderCallback() {}
void SetExpectedResult(bool expected_key_frame,
uint8 expected_frame_id,
uint8 expected_last_referenced_frame_id,
const base::TimeTicks& expected_capture_time) {
expected_key_frame_ = expected_key_frame;
expected_frame_id_ = expected_frame_id;
expected_last_referenced_frame_id_ = expected_last_referenced_frame_id;
expected_capture_time_ = expected_capture_time;
}
void DeliverEncodedVideoFrame(scoped_ptr<EncodedVideoFrame> encoded_frame,
const base::TimeTicks& capture_time) {
EXPECT_EQ(expected_key_frame_, encoded_frame->key_frame);
EXPECT_EQ(expected_frame_id_, encoded_frame->frame_id);
EXPECT_EQ(expected_last_referenced_frame_id_,
encoded_frame->last_referenced_frame_id);
EXPECT_EQ(expected_capture_time_, capture_time);
}
protected:
virtual ~TestVideoEncoderCallback() {}
private:
friend class base::RefCountedThreadSafe<TestVideoEncoderCallback>;
bool expected_key_frame_;
uint8 expected_frame_id_;
uint8 expected_last_referenced_frame_id_;
base::TimeTicks expected_capture_time_;
};
} // namespace
class ExternalVideoEncoderTest : public ::testing::Test {
protected:
ExternalVideoEncoderTest()
: test_video_encoder_callback_(new TestVideoEncoderCallback()) {
video_config_.sender_ssrc = 1;
video_config_.incoming_feedback_ssrc = 2;
video_config_.rtp_payload_type = 127;
video_config_.use_external_encoder = true;
video_config_.width = 320;
video_config_.height = 240;
video_config_.max_bitrate = 5000000;
video_config_.min_bitrate = 1000000;
video_config_.start_bitrate = 2000000;
video_config_.max_qp = 56;
video_config_.min_qp = 0;
video_config_.max_frame_rate = 30;
video_config_.max_number_of_video_buffers_used = 3;
video_config_.codec = kVp8;
gfx::Size size(video_config_.width, video_config_.height);
video_frame_ = media::VideoFrame::CreateFrame(VideoFrame::I420,
size, gfx::Rect(size), size, base::TimeDelta());
PopulateVideoFrame(video_frame_, 123);
}
virtual ~ExternalVideoEncoderTest() {}
virtual void SetUp() {
task_runner_ = new test::FakeTaskRunner(&testing_clock_);
cast_environment_ = new CastEnvironment(&testing_clock_, task_runner_,
task_runner_, task_runner_, task_runner_, task_runner_,
GetDefaultCastLoggingConfig());
video_encoder_.reset(new ExternalVideoEncoder(
cast_environment_,
video_config_,
new test::FakeGpuVideoAcceleratorFactories(task_runner_)));
}
base::SimpleTestTickClock testing_clock_;
scoped_refptr<TestVideoEncoderCallback> test_video_encoder_callback_;
VideoSenderConfig video_config_;
scoped_refptr<test::FakeTaskRunner> task_runner_;
scoped_ptr<VideoEncoder> video_encoder_;
scoped_refptr<media::VideoFrame> video_frame_;
scoped_refptr<CastEnvironment> cast_environment_;
};
TEST_F(ExternalVideoEncoderTest, EncodePattern30fpsRunningOutOfAck) {
task_runner_->RunTasks(); // Run the initializer on the correct thread.
VideoEncoder::FrameEncodedCallback frame_encoded_callback =
base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame,
test_video_encoder_callback_.get());
base::TimeTicks capture_time;
capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(true, 0, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback));
task_runner_->RunTasks();
for (int i = 0; i < 6; ++i) {
capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, i + 1, i,
capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback));
task_runner_->RunTasks();
}
}
} // namespace cast
} // namespace media
// Copyright 2013 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/video_sender/mock_video_encoder_controller.h"
namespace media {
namespace cast {
MockVideoEncoderController::MockVideoEncoderController() {
}
MockVideoEncoderController::~MockVideoEncoderController() {
}
} // namespace cast
} // namespace media
// Copyright 2013 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_VIDEO_SENDER_MOCK_VIDEO_ENCODER_CONTROLLER_H_
#define MEDIA_CAST_VIDEO_SENDER_MOCK_VIDEO_ENCODER_CONTROLLER_H_
#include "media/cast/cast_config.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
namespace cast {
class MockVideoEncoderController : public VideoEncoderController {
public:
MockVideoEncoderController();
virtual ~MockVideoEncoderController();
MOCK_METHOD1(SetBitRate, void(int new_bit_rate));
MOCK_METHOD1(SkipNextFrame, void(bool skip_next_frame));
MOCK_METHOD0(GenerateKeyFrame, void());
MOCK_METHOD1(LatestFrameIdToReference, void(uint32 frame_id));
MOCK_CONST_METHOD0(NumberOfSkippedFrames, int());
};
} // namespace cast
} // namespace media
#endif // MEDIA_CAST_VIDEO_SENDER_MOCK_VIDEO_ENCODER_CONTROLLER_H_
...@@ -5,79 +5,55 @@ ...@@ -5,79 +5,55 @@
#ifndef MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_H_ #ifndef MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_H_
#define MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_H_ #define MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h" #include "base/time/time.h"
#include "media/base/video_frame.h"
#include "media/cast/cast_config.h" #include "media/cast/cast_config.h"
#include "media/cast/cast_environment.h" #include "media/cast/cast_environment.h"
#include "media/cast/video_sender/codecs/vp8/vp8_encoder.h"
namespace media {
class VideoFrame;
}
namespace media { namespace media {
namespace cast { namespace cast {
// This object is called external from the main cast thread and internally from // All these functions are called from the main cast thread.
// the video encoder thread. class VideoEncoder {
class VideoEncoder : public VideoEncoderController {
public: public:
typedef base::Callback<void(scoped_ptr<EncodedVideoFrame>, typedef base::Callback<void(scoped_ptr<EncodedVideoFrame>,
const base::TimeTicks&)> FrameEncodedCallback; const base::TimeTicks&)> FrameEncodedCallback;
VideoEncoder(scoped_refptr<CastEnvironment> cast_environment, virtual ~VideoEncoder() {}
const VideoSenderConfig& video_config,
uint8 max_unacked_frames);
virtual ~VideoEncoder();
// Called from the main cast thread. This function post the encode task to the
// video encoder thread;
// The video_frame must be valid until the closure callback is called. // The video_frame must be valid until the closure callback is called.
// The closure callback is called from the video encoder thread as soon as // The closure callback is called from the video encoder thread as soon as
// the encoder is done with the frame; it does not mean that the encoded frame // the encoder is done with the frame; it does not mean that the encoded frame
// has been sent out. // has been sent out.
// Once the encoded frame is ready the frame_encoded_callback is called. // Once the encoded frame is ready the frame_encoded_callback is called.
bool EncodeVideoFrame(const scoped_refptr<media::VideoFrame>& video_frame, virtual bool EncodeVideoFrame(
const base::TimeTicks& capture_time,
const FrameEncodedCallback& frame_encoded_callback);
protected:
struct CodecDynamicConfig {
bool key_frame_requested;
uint32 latest_frame_id_to_reference;
int bit_rate;
};
// The actual encode, called from the video encoder thread.
void EncodeVideoFrameEncoderThread(
const scoped_refptr<media::VideoFrame>& video_frame, const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time, const base::TimeTicks& capture_time,
const CodecDynamicConfig& dynamic_config, const FrameEncodedCallback& frame_encoded_callback) = 0;
const FrameEncodedCallback& frame_encoded_callback);
// Inform the encoder about the new target bit rate.
virtual void SetBitRate(int new_bit_rate) = 0;
// The following functions are called from the main cast thread. // Inform the encoder to not encode the next frame.
virtual void SetBitRate(int new_bit_rate) OVERRIDE; // Note: this setting is sticky and should last until called with false.
virtual void SkipNextFrame(bool skip_next_frame) OVERRIDE; virtual void SkipNextFrame(bool skip_next_frame) = 0;
virtual void GenerateKeyFrame() OVERRIDE;
virtual void LatestFrameIdToReference(uint32 frame_id) OVERRIDE;
virtual int NumberOfSkippedFrames() const OVERRIDE;
private: // Inform the encoder to encode the next frame as a key frame.
friend class base::RefCountedThreadSafe<VideoEncoder>; virtual void GenerateKeyFrame() = 0;
const VideoSenderConfig video_config_; // Inform the encoder to only reference frames older or equal to frame_id;
scoped_refptr<CastEnvironment> cast_environment_; virtual void LatestFrameIdToReference(uint32 frame_id) = 0;
scoped_ptr<Vp8Encoder> vp8_encoder_;
CodecDynamicConfig dynamic_config_;
bool skip_next_frame_;
int skip_count_;
DISALLOW_COPY_AND_ASSIGN(VideoEncoder); // Query the codec about how many frames it has skipped due to slow ACK.
virtual int NumberOfSkippedFrames() const = 0;
}; };
} // namespace cast } // namespace cast
} // namespace media } // namespace media
#endif // MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_H_ #endif // MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_H_
// Copyright 2013 The Chromium Authors. All rights reserved. // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -9,20 +9,22 @@ ...@@ -9,20 +9,22 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/cast/cast_defines.h" #include "media/cast/cast_defines.h"
#include "media/cast/video_sender/video_encoder_impl.h"
namespace media { namespace media {
namespace cast { namespace cast {
void LogFrameEncodedEvent(CastEnvironment* const cast_environment, void LogFrameEncodedEvent(const base::TimeTicks& now,
CastEnvironment* const cast_environment,
const base::TimeTicks& capture_time) { const base::TimeTicks& capture_time) {
base::TimeTicks now = cast_environment->Clock()->NowTicks();
cast_environment->Logging()->InsertFrameEvent(now, kVideoFrameEncoded, cast_environment->Logging()->InsertFrameEvent(now, kVideoFrameEncoded,
GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); GetVideoRtpTimestamp(capture_time), kFrameIdUnknown);
} }
VideoEncoder::VideoEncoder(scoped_refptr<CastEnvironment> cast_environment, VideoEncoderImpl::VideoEncoderImpl(
const VideoSenderConfig& video_config, scoped_refptr<CastEnvironment> cast_environment,
uint8 max_unacked_frames) const VideoSenderConfig& video_config,
uint8 max_unacked_frames)
: video_config_(video_config), : video_config_(video_config),
cast_environment_(cast_environment), cast_environment_(cast_environment),
skip_next_frame_(false), skip_next_frame_(false),
...@@ -38,9 +40,9 @@ VideoEncoder::VideoEncoder(scoped_refptr<CastEnvironment> cast_environment, ...@@ -38,9 +40,9 @@ VideoEncoder::VideoEncoder(scoped_refptr<CastEnvironment> cast_environment,
dynamic_config_.bit_rate = video_config.start_bitrate; dynamic_config_.bit_rate = video_config.start_bitrate;
} }
VideoEncoder::~VideoEncoder() {} VideoEncoderImpl::~VideoEncoderImpl() {}
bool VideoEncoder::EncodeVideoFrame( bool VideoEncoderImpl::EncodeVideoFrame(
const scoped_refptr<media::VideoFrame>& video_frame, const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time, const base::TimeTicks& capture_time,
const FrameEncodedCallback& frame_encoded_callback) { const FrameEncodedCallback& frame_encoded_callback) {
...@@ -49,6 +51,7 @@ bool VideoEncoder::EncodeVideoFrame( ...@@ -49,6 +51,7 @@ bool VideoEncoder::EncodeVideoFrame(
if (skip_next_frame_) { if (skip_next_frame_) {
++skip_count_; ++skip_count_;
skip_next_frame_ = false;
VLOG(1) << "Skip encoding frame"; VLOG(1) << "Skip encoding frame";
return false; return false;
} }
...@@ -57,7 +60,7 @@ bool VideoEncoder::EncodeVideoFrame( ...@@ -57,7 +60,7 @@ bool VideoEncoder::EncodeVideoFrame(
cast_environment_->Logging()->InsertFrameEvent(now, kVideoFrameSentToEncoder, cast_environment_->Logging()->InsertFrameEvent(now, kVideoFrameSentToEncoder,
GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); GetVideoRtpTimestamp(capture_time), kFrameIdUnknown);
cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER, FROM_HERE, cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER, FROM_HERE,
base::Bind(&VideoEncoder::EncodeVideoFrameEncoderThread, base::Bind(&VideoEncoderImpl::EncodeVideoFrameEncoderThread,
base::Unretained(this), video_frame, capture_time, base::Unretained(this), video_frame, capture_time,
dynamic_config_, frame_encoded_callback)); dynamic_config_, frame_encoded_callback));
...@@ -65,7 +68,7 @@ bool VideoEncoder::EncodeVideoFrame( ...@@ -65,7 +68,7 @@ bool VideoEncoder::EncodeVideoFrame(
return true; return true;
} }
void VideoEncoder::EncodeVideoFrameEncoderThread( void VideoEncoderImpl::EncodeVideoFrameEncoderThread(
const scoped_refptr<media::VideoFrame>& video_frame, const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time, const base::TimeTicks& capture_time,
const CodecDynamicConfig& dynamic_config, const CodecDynamicConfig& dynamic_config,
...@@ -81,8 +84,9 @@ void VideoEncoder::EncodeVideoFrameEncoderThread( ...@@ -81,8 +84,9 @@ void VideoEncoder::EncodeVideoFrameEncoderThread(
scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame());
bool retval = vp8_encoder_->Encode(video_frame, encoded_frame.get()); bool retval = vp8_encoder_->Encode(video_frame, encoded_frame.get());
base::TimeTicks now = cast_environment_->Clock()->NowTicks();
cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
base::Bind(LogFrameEncodedEvent, cast_environment_, capture_time)); base::Bind(LogFrameEncodedEvent, now, cast_environment_, capture_time));
if (!retval) { if (!retval) {
VLOG(1) << "Encoding failed"; VLOG(1) << "Encoding failed";
...@@ -98,26 +102,26 @@ void VideoEncoder::EncodeVideoFrameEncoderThread( ...@@ -98,26 +102,26 @@ void VideoEncoder::EncodeVideoFrameEncoderThread(
} }
// Inform the encoder about the new target bit rate. // Inform the encoder about the new target bit rate.
void VideoEncoder::SetBitRate(int new_bit_rate) { void VideoEncoderImpl::SetBitRate(int new_bit_rate) {
dynamic_config_.bit_rate = new_bit_rate; dynamic_config_.bit_rate = new_bit_rate;
} }
// Inform the encoder to not encode the next frame. // Inform the encoder to not encode the next frame.
void VideoEncoder::SkipNextFrame(bool skip_next_frame) { void VideoEncoderImpl::SkipNextFrame(bool skip_next_frame) {
skip_next_frame_ = skip_next_frame; skip_next_frame_ = skip_next_frame;
} }
// Inform the encoder to encode the next frame as a key frame. // Inform the encoder to encode the next frame as a key frame.
void VideoEncoder::GenerateKeyFrame() { void VideoEncoderImpl::GenerateKeyFrame() {
dynamic_config_.key_frame_requested = true; dynamic_config_.key_frame_requested = true;
} }
// Inform the encoder to only reference frames older or equal to frame_id; // Inform the encoder to only reference frames older or equal to frame_id;
void VideoEncoder::LatestFrameIdToReference(uint32 frame_id) { void VideoEncoderImpl::LatestFrameIdToReference(uint32 frame_id) {
dynamic_config_.latest_frame_id_to_reference = frame_id; dynamic_config_.latest_frame_id_to_reference = frame_id;
} }
int VideoEncoder::NumberOfSkippedFrames() const { int VideoEncoderImpl::NumberOfSkippedFrames() const {
return skip_count_; return skip_count_;
} }
......
// 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_VIDEO_SENDER_VIDEO_ENCODER_IMPL_H_
#define MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_IMPL_H_
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_environment.h"
#include "media/cast/video_sender/codecs/vp8/vp8_encoder.h"
#include "media/cast/video_sender/video_encoder.h"
namespace media {
class VideoFrame;
namespace cast {
// This object is called external from the main cast thread and internally from
// the video encoder thread.
class VideoEncoderImpl : public VideoEncoder {
public:
typedef base::Callback<void(scoped_ptr<EncodedVideoFrame>,
const base::TimeTicks&)> FrameEncodedCallback;
VideoEncoderImpl(scoped_refptr<CastEnvironment> cast_environment,
const VideoSenderConfig& video_config,
uint8 max_unacked_frames);
virtual ~VideoEncoderImpl();
// Called from the main cast thread. This function post the encode task to the
// video encoder thread;
// The video_frame must be valid until the closure callback is called.
// The closure callback is called from the video encoder thread as soon as
// the encoder is done with the frame; it does not mean that the encoded frame
// has been sent out.
// Once the encoded frame is ready the frame_encoded_callback is called.
virtual bool EncodeVideoFrame(
const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time,
const FrameEncodedCallback& frame_encoded_callback) OVERRIDE;
// The following functions are called from the main cast thread.
virtual void SetBitRate(int new_bit_rate) OVERRIDE;
virtual void SkipNextFrame(bool skip_next_frame) OVERRIDE;
virtual void GenerateKeyFrame() OVERRIDE;
virtual void LatestFrameIdToReference(uint32 frame_id) OVERRIDE;
virtual int NumberOfSkippedFrames() const OVERRIDE;
protected:
struct CodecDynamicConfig {
bool key_frame_requested;
uint32 latest_frame_id_to_reference;
int bit_rate;
};
// The actual encode, called from the video encoder thread.
void EncodeVideoFrameEncoderThread(
const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time,
const CodecDynamicConfig& dynamic_config,
const FrameEncodedCallback& frame_encoded_callback);
private:
const VideoSenderConfig video_config_;
scoped_refptr<CastEnvironment> cast_environment_;
scoped_ptr<Vp8Encoder> vp8_encoder_;
CodecDynamicConfig dynamic_config_;
bool skip_next_frame_;
int skip_count_;
DISALLOW_COPY_AND_ASSIGN(VideoEncoderImpl);
};
} // namespace cast
} // namespace media
#endif // MEDIA_CAST_VIDEO_SENDER_VIDEO_ENCODER_IMPL_H_
// Copyright 2013 The Chromium Authors. All rights reserved. // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "media/cast/cast_environment.h" #include "media/cast/cast_environment.h"
#include "media/cast/test/fake_task_runner.h" #include "media/cast/test/fake_task_runner.h"
#include "media/cast/test/video_utility.h" #include "media/cast/test/video_utility.h"
#include "media/cast/video_sender/video_encoder.h" #include "media/cast/video_sender/video_encoder_impl.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
namespace media { namespace media {
...@@ -58,9 +58,9 @@ class TestVideoEncoderCallback : ...@@ -58,9 +58,9 @@ class TestVideoEncoderCallback :
}; };
} // namespace } // namespace
class VideoEncoderTest : public ::testing::Test { class VideoEncoderImplTest : public ::testing::Test {
protected: protected:
VideoEncoderTest() VideoEncoderImplTest()
: test_video_encoder_callback_(new TestVideoEncoderCallback()) { : test_video_encoder_callback_(new TestVideoEncoderCallback()) {
video_config_.sender_ssrc = 1; video_config_.sender_ssrc = 1;
video_config_.incoming_feedback_ssrc = 2; video_config_.incoming_feedback_ssrc = 2;
...@@ -82,7 +82,7 @@ class VideoEncoderTest : public ::testing::Test { ...@@ -82,7 +82,7 @@ class VideoEncoderTest : public ::testing::Test {
PopulateVideoFrame(video_frame_, 123); PopulateVideoFrame(video_frame_, 123);
} }
virtual ~VideoEncoderTest() {} virtual ~VideoEncoderImplTest() {}
virtual void SetUp() { virtual void SetUp() {
task_runner_ = new test::FakeTaskRunner(&testing_clock_); task_runner_ = new test::FakeTaskRunner(&testing_clock_);
...@@ -92,9 +92,8 @@ class VideoEncoderTest : public ::testing::Test { ...@@ -92,9 +92,8 @@ class VideoEncoderTest : public ::testing::Test {
} }
void Configure(uint8 max_unacked_frames) { void Configure(uint8 max_unacked_frames) {
video_encoder_.reset(new VideoEncoder(cast_environment_, video_config_, video_encoder_.reset(new VideoEncoderImpl(cast_environment_, video_config_,
max_unacked_frames)); max_unacked_frames));
video_encoder_controller_ = video_encoder_.get();
} }
base::SimpleTestTickClock testing_clock_; base::SimpleTestTickClock testing_clock_;
...@@ -102,13 +101,12 @@ class VideoEncoderTest : public ::testing::Test { ...@@ -102,13 +101,12 @@ class VideoEncoderTest : public ::testing::Test {
VideoSenderConfig video_config_; VideoSenderConfig video_config_;
scoped_refptr<test::FakeTaskRunner> task_runner_; scoped_refptr<test::FakeTaskRunner> task_runner_;
scoped_ptr<VideoEncoder> video_encoder_; scoped_ptr<VideoEncoder> video_encoder_;
VideoEncoderController* video_encoder_controller_;
scoped_refptr<media::VideoFrame> video_frame_; scoped_refptr<media::VideoFrame> video_frame_;
scoped_refptr<CastEnvironment> cast_environment_; scoped_refptr<CastEnvironment> cast_environment_;
}; };
TEST_F(VideoEncoderTest, EncodePattern30fpsRunningOutOfAck) { TEST_F(VideoEncoderImplTest, EncodePattern30fpsRunningOutOfAck) {
Configure(3); Configure(3);
VideoEncoder::FrameEncodedCallback frame_encoded_callback = VideoEncoder::FrameEncodedCallback frame_encoded_callback =
...@@ -123,20 +121,20 @@ TEST_F(VideoEncoderTest, EncodePattern30fpsRunningOutOfAck) { ...@@ -123,20 +121,20 @@ TEST_F(VideoEncoderTest, EncodePattern30fpsRunningOutOfAck) {
task_runner_->RunTasks(); task_runner_->RunTasks();
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
video_encoder_controller_->LatestFrameIdToReference(0); video_encoder_->LatestFrameIdToReference(0);
test_video_encoder_callback_->SetExpectedResult(false, 1, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 1, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
video_encoder_controller_->LatestFrameIdToReference(1); video_encoder_->LatestFrameIdToReference(1);
test_video_encoder_callback_->SetExpectedResult(false, 2, 1, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 2, 1, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(2); video_encoder_->LatestFrameIdToReference(2);
for (int i = 3; i < 6; ++i) { for (int i = 3; i < 6; ++i) {
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
...@@ -149,7 +147,7 @@ TEST_F(VideoEncoderTest, EncodePattern30fpsRunningOutOfAck) { ...@@ -149,7 +147,7 @@ TEST_F(VideoEncoderTest, EncodePattern30fpsRunningOutOfAck) {
// TODO(pwestin): Re-enabled after redesign the encoder to control number of // TODO(pwestin): Re-enabled after redesign the encoder to control number of
// frames in flight. // frames in flight.
TEST_F(VideoEncoderTest,DISABLED_EncodePattern60fpsRunningOutOfAck) { TEST_F(VideoEncoderImplTest,DISABLED_EncodePattern60fpsRunningOutOfAck) {
video_config_.max_number_of_video_buffers_used = 1; video_config_.max_number_of_video_buffers_used = 1;
Configure(6); Configure(6);
...@@ -164,21 +162,21 @@ TEST_F(VideoEncoderTest,DISABLED_EncodePattern60fpsRunningOutOfAck) { ...@@ -164,21 +162,21 @@ TEST_F(VideoEncoderTest,DISABLED_EncodePattern60fpsRunningOutOfAck) {
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(0); video_encoder_->LatestFrameIdToReference(0);
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, 1, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 1, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(1); video_encoder_->LatestFrameIdToReference(1);
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, 2, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 2, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(2); video_encoder_->LatestFrameIdToReference(2);
for (int i = 3; i < 9; ++i) { for (int i = 3; i < 9; ++i) {
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
...@@ -191,7 +189,8 @@ TEST_F(VideoEncoderTest,DISABLED_EncodePattern60fpsRunningOutOfAck) { ...@@ -191,7 +189,8 @@ TEST_F(VideoEncoderTest,DISABLED_EncodePattern60fpsRunningOutOfAck) {
// TODO(pwestin): Re-enabled after redesign the encoder to control number of // TODO(pwestin): Re-enabled after redesign the encoder to control number of
// frames in flight. // frames in flight.
TEST_F(VideoEncoderTest, DISABLED_EncodePattern60fps200msDelayRunningOutOfAck) { TEST_F(VideoEncoderImplTest,
DISABLED_EncodePattern60fps200msDelayRunningOutOfAck) {
Configure(12); Configure(12);
base::TimeTicks capture_time; base::TimeTicks capture_time;
...@@ -205,35 +204,35 @@ TEST_F(VideoEncoderTest, DISABLED_EncodePattern60fps200msDelayRunningOutOfAck) { ...@@ -205,35 +204,35 @@ TEST_F(VideoEncoderTest, DISABLED_EncodePattern60fps200msDelayRunningOutOfAck) {
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(0); video_encoder_->LatestFrameIdToReference(0);
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, 1, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 1, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(1); video_encoder_->LatestFrameIdToReference(1);
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, 2, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 2, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(2); video_encoder_->LatestFrameIdToReference(2);
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, 3, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 3, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(3); video_encoder_->LatestFrameIdToReference(3);
capture_time += base::TimeDelta::FromMilliseconds(33); capture_time += base::TimeDelta::FromMilliseconds(33);
test_video_encoder_callback_->SetExpectedResult(false, 4, 0, capture_time); test_video_encoder_callback_->SetExpectedResult(false, 4, 0, capture_time);
EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time, EXPECT_TRUE(video_encoder_->EncodeVideoFrame(video_frame_, capture_time,
frame_encoded_callback)); frame_encoded_callback));
task_runner_->RunTasks(); task_runner_->RunTasks();
video_encoder_controller_->LatestFrameIdToReference(4); video_encoder_->LatestFrameIdToReference(4);
for (int i = 5; i < 17; ++i) { for (int i = 5; i < 17; ++i) {
test_video_encoder_callback_->SetExpectedResult(false, i, 4, capture_time); test_video_encoder_callback_->SetExpectedResult(false, i, 4, capture_time);
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
#include "crypto/symmetric_key.h" #include "crypto/symmetric_key.h"
#include "media/cast/cast_defines.h" #include "media/cast/cast_defines.h"
#include "media/cast/transport/pacing/paced_sender.h" #include "media/cast/transport/pacing/paced_sender.h"
#include "media/cast/video_sender/video_encoder.h" #include "media/cast/video_sender/external_video_encoder.h"
#include "media/cast/video_sender/video_encoder_impl.h"
namespace media { namespace media {
namespace cast { namespace cast {
...@@ -53,7 +54,7 @@ class LocalRtpVideoSenderStatistics : public RtpSenderStatistics { ...@@ -53,7 +54,7 @@ class LocalRtpVideoSenderStatistics : public RtpSenderStatistics {
VideoSender::VideoSender( VideoSender::VideoSender(
scoped_refptr<CastEnvironment> cast_environment, scoped_refptr<CastEnvironment> cast_environment,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
VideoEncoderController* const video_encoder_controller, const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
transport::PacedPacketSender* const paced_packet_sender) transport::PacedPacketSender* const paced_packet_sender)
: rtp_max_delay_( : rtp_max_delay_(
base::TimeDelta::FromMilliseconds(video_config.rtp_max_delay_ms)), base::TimeDelta::FromMilliseconds(video_config.rtp_max_delay_ms)),
...@@ -84,12 +85,11 @@ VideoSender::VideoSender( ...@@ -84,12 +85,11 @@ VideoSender::VideoSender(
new LocalRtpVideoSenderStatistics(rtp_sender_.get())); new LocalRtpVideoSenderStatistics(rtp_sender_.get()));
if (video_config.use_external_encoder) { if (video_config.use_external_encoder) {
DCHECK(video_encoder_controller) << "Invalid argument"; video_encoder_.reset(new ExternalVideoEncoder(cast_environment,
video_encoder_controller_ = video_encoder_controller; video_config, gpu_factories));
} else { } else {
video_encoder_.reset(new VideoEncoder(cast_environment, video_config, video_encoder_.reset(new VideoEncoderImpl(cast_environment, video_config,
max_unacked_frames_)); max_unacked_frames_));
video_encoder_controller_ = video_encoder_.get();
} }
if (video_config.aes_iv_mask.size() == kAesKeySize && if (video_config.aes_iv_mask.size() == kAesKeySize &&
...@@ -103,7 +103,7 @@ VideoSender::VideoSender( ...@@ -103,7 +103,7 @@ VideoSender::VideoSender(
std::string()); std::string());
} else if (video_config.aes_iv_mask.size() != 0 || } else if (video_config.aes_iv_mask.size() != 0 ||
video_config.aes_key.size() != 0) { video_config.aes_key.size() != 0) {
DCHECK(false) << "Invalid crypto configuration"; NOTREACHED() << "Invalid crypto configuration";
} }
rtcp_.reset(new Rtcp( rtcp_.reset(new Rtcp(
...@@ -147,17 +147,6 @@ void VideoSender::InsertRawVideoFrame( ...@@ -147,17 +147,6 @@ void VideoSender::InsertRawVideoFrame(
} }
} }
void VideoSender::InsertCodedVideoFrame(const EncodedVideoFrame* encoded_frame,
const base::TimeTicks& capture_time,
const base::Closure callback) {
DCHECK(!video_encoder_.get()) << "Invalid state";
DCHECK(encoded_frame) << "Invalid argument";
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
SendEncodedVideoFrame(encoded_frame, capture_time);
cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
}
void VideoSender::SendEncodedVideoFrameMainThread( void VideoSender::SendEncodedVideoFrameMainThread(
scoped_ptr<EncodedVideoFrame> video_frame, scoped_ptr<EncodedVideoFrame> video_frame,
const base::TimeTicks& capture_time) { const base::TimeTicks& capture_time) {
...@@ -312,7 +301,7 @@ void VideoSender::ResendCheck() { ...@@ -312,7 +301,7 @@ void VideoSender::ResendCheck() {
if (time_since_last_send > rtp_max_delay_) { if (time_since_last_send > rtp_max_delay_) {
if (last_acked_frame_id_ == -1) { if (last_acked_frame_id_ == -1) {
// We have not received any ack, send a key frame. // We have not received any ack, send a key frame.
video_encoder_controller_->GenerateKeyFrame(); video_encoder_->GenerateKeyFrame();
last_acked_frame_id_ = -1; last_acked_frame_id_ = -1;
last_sent_frame_id_ = -1; last_sent_frame_id_ = -1;
UpdateFramesInFlight(); UpdateFramesInFlight();
...@@ -349,7 +338,7 @@ void VideoSender::ScheduleNextSkippedFramesCheck() { ...@@ -349,7 +338,7 @@ void VideoSender::ScheduleNextSkippedFramesCheck() {
void VideoSender::SkippedFramesCheck() { void VideoSender::SkippedFramesCheck() {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
int skip_count = video_encoder_controller_->NumberOfSkippedFrames(); int skip_count = video_encoder_->NumberOfSkippedFrames();
if (skip_count - last_skip_count_ > if (skip_count - last_skip_count_ >
kSkippedFramesThreshold * max_frame_rate_) { kSkippedFramesThreshold * max_frame_rate_) {
// TODO(pwestin): Propagate this up to the application. // TODO(pwestin): Propagate this up to the application.
...@@ -381,14 +370,14 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { ...@@ -381,14 +370,14 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
int resend_frame = -1; int resend_frame = -1;
if (last_sent_frame_id_ == -1) return; if (last_sent_frame_id_ == -1) return;
video_encoder_controller_->LatestFrameIdToReference( video_encoder_->LatestFrameIdToReference(
cast_feedback.ack_frame_id_); cast_feedback.ack_frame_id_);
if (static_cast<uint32>(last_acked_frame_id_ + 1) == if (static_cast<uint32>(last_acked_frame_id_ + 1) ==
cast_feedback.ack_frame_id_) { cast_feedback.ack_frame_id_) {
uint32 new_bitrate = 0; uint32 new_bitrate = 0;
if (congestion_control_.OnAck(rtt, &new_bitrate)) { if (congestion_control_.OnAck(rtt, &new_bitrate)) {
video_encoder_controller_->SetBitRate(new_bitrate); video_encoder_->SetBitRate(new_bitrate);
} }
} }
if (static_cast<uint32>(last_acked_frame_id_) == cast_feedback.ack_frame_id_ if (static_cast<uint32>(last_acked_frame_id_) == cast_feedback.ack_frame_id_
...@@ -414,7 +403,7 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { ...@@ -414,7 +403,7 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
uint32 new_bitrate = 0; uint32 new_bitrate = 0;
if (congestion_control_.OnNack(rtt, &new_bitrate)) { if (congestion_control_.OnNack(rtt, &new_bitrate)) {
video_encoder_controller_->SetBitRate(new_bitrate); video_encoder_->SetBitRate(new_bitrate);
} }
} }
ReceivedAck(cast_feedback.ack_frame_id_); ReceivedAck(cast_feedback.ack_frame_id_);
...@@ -446,11 +435,11 @@ void VideoSender::UpdateFramesInFlight() { ...@@ -446,11 +435,11 @@ void VideoSender::UpdateFramesInFlight() {
VLOG(1) << "Frames in flight; last sent: " << last_sent_frame_id_ VLOG(1) << "Frames in flight; last sent: " << last_sent_frame_id_
<< " last acked:" << last_acked_frame_id_; << " last acked:" << last_acked_frame_id_;
if (frames_in_flight >= max_unacked_frames_) { if (frames_in_flight >= max_unacked_frames_) {
video_encoder_controller_->SkipNextFrame(true); video_encoder_->SkipNextFrame(true);
return; return;
} }
} }
video_encoder_controller_->SkipNextFrame(false); video_encoder_->SkipNextFrame(false);
} }
void VideoSender::ResendFrame(uint32 resend_frame_id) { void VideoSender::ResendFrame(uint32 resend_frame_id) {
......
...@@ -14,8 +14,11 @@ ...@@ -14,8 +14,11 @@
'<(DEPTH)/', '<(DEPTH)/',
], ],
'sources': [ 'sources': [
'external_video_encoder.h',
'external_video_encoder.cc',
'video_encoder.h', 'video_encoder.h',
'video_encoder.cc', 'video_encoder_impl.h',
'video_encoder_impl.cc',
'video_sender.h', 'video_sender.h',
'video_sender.cc', 'video_sender.cc',
], # source ], # source
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include "media/cast/congestion_control/congestion_control.h" #include "media/cast/congestion_control/congestion_control.h"
#include "media/cast/rtcp/rtcp.h" #include "media/cast/rtcp/rtcp.h"
#include "media/cast/transport/rtp_sender/rtp_sender.h" #include "media/cast/transport/rtp_sender/rtp_sender.h"
#include "media/filters/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator.h"
namespace crypto { namespace crypto {
class Encryptor; class Encryptor;
...@@ -46,7 +48,7 @@ class VideoSender : public base::NonThreadSafe, ...@@ -46,7 +48,7 @@ class VideoSender : public base::NonThreadSafe,
public: public:
VideoSender(scoped_refptr<CastEnvironment> cast_environment, VideoSender(scoped_refptr<CastEnvironment> cast_environment,
const VideoSenderConfig& video_config, const VideoSenderConfig& video_config,
VideoEncoderController* const video_encoder_controller, const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
transport::PacedPacketSender* const paced_packet_sender); transport::PacedPacketSender* const paced_packet_sender);
virtual ~VideoSender(); virtual ~VideoSender();
...@@ -59,14 +61,6 @@ class VideoSender : public base::NonThreadSafe, ...@@ -59,14 +61,6 @@ class VideoSender : public base::NonThreadSafe,
const scoped_refptr<media::VideoFrame>& video_frame, const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time); const base::TimeTicks& capture_time);
// The video_frame must be valid until the closure callback is called.
// The closure callback is called from the main thread as soon as
// the cast sender is done with the frame; it does not mean that the encoded
// frame has been sent out.
void InsertCodedVideoFrame(const EncodedVideoFrame* video_frame,
const base::TimeTicks& capture_time,
const base::Closure callback);
// Only called from the main cast thread. // Only called from the main cast thread.
void IncomingRtcpPacket(const uint8* packet, size_t length, void IncomingRtcpPacket(const uint8* packet, size_t length,
const base::Closure callback); const base::Closure callback);
...@@ -123,7 +117,6 @@ class VideoSender : public base::NonThreadSafe, ...@@ -123,7 +117,6 @@ class VideoSender : public base::NonThreadSafe,
scoped_ptr<VideoEncoder> video_encoder_; scoped_ptr<VideoEncoder> video_encoder_;
scoped_ptr<Rtcp> rtcp_; scoped_ptr<Rtcp> rtcp_;
scoped_ptr<transport::RtpSender> rtp_sender_; scoped_ptr<transport::RtpSender> rtp_sender_;
VideoEncoderController* video_encoder_controller_;
uint8 max_unacked_frames_; uint8 max_unacked_frames_;
scoped_ptr<crypto::Encryptor> encryptor_; scoped_ptr<crypto::Encryptor> encryptor_;
scoped_ptr<crypto::SymmetricKey> encryption_key_; scoped_ptr<crypto::SymmetricKey> encryption_key_;
......
...@@ -9,11 +9,11 @@ ...@@ -9,11 +9,11 @@
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/cast/cast_environment.h" #include "media/cast/cast_environment.h"
#include "media/cast/test/fake_gpu_video_accelerator_factories.h"
#include "media/cast/test/fake_task_runner.h" #include "media/cast/test/fake_task_runner.h"
#include "media/cast/test/video_utility.h" #include "media/cast/test/video_utility.h"
#include "media/cast/transport/pacing/mock_paced_packet_sender.h" #include "media/cast/transport/pacing/mock_paced_packet_sender.h"
#include "media/cast/transport/pacing/paced_sender.h" #include "media/cast/transport/pacing/paced_sender.h"
#include "media/cast/video_sender/mock_video_encoder_controller.h"
#include "media/cast/video_sender/video_sender.h" #include "media/cast/video_sender/video_sender.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -34,12 +34,13 @@ using testing::AtLeast; ...@@ -34,12 +34,13 @@ using testing::AtLeast;
namespace { namespace {
class PeerVideoSender : public VideoSender { class PeerVideoSender : public VideoSender {
public: public:
PeerVideoSender(scoped_refptr<CastEnvironment> cast_environment, PeerVideoSender(
const VideoSenderConfig& video_config, scoped_refptr<CastEnvironment> cast_environment,
VideoEncoderController* const video_encoder_controller, const VideoSenderConfig& video_config,
transport::PacedPacketSender* const paced_packet_sender) const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
: VideoSender(cast_environment, video_config, transport::PacedPacketSender* const paced_packet_sender)
video_encoder_controller, paced_packet_sender) { : VideoSender(cast_environment, video_config, gpu_factories,
paced_packet_sender) {
} }
using VideoSender::OnReceivedCastFeedback; using VideoSender::OnReceivedCastFeedback;
}; };
...@@ -73,7 +74,9 @@ class VideoSenderTest : public ::testing::Test { ...@@ -73,7 +74,9 @@ class VideoSenderTest : public ::testing::Test {
if (external) { if (external) {
video_sender_.reset(new PeerVideoSender(cast_environment_, video_sender_.reset(new PeerVideoSender(cast_environment_,
video_config, &mock_video_encoder_controller_, &mock_transport_)); video_config,
new test::FakeGpuVideoAcceleratorFactories(task_runner_),
&mock_transport_));
} else { } else {
video_sender_.reset(new PeerVideoSender(cast_environment_, video_config, video_sender_.reset(new PeerVideoSender(cast_environment_, video_config,
NULL, &mock_transport_)); NULL, &mock_transport_));
...@@ -96,7 +99,6 @@ class VideoSenderTest : public ::testing::Test { ...@@ -96,7 +99,6 @@ class VideoSenderTest : public ::testing::Test {
return video_frame; return video_frame;
} }
MockVideoEncoderController mock_video_encoder_controller_;
base::SimpleTestTickClock testing_clock_; base::SimpleTestTickClock testing_clock_;
transport::MockPacedPacketSender mock_transport_; transport::MockPacedPacketSender mock_transport_;
scoped_refptr<test::FakeTaskRunner> task_runner_; scoped_refptr<test::FakeTaskRunner> task_runner_;
...@@ -118,40 +120,27 @@ TEST_F(VideoSenderTest, BuiltInEncoder) { ...@@ -118,40 +120,27 @@ TEST_F(VideoSenderTest, BuiltInEncoder) {
TEST_F(VideoSenderTest, ExternalEncoder) { TEST_F(VideoSenderTest, ExternalEncoder) {
EXPECT_CALL(mock_transport_, SendPackets(_)).Times(1); EXPECT_CALL(mock_transport_, SendPackets(_)).Times(1);
EXPECT_CALL(mock_video_encoder_controller_, SkipNextFrame(false)).Times(1);
InitEncoder(true); InitEncoder(true);
task_runner_->RunTasks();
EncodedVideoFrame video_frame; scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
base::TimeTicks capture_time;
video_frame.codec = kVp8; base::TimeTicks capture_time;
video_frame.key_frame = true; video_sender_->InsertRawVideoFrame(video_frame, capture_time);
video_frame.frame_id = 0;
video_frame.last_referenced_frame_id = 0;
video_frame.data.insert(video_frame.data.begin(), 1000, kPixelValue);
video_sender_->InsertCodedVideoFrame(&video_frame, capture_time, task_runner_->RunTasks();
base::Bind(base::DoNothing));
} }
TEST_F(VideoSenderTest, RtcpTimer) { TEST_F(VideoSenderTest, RtcpTimer) {
EXPECT_CALL(mock_transport_, SendPackets(_)).Times(AtLeast(1)); EXPECT_CALL(mock_transport_, SendPackets(_)).Times(AtLeast(1));
EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).Times(1); EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).Times(1);
EXPECT_CALL(mock_video_encoder_controller_, InitEncoder(false);
SkipNextFrame(false)).Times(AtLeast(1));
InitEncoder(true);
EncodedVideoFrame video_frame;
base::TimeTicks capture_time;
video_frame.codec = kVp8; scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
video_frame.key_frame = true;
video_frame.frame_id = 0;
video_frame.last_referenced_frame_id = 0;
video_frame.data.insert(video_frame.data.begin(), 1000, kPixelValue);
video_sender_->InsertCodedVideoFrame(&video_frame, capture_time, base::TimeTicks capture_time;
base::Bind(base::DoNothing)); video_sender_->InsertRawVideoFrame(video_frame, capture_time);
task_runner_->RunTasks();
// Make sure that we send at least one RTCP packet. // Make sure that we send at least one RTCP packet.
base::TimeDelta max_rtcp_timeout = base::TimeDelta max_rtcp_timeout =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment