Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / media / cast / sender / h264_vt_encoder_unittest.cc
blob04f3d629da95b23a9d9f8786347b5eb691ddacfd
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.
5 #include <queue>
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/test/launcher/unit_test_launcher.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "base/test/test_suite.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/media.h"
15 #include "media/base/media_switches.h"
16 #include "media/cast/sender/h264_vt_encoder.h"
17 #include "media/cast/sender/video_frame_factory.h"
18 #include "media/cast/test/utility/default_config.h"
19 #include "media/cast/test/utility/video_utility.h"
20 #include "media/ffmpeg/ffmpeg_common.h"
21 #include "media/filters/ffmpeg_glue.h"
22 #include "media/filters/ffmpeg_video_decoder.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace {
27 const int kVideoWidth = 1280;
28 const int kVideoHeight = 720;
30 class MediaTestSuite : public base::TestSuite {
31 public:
32 MediaTestSuite(int argc, char** argv) : TestSuite(argc, argv) {}
33 ~MediaTestSuite() override {}
35 protected:
36 void Initialize() override;
39 void MediaTestSuite::Initialize() {
40 base::TestSuite::Initialize();
41 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
42 command_line->AppendSwitch(switches::kEnableInbandTextTracks);
43 media::InitializeMediaLibraryForTesting();
46 } // namespace
48 int main(int argc, char** argv) {
50 base::AtExitManager at_exit_manager;
51 CHECK(VideoToolboxGlue::Get())
52 << "VideoToolbox is not available. Requires OS X 10.8 or iOS 8.0.";
54 MediaTestSuite test_suite(argc, argv);
55 return base::LaunchUnitTests(
56 argc, argv,
57 base::Bind(&MediaTestSuite::Run, base::Unretained(&test_suite)));
60 namespace media {
61 namespace cast {
63 // See comment in end2end_unittest.cc for details on this value.
64 const double kVideoAcceptedPSNR = 38.0;
66 void SavePipelineStatus(PipelineStatus* out_status, PipelineStatus in_status) {
67 *out_status = in_status;
70 void SaveOperationalStatus(OperationalStatus* out_status,
71 OperationalStatus in_status) {
72 *out_status = in_status;
75 class MetadataRecorder : public base::RefCountedThreadSafe<MetadataRecorder> {
76 public:
77 MetadataRecorder() : count_frames_delivered_(0) {}
79 int count_frames_delivered() const { return count_frames_delivered_; }
81 void PushExpectation(uint32 expected_frame_id,
82 uint32 expected_last_referenced_frame_id,
83 uint32 expected_rtp_timestamp,
84 const base::TimeTicks& expected_reference_time) {
85 expectations_.push(Expectation{expected_frame_id,
86 expected_last_referenced_frame_id,
87 expected_rtp_timestamp,
88 expected_reference_time});
91 void CompareFrameWithExpected(scoped_ptr<EncodedFrame> encoded_frame) {
92 ASSERT_LT(0u, expectations_.size());
93 auto e = expectations_.front();
94 expectations_.pop();
95 if (e.expected_frame_id != e.expected_last_referenced_frame_id) {
96 EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
97 } else {
98 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
100 EXPECT_EQ(e.expected_frame_id, encoded_frame->frame_id);
101 EXPECT_EQ(e.expected_last_referenced_frame_id,
102 encoded_frame->referenced_frame_id)
103 << "frame id: " << e.expected_frame_id;
104 EXPECT_EQ(e.expected_rtp_timestamp, encoded_frame->rtp_timestamp);
105 EXPECT_EQ(e.expected_reference_time, encoded_frame->reference_time);
106 EXPECT_FALSE(encoded_frame->data.empty());
107 ++count_frames_delivered_;
110 private:
111 friend class base::RefCountedThreadSafe<MetadataRecorder>;
112 virtual ~MetadataRecorder() {}
114 int count_frames_delivered_;
116 struct Expectation {
117 uint32 expected_frame_id;
118 uint32 expected_last_referenced_frame_id;
119 uint32 expected_rtp_timestamp;
120 base::TimeTicks expected_reference_time;
122 std::queue<Expectation> expectations_;
124 DISALLOW_COPY_AND_ASSIGN(MetadataRecorder);
127 class EndToEndFrameChecker
128 : public base::RefCountedThreadSafe<EndToEndFrameChecker> {
129 public:
130 explicit EndToEndFrameChecker(const VideoDecoderConfig& config)
131 : decoder_(base::MessageLoop::current()->task_runner()),
132 count_frames_checked_(0) {
133 PipelineStatus pipeline_status;
134 decoder_.Initialize(
135 config, false, base::Bind(&SavePipelineStatus, &pipeline_status),
136 base::Bind(&EndToEndFrameChecker::CompareFrameWithExpected,
137 base::Unretained(this)));
138 base::MessageLoop::current()->RunUntilIdle();
139 EXPECT_EQ(PIPELINE_OK, pipeline_status);
142 void PushExpectation(const scoped_refptr<VideoFrame>& frame) {
143 expectations_.push(frame);
146 void EncodeDone(scoped_ptr<EncodedFrame> encoded_frame) {
147 auto buffer = DecoderBuffer::CopyFrom(encoded_frame->bytes(),
148 encoded_frame->data.size());
149 decoder_.Decode(buffer, base::Bind(&EndToEndFrameChecker::DecodeDone,
150 base::Unretained(this)));
153 void CompareFrameWithExpected(const scoped_refptr<VideoFrame>& frame) {
154 ASSERT_LT(0u, expectations_.size());
155 auto& e = expectations_.front();
156 expectations_.pop();
157 EXPECT_LE(kVideoAcceptedPSNR, I420PSNR(e, frame));
158 ++count_frames_checked_;
161 void DecodeDone(VideoDecoder::Status status) {
162 EXPECT_EQ(VideoDecoder::kOk, status);
165 int count_frames_checked() const { return count_frames_checked_; }
167 private:
168 friend class base::RefCountedThreadSafe<EndToEndFrameChecker>;
169 virtual ~EndToEndFrameChecker() {}
171 FFmpegVideoDecoder decoder_;
172 std::queue<scoped_refptr<VideoFrame>> expectations_;
173 int count_frames_checked_;
175 DISALLOW_COPY_AND_ASSIGN(EndToEndFrameChecker);
178 void CreateFrameAndMemsetPlane(VideoFrameFactory* const video_frame_factory) {
179 const scoped_refptr<media::VideoFrame> video_frame =
180 video_frame_factory->MaybeCreateFrame(
181 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta());
182 ASSERT_TRUE(video_frame.get());
183 auto cv_pixel_buffer = video_frame->cv_pixel_buffer();
184 ASSERT_TRUE(cv_pixel_buffer);
185 CVPixelBufferLockBaseAddress(cv_pixel_buffer, 0);
186 auto ptr = CVPixelBufferGetBaseAddressOfPlane(cv_pixel_buffer, 0);
187 ASSERT_TRUE(ptr);
188 memset(ptr, 0xfe, CVPixelBufferGetBytesPerRowOfPlane(cv_pixel_buffer, 0) *
189 CVPixelBufferGetHeightOfPlane(cv_pixel_buffer, 0));
190 CVPixelBufferUnlockBaseAddress(cv_pixel_buffer, 0);
193 class H264VideoToolboxEncoderTest : public ::testing::Test {
194 protected:
195 H264VideoToolboxEncoderTest()
196 : operational_status_(STATUS_UNINITIALIZED) {
197 frame_->set_timestamp(base::TimeDelta());
200 void SetUp() override {
201 clock_ = new base::SimpleTestTickClock();
202 clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
204 cast_environment_ = new CastEnvironment(
205 scoped_ptr<base::TickClock>(clock_).Pass(),
206 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(),
207 message_loop_.message_loop_proxy());
208 encoder_.reset(new H264VideoToolboxEncoder(
209 cast_environment_,
210 video_sender_config_,
211 gfx::Size(kVideoWidth, kVideoHeight),
213 base::Bind(&SaveOperationalStatus, &operational_status_)));
214 message_loop_.RunUntilIdle();
215 EXPECT_EQ(STATUS_INITIALIZED, operational_status_);
218 void TearDown() override {
219 encoder_.reset();
220 message_loop_.RunUntilIdle();
223 void AdvanceClockAndVideoFrameTimestamp() {
224 clock_->Advance(base::TimeDelta::FromMilliseconds(33));
225 frame_->set_timestamp(frame_->timestamp() +
226 base::TimeDelta::FromMilliseconds(33));
229 static void SetUpTestCase() {
230 // Reusable test data.
231 video_sender_config_ = GetDefaultVideoSenderConfig();
232 video_sender_config_.codec = CODEC_VIDEO_H264;
233 const gfx::Size size(kVideoWidth, kVideoHeight);
234 frame_ = media::VideoFrame::CreateFrame(
235 VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
236 PopulateVideoFrame(frame_.get(), 123);
239 static void TearDownTestCase() { frame_ = nullptr; }
241 static scoped_refptr<media::VideoFrame> frame_;
242 static VideoSenderConfig video_sender_config_;
244 base::SimpleTestTickClock* clock_; // Owned by CastEnvironment.
245 base::MessageLoop message_loop_;
246 scoped_refptr<CastEnvironment> cast_environment_;
247 scoped_ptr<VideoEncoder> encoder_;
248 OperationalStatus operational_status_;
250 private:
251 DISALLOW_COPY_AND_ASSIGN(H264VideoToolboxEncoderTest);
254 // static
255 scoped_refptr<media::VideoFrame> H264VideoToolboxEncoderTest::frame_;
256 VideoSenderConfig H264VideoToolboxEncoderTest::video_sender_config_;
258 TEST_F(H264VideoToolboxEncoderTest, CheckFrameMetadataSequence) {
259 scoped_refptr<MetadataRecorder> metadata_recorder(new MetadataRecorder());
260 VideoEncoder::FrameEncodedCallback cb = base::Bind(
261 &MetadataRecorder::CompareFrameWithExpected, metadata_recorder.get());
263 metadata_recorder->PushExpectation(
264 0, 0, TimeDeltaToRtpDelta(frame_->timestamp(), kVideoFrequency),
265 clock_->NowTicks());
266 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
267 message_loop_.RunUntilIdle();
269 for (uint32 frame_id = 1; frame_id < 10; ++frame_id) {
270 AdvanceClockAndVideoFrameTimestamp();
271 metadata_recorder->PushExpectation(
272 frame_id, frame_id - 1,
273 TimeDeltaToRtpDelta(frame_->timestamp(), kVideoFrequency),
274 clock_->NowTicks());
275 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
278 encoder_.reset();
279 message_loop_.RunUntilIdle();
281 EXPECT_EQ(10, metadata_recorder->count_frames_delivered());
284 #if defined(USE_PROPRIETARY_CODECS)
285 TEST_F(H264VideoToolboxEncoderTest, CheckFramesAreDecodable) {
286 VideoDecoderConfig config(kCodecH264, H264PROFILE_MAIN, frame_->format(),
287 frame_->coded_size(), frame_->visible_rect(),
288 frame_->natural_size(), nullptr, 0, false);
289 scoped_refptr<EndToEndFrameChecker> checker(new EndToEndFrameChecker(config));
291 VideoEncoder::FrameEncodedCallback cb =
292 base::Bind(&EndToEndFrameChecker::EncodeDone, checker.get());
293 for (uint32 frame_id = 0; frame_id < 6; ++frame_id) {
294 checker->PushExpectation(frame_);
295 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
296 AdvanceClockAndVideoFrameTimestamp();
299 encoder_.reset();
300 message_loop_.RunUntilIdle();
302 EXPECT_EQ(5, checker->count_frames_checked());
304 #endif
306 TEST_F(H264VideoToolboxEncoderTest, CheckVideoFrameFactory) {
307 auto video_frame_factory = encoder_->CreateVideoFrameFactory();
308 ASSERT_TRUE(video_frame_factory.get());
309 CreateFrameAndMemsetPlane(video_frame_factory.get());
310 // TODO(jfroy): Need to test that the encoder can encode VideoFrames provided
311 // by the VideoFrameFactory.
312 encoder_.reset();
313 message_loop_.RunUntilIdle();
314 CreateFrameAndMemsetPlane(video_frame_factory.get());
317 } // namespace cast
318 } // namespace media