1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <vector> 6 7 #include "base/bind.h" 8 #include "base/memory/ref_counted.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "media/base/video_frame.h" 11 #include "media/cast/cast_defines.h" 12 #include "media/cast/cast_environment.h" 13 #include "media/cast/sender/external_video_encoder.h" 14 #include "media/cast/test/fake_single_thread_task_runner.h" 15 #include "media/cast/test/fake_video_encode_accelerator.h" 16 #include "media/cast/test/utility/video_utility.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 19 namespace media { 20 namespace cast { 21 22 using testing::_; 23 24 namespace { 25 26 void IgnoreInitializationStatus(CastInitializationStatus status) {} 27 28 class VEAFactory { 29 public: 30 VEAFactory(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 31 scoped_ptr<VideoEncodeAccelerator> vea) 32 : task_runner_(task_runner), vea_(vea.Pass()) {} 33 34 void CreateVideoEncodeAccelerator( 35 const ReceiveVideoEncodeAcceleratorCallback& callback) { 36 create_cb_ = callback; 37 } 38 39 void FinishCreatingVideoEncodeAccelerator() { 40 create_cb_.Run(task_runner_, vea_.Pass()); 41 } 42 43 private: 44 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 45 scoped_ptr<VideoEncodeAccelerator> vea_; 46 ReceiveVideoEncodeAcceleratorCallback create_cb_; 47 }; 48 49 void CreateSharedMemory( 50 size_t size, const ReceiveVideoEncodeMemoryCallback& callback) { 51 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); 52 if (!shm->CreateAndMapAnonymous(size)) { 53 NOTREACHED(); 54 return; 55 } 56 callback.Run(shm.Pass()); 57 } 58 59 class TestVideoEncoderCallback 60 : public base::RefCountedThreadSafe<TestVideoEncoderCallback> { 61 public: 62 TestVideoEncoderCallback() {} 63 64 void SetExpectedResult(uint32 expected_frame_id, 65 uint32 expected_last_referenced_frame_id, 66 const base::TimeTicks& expected_capture_time) { 67 expected_frame_id_ = expected_frame_id; 68 expected_last_referenced_frame_id_ = expected_last_referenced_frame_id; 69 expected_capture_time_ = expected_capture_time; 70 } 71 72 void DeliverEncodedVideoFrame( 73 scoped_ptr<EncodedFrame> encoded_frame) { 74 if (expected_frame_id_ == expected_last_referenced_frame_id_) { 75 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency); 76 } else { 77 EXPECT_EQ(EncodedFrame::DEPENDENT, 78 encoded_frame->dependency); 79 } 80 EXPECT_EQ(expected_frame_id_, encoded_frame->frame_id); 81 EXPECT_EQ(expected_last_referenced_frame_id_, 82 encoded_frame->referenced_frame_id); 83 EXPECT_EQ(expected_capture_time_, encoded_frame->reference_time); 84 } 85 86 protected: 87 virtual ~TestVideoEncoderCallback() {} 88 89 private: 90 friend class base::RefCountedThreadSafe<TestVideoEncoderCallback>; 91 92 bool expected_key_frame_; 93 uint32 expected_frame_id_; 94 uint32 expected_last_referenced_frame_id_; 95 base::TimeTicks expected_capture_time_; 96 97 DISALLOW_COPY_AND_ASSIGN(TestVideoEncoderCallback); 98 }; 99 } // namespace 100 101 class ExternalVideoEncoderTest : public ::testing::Test { 102 protected: 103 ExternalVideoEncoderTest() 104 : test_video_encoder_callback_(new TestVideoEncoderCallback()) { 105 video_config_.ssrc = 1; 106 video_config_.incoming_feedback_ssrc = 2; 107 video_config_.rtp_payload_type = 127; 108 video_config_.use_external_encoder = true; 109 video_config_.width = 320; 110 video_config_.height = 240; 111 video_config_.max_bitrate = 5000000; 112 video_config_.min_bitrate = 1000000; 113 video_config_.start_bitrate = 2000000; 114 video_config_.max_qp = 56; 115 video_config_.min_qp = 0; 116 video_config_.max_frame_rate = 30; 117 video_config_.max_number_of_video_buffers_used = 3; 118 video_config_.codec = CODEC_VIDEO_VP8; 119 gfx::Size size(video_config_.width, video_config_.height); 120 video_frame_ = media::VideoFrame::CreateFrame( 121 VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta()); 122 PopulateVideoFrame(video_frame_.get(), 123); 123 124 testing_clock_ = new base::SimpleTestTickClock(); 125 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); 126 cast_environment_ = 127 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(), 128 task_runner_, 129 task_runner_, 130 task_runner_); 131 132 fake_vea_ = new test::FakeVideoEncodeAccelerator(task_runner_, 133 &stored_bitrates_); 134 scoped_ptr<VideoEncodeAccelerator> fake_vea(fake_vea_); 135 VEAFactory vea_factory(task_runner_, fake_vea.Pass()); 136 video_encoder_.reset(new ExternalVideoEncoder( 137 cast_environment_, 138 video_config_, 139 base::Bind(&IgnoreInitializationStatus), 140 base::Bind(&VEAFactory::CreateVideoEncodeAccelerator, 141 base::Unretained(&vea_factory)), 142 base::Bind(&CreateSharedMemory))); 143 vea_factory.FinishCreatingVideoEncodeAccelerator(); 144 } 145 146 virtual ~ExternalVideoEncoderTest() {} 147 148 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. 149 test::FakeVideoEncodeAccelerator* fake_vea_; // Owned by video_encoder_. 150 std::vector<uint32> stored_bitrates_; 151 scoped_refptr<TestVideoEncoderCallback> test_video_encoder_callback_; 152 VideoSenderConfig video_config_; 153 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; 154 scoped_ptr<VideoEncoder> video_encoder_; 155 scoped_refptr<media::VideoFrame> video_frame_; 156 scoped_refptr<CastEnvironment> cast_environment_; 157 158 DISALLOW_COPY_AND_ASSIGN(ExternalVideoEncoderTest); 159 }; 160 161 TEST_F(ExternalVideoEncoderTest, EncodePattern30fpsRunningOutOfAck) { 162 task_runner_->RunTasks(); // Run the initializer on the correct thread. 163 164 VideoEncoder::FrameEncodedCallback frame_encoded_callback = 165 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame, 166 test_video_encoder_callback_.get()); 167 168 base::TimeTicks capture_time; 169 capture_time += base::TimeDelta::FromMilliseconds(33); 170 test_video_encoder_callback_->SetExpectedResult(0, 0, capture_time); 171 video_encoder_->SetBitRate(2000); 172 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 173 video_frame_, capture_time, frame_encoded_callback)); 174 task_runner_->RunTasks(); 175 176 for (int i = 0; i < 6; ++i) { 177 capture_time += base::TimeDelta::FromMilliseconds(33); 178 test_video_encoder_callback_->SetExpectedResult(i + 1, i, capture_time); 179 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 180 video_frame_, capture_time, frame_encoded_callback)); 181 task_runner_->RunTasks(); 182 } 183 // We need to run the task to cleanup the GPU instance. 184 video_encoder_.reset(NULL); 185 task_runner_->RunTasks(); 186 187 ASSERT_EQ(1u, stored_bitrates_.size()); 188 EXPECT_EQ(2000u, stored_bitrates_[0]); 189 } 190 191 TEST_F(ExternalVideoEncoderTest, StreamHeader) { 192 task_runner_->RunTasks(); // Run the initializer on the correct thread. 193 194 VideoEncoder::FrameEncodedCallback frame_encoded_callback = 195 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame, 196 test_video_encoder_callback_.get()); 197 198 // Force the FakeVideoEncodeAccelerator to return a dummy non-key frame first. 199 fake_vea_->SendDummyFrameForTesting(false); 200 201 // Verify the first returned bitstream buffer is still a key frame. 202 base::TimeTicks capture_time; 203 capture_time += base::TimeDelta::FromMilliseconds(33); 204 test_video_encoder_callback_->SetExpectedResult(0, 0, capture_time); 205 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 206 video_frame_, capture_time, frame_encoded_callback)); 207 task_runner_->RunTasks(); 208 209 // We need to run the task to cleanup the GPU instance. 210 video_encoder_.reset(NULL); 211 task_runner_->RunTasks(); 212 } 213 214 // Verify that everything goes well even if ExternalVideoEncoder is destroyed 215 // before it has a chance to receive the VEA creation callback. 216 TEST(ExternalVideoEncoderEarlyDestroyTest, DestroyBeforeVEACreatedCallback) { 217 VideoSenderConfig video_config; 218 base::SimpleTestTickClock* testing_clock = new base::SimpleTestTickClock(); 219 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner( 220 new test::FakeSingleThreadTaskRunner(testing_clock)); 221 scoped_refptr<CastEnvironment> cast_environment( 222 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock).Pass(), 223 task_runner, 224 task_runner, 225 task_runner)); 226 227 std::vector<uint32> stored_bitrates; 228 scoped_ptr<VideoEncodeAccelerator> fake_vea( 229 new test::FakeVideoEncodeAccelerator(task_runner, &stored_bitrates)); 230 VEAFactory vea_factory(task_runner, fake_vea.Pass()); 231 232 scoped_ptr<ExternalVideoEncoder> video_encoder(new ExternalVideoEncoder( 233 cast_environment, 234 video_config, 235 base::Bind(&IgnoreInitializationStatus), 236 base::Bind(&VEAFactory::CreateVideoEncodeAccelerator, 237 base::Unretained(&vea_factory)), 238 base::Bind(&CreateSharedMemory))); 239 240 video_encoder.reset(); 241 vea_factory.FinishCreatingVideoEncodeAccelerator(); 242 task_runner->RunTasks(); 243 } 244 245 } // namespace cast 246 } // namespace media 247