Remove INJECT_EVENTS permissions from test APKs.
[chromium-blink-merge.git] / media / cast / sender / video_sender_unittest.cc
blob8100b22e556188f251a546d383678ef25b256591
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 <stdint.h>
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "media/base/video_frame.h"
13 #include "media/cast/cast_environment.h"
14 #include "media/cast/logging/simple_event_subscriber.h"
15 #include "media/cast/net/cast_transport_config.h"
16 #include "media/cast/net/cast_transport_sender_impl.h"
17 #include "media/cast/net/pacing/paced_sender.h"
18 #include "media/cast/sender/fake_video_encode_accelerator_factory.h"
19 #include "media/cast/sender/video_frame_factory.h"
20 #include "media/cast/sender/video_sender.h"
21 #include "media/cast/test/fake_single_thread_task_runner.h"
22 #include "media/cast/test/utility/default_config.h"
23 #include "media/cast/test/utility/video_utility.h"
24 #include "media/video/fake_video_encode_accelerator.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace media {
29 namespace cast {
31 namespace {
32 static const uint8 kPixelValue = 123;
33 static const int kWidth = 320;
34 static const int kHeight = 240;
36 using testing::_;
37 using testing::AtLeast;
40 void SaveOperationalStatus(OperationalStatus* out_status,
41 OperationalStatus in_status) {
42 DVLOG(1) << "OperationalStatus transitioning from " << *out_status << " to "
43 << in_status;
44 *out_status = in_status;
47 class TestPacketSender : public PacketSender {
48 public:
49 TestPacketSender()
50 : number_of_rtp_packets_(0),
51 number_of_rtcp_packets_(0),
52 paused_(false) {}
54 // A singular packet implies a RTCP packet.
55 bool SendPacket(PacketRef packet, const base::Closure& cb) final {
56 if (paused_) {
57 stored_packet_ = packet;
58 callback_ = cb;
59 return false;
61 if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
62 ++number_of_rtcp_packets_;
63 } else {
64 // Check that at least one RTCP packet was sent before the first RTP
65 // packet. This confirms that the receiver will have the necessary lip
66 // sync info before it has to calculate the playout time of the first
67 // frame.
68 if (number_of_rtp_packets_ == 0)
69 EXPECT_LE(1, number_of_rtcp_packets_);
70 ++number_of_rtp_packets_;
72 return true;
75 int64 GetBytesSent() final { return 0; }
77 int number_of_rtp_packets() const { return number_of_rtp_packets_; }
79 int number_of_rtcp_packets() const { return number_of_rtcp_packets_; }
81 void SetPause(bool paused) {
82 paused_ = paused;
83 if (!paused && stored_packet_.get()) {
84 SendPacket(stored_packet_, callback_);
85 callback_.Run();
89 private:
90 int number_of_rtp_packets_;
91 int number_of_rtcp_packets_;
92 bool paused_;
93 base::Closure callback_;
94 PacketRef stored_packet_;
96 DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
99 void IgnorePlayoutDelayChanges(base::TimeDelta unused_playout_delay) {
102 class PeerVideoSender : public VideoSender {
103 public:
104 PeerVideoSender(
105 scoped_refptr<CastEnvironment> cast_environment,
106 const VideoSenderConfig& video_config,
107 const StatusChangeCallback& status_change_cb,
108 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
109 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
110 CastTransportSender* const transport_sender)
111 : VideoSender(cast_environment,
112 video_config,
113 status_change_cb,
114 create_vea_cb,
115 create_video_encode_mem_cb,
116 transport_sender,
117 base::Bind(&IgnorePlayoutDelayChanges)) {}
118 using VideoSender::OnReceivedCastFeedback;
120 } // namespace
122 class VideoSenderTest : public ::testing::Test {
123 protected:
124 VideoSenderTest()
125 : testing_clock_(new base::SimpleTestTickClock()),
126 task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
127 cast_environment_(new CastEnvironment(
128 scoped_ptr<base::TickClock>(testing_clock_).Pass(),
129 task_runner_,
130 task_runner_,
131 task_runner_)),
132 operational_status_(STATUS_UNINITIALIZED),
133 vea_factory_(task_runner_) {
134 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
135 vea_factory_.SetAutoRespond(true);
136 last_pixel_value_ = kPixelValue;
137 net::IPEndPoint dummy_endpoint;
138 transport_sender_.reset(new CastTransportSenderImpl(
139 NULL,
140 testing_clock_,
141 dummy_endpoint,
142 dummy_endpoint,
143 make_scoped_ptr(new base::DictionaryValue),
144 base::Bind(&UpdateCastTransportStatus),
145 BulkRawEventsCallback(),
146 base::TimeDelta(),
147 task_runner_,
148 PacketReceiverCallback(),
149 &transport_));
152 ~VideoSenderTest() override {}
154 void TearDown() final {
155 video_sender_.reset();
156 task_runner_->RunTasks();
159 static void UpdateCastTransportStatus(CastTransportStatus status) {
160 EXPECT_EQ(TRANSPORT_VIDEO_INITIALIZED, status);
163 // If |external| is true then external video encoder (VEA) is used.
164 // |expect_init_sucess| is true if initialization is expected to succeed.
165 void InitEncoder(bool external, bool expect_init_success) {
166 VideoSenderConfig video_config = GetDefaultVideoSenderConfig();
167 video_config.use_external_encoder = external;
169 ASSERT_EQ(operational_status_, STATUS_UNINITIALIZED);
171 if (external) {
172 vea_factory_.SetInitializationWillSucceed(expect_init_success);
173 video_sender_.reset(new PeerVideoSender(
174 cast_environment_,
175 video_config,
176 base::Bind(&SaveOperationalStatus, &operational_status_),
177 base::Bind(
178 &FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator,
179 base::Unretained(&vea_factory_)),
180 base::Bind(&FakeVideoEncodeAcceleratorFactory::CreateSharedMemory,
181 base::Unretained(&vea_factory_)),
182 transport_sender_.get()));
183 } else {
184 video_sender_.reset(new PeerVideoSender(
185 cast_environment_,
186 video_config,
187 base::Bind(&SaveOperationalStatus, &operational_status_),
188 CreateDefaultVideoEncodeAcceleratorCallback(),
189 CreateDefaultVideoEncodeMemoryCallback(),
190 transport_sender_.get()));
192 task_runner_->RunTasks();
195 scoped_refptr<media::VideoFrame> GetNewVideoFrame() {
196 if (first_frame_timestamp_.is_null())
197 first_frame_timestamp_ = testing_clock_->NowTicks();
198 gfx::Size size(kWidth, kHeight);
199 scoped_refptr<media::VideoFrame> video_frame =
200 media::VideoFrame::CreateFrame(
201 VideoFrame::I420, size, gfx::Rect(size), size,
202 testing_clock_->NowTicks() - first_frame_timestamp_);
203 PopulateVideoFrame(video_frame.get(), last_pixel_value_++);
204 return video_frame;
207 scoped_refptr<media::VideoFrame> GetLargeNewVideoFrame() {
208 if (first_frame_timestamp_.is_null())
209 first_frame_timestamp_ = testing_clock_->NowTicks();
210 gfx::Size size(kWidth, kHeight);
211 scoped_refptr<media::VideoFrame> video_frame =
212 media::VideoFrame::CreateFrame(
213 VideoFrame::I420, size, gfx::Rect(size), size,
214 testing_clock_->NowTicks() - first_frame_timestamp_);
215 PopulateVideoFrameWithNoise(video_frame.get());
216 return video_frame;
219 void RunTasks(int during_ms) {
220 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(during_ms));
223 base::SimpleTestTickClock* const testing_clock_; // Owned by CastEnvironment.
224 const scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
225 const scoped_refptr<CastEnvironment> cast_environment_;
226 OperationalStatus operational_status_;
227 FakeVideoEncodeAcceleratorFactory vea_factory_;
228 TestPacketSender transport_;
229 scoped_ptr<CastTransportSenderImpl> transport_sender_;
230 scoped_ptr<PeerVideoSender> video_sender_;
231 int last_pixel_value_;
232 base::TimeTicks first_frame_timestamp_;
234 DISALLOW_COPY_AND_ASSIGN(VideoSenderTest);
237 TEST_F(VideoSenderTest, BuiltInEncoder) {
238 InitEncoder(false, true);
239 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
241 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
243 const base::TimeTicks reference_time = testing_clock_->NowTicks();
244 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
246 task_runner_->RunTasks();
247 EXPECT_LE(1, transport_.number_of_rtp_packets());
248 EXPECT_LE(1, transport_.number_of_rtcp_packets());
251 TEST_F(VideoSenderTest, ExternalEncoder) {
252 InitEncoder(true, true);
253 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
255 // The SizeAdaptableExternalVideoEncoder initally reports STATUS_INITIALIZED
256 // so that frames will be sent to it. Therefore, no encoder activity should
257 // have occurred at this point. Send a frame to spurn creation of the
258 // underlying ExternalVideoEncoder instance.
259 if (vea_factory_.vea_response_count() == 0) {
260 video_sender_->InsertRawVideoFrame(GetNewVideoFrame(),
261 testing_clock_->NowTicks());
262 task_runner_->RunTasks();
264 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
265 RunTasks(33);
267 // VideoSender created an encoder for 1280x720 frames, in order to provide the
268 // INITIALIZED status.
269 EXPECT_EQ(1, vea_factory_.vea_response_count());
270 EXPECT_EQ(3, vea_factory_.shm_response_count());
272 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
274 for (int i = 0; i < 3; ++i) {
275 const base::TimeTicks reference_time = testing_clock_->NowTicks();
276 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
277 RunTasks(33);
278 // VideoSender re-created the encoder for the 320x240 frames we're
279 // providing.
280 EXPECT_EQ(1, vea_factory_.vea_response_count());
281 EXPECT_EQ(3, vea_factory_.shm_response_count());
284 video_sender_.reset(NULL);
285 task_runner_->RunTasks();
286 EXPECT_EQ(1, vea_factory_.vea_response_count());
287 EXPECT_EQ(3, vea_factory_.shm_response_count());
290 TEST_F(VideoSenderTest, ExternalEncoderInitFails) {
291 InitEncoder(true, false);
293 // The SizeAdaptableExternalVideoEncoder initally reports STATUS_INITIALIZED
294 // so that frames will be sent to it. Send a frame to spurn creation of the
295 // underlying ExternalVideoEncoder instance, which should result in failure.
296 if (operational_status_ == STATUS_INITIALIZED ||
297 operational_status_ == STATUS_CODEC_REINIT_PENDING) {
298 video_sender_->InsertRawVideoFrame(GetNewVideoFrame(),
299 testing_clock_->NowTicks());
300 task_runner_->RunTasks();
302 EXPECT_EQ(STATUS_CODEC_INIT_FAILED, operational_status_);
304 video_sender_.reset(NULL);
305 task_runner_->RunTasks();
308 TEST_F(VideoSenderTest, RtcpTimer) {
309 InitEncoder(false, true);
310 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
312 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
314 const base::TimeTicks reference_time = testing_clock_->NowTicks();
315 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
317 // Make sure that we send at least one RTCP packet.
318 base::TimeDelta max_rtcp_timeout =
319 base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2);
321 RunTasks(max_rtcp_timeout.InMilliseconds());
322 EXPECT_LE(1, transport_.number_of_rtp_packets());
323 EXPECT_LE(1, transport_.number_of_rtcp_packets());
324 // Build Cast msg and expect RTCP packet.
325 RtcpCastMessage cast_feedback(1);
326 cast_feedback.media_ssrc = 2;
327 cast_feedback.ack_frame_id = 0;
328 video_sender_->OnReceivedCastFeedback(cast_feedback);
329 RunTasks(max_rtcp_timeout.InMilliseconds());
330 EXPECT_LE(1, transport_.number_of_rtcp_packets());
333 TEST_F(VideoSenderTest, ResendTimer) {
334 InitEncoder(false, true);
335 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
337 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
339 const base::TimeTicks reference_time = testing_clock_->NowTicks();
340 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
342 // ACK the key frame.
343 RtcpCastMessage cast_feedback(1);
344 cast_feedback.media_ssrc = 2;
345 cast_feedback.ack_frame_id = 0;
346 video_sender_->OnReceivedCastFeedback(cast_feedback);
348 video_frame = GetNewVideoFrame();
349 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
351 base::TimeDelta max_resend_timeout =
352 base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs);
354 // Make sure that we do a re-send.
355 RunTasks(max_resend_timeout.InMilliseconds());
356 // Should have sent at least 3 packets.
357 EXPECT_LE(
359 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
362 TEST_F(VideoSenderTest, LogAckReceivedEvent) {
363 InitEncoder(false, true);
364 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
366 SimpleEventSubscriber event_subscriber;
367 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
369 int num_frames = 10;
370 for (int i = 0; i < num_frames; i++) {
371 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
373 const base::TimeTicks reference_time = testing_clock_->NowTicks();
374 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
375 RunTasks(33);
378 task_runner_->RunTasks();
380 RtcpCastMessage cast_feedback(1);
381 cast_feedback.ack_frame_id = num_frames - 1;
383 video_sender_->OnReceivedCastFeedback(cast_feedback);
385 std::vector<FrameEvent> frame_events;
386 event_subscriber.GetFrameEventsAndReset(&frame_events);
388 ASSERT_TRUE(!frame_events.empty());
389 EXPECT_EQ(FRAME_ACK_RECEIVED, frame_events.rbegin()->type);
390 EXPECT_EQ(VIDEO_EVENT, frame_events.rbegin()->media_type);
391 EXPECT_EQ(num_frames - 1u, frame_events.rbegin()->frame_id);
393 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
396 TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
397 InitEncoder(false, true);
398 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
400 // Send a stream of frames and don't ACK; by default we shouldn't have more
401 // than 4 frames in flight.
402 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
403 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
404 RunTasks(33);
406 // Send 3 more frames and record the number of packets sent.
407 for (int i = 0; i < 3; ++i) {
408 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
409 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
410 RunTasks(33);
412 const int number_of_packets_sent = transport_.number_of_rtp_packets();
414 // Send 3 more frames - they should not be encoded, as we have not received
415 // any acks.
416 for (int i = 0; i < 3; ++i) {
417 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
418 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
419 RunTasks(33);
422 // We expect a frame to be retransmitted because of duplicated ACKs.
423 // Only one packet of the frame is re-transmitted.
424 EXPECT_EQ(number_of_packets_sent + 1,
425 transport_.number_of_rtp_packets());
427 // Start acking and make sure we're back to steady-state.
428 RtcpCastMessage cast_feedback(1);
429 cast_feedback.media_ssrc = 2;
430 cast_feedback.ack_frame_id = 0;
431 video_sender_->OnReceivedCastFeedback(cast_feedback);
432 EXPECT_LE(
434 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
436 // Empty the pipeline.
437 RunTasks(100);
438 // Should have sent at least 7 packets.
439 EXPECT_LE(
441 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
444 TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
445 InitEncoder(false, true);
446 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
448 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
449 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
450 RunTasks(33);
451 RtcpCastMessage cast_feedback(1);
452 cast_feedback.media_ssrc = 2;
453 cast_feedback.ack_frame_id = 0;
455 // Send 3 more frames but don't ACK.
456 for (int i = 0; i < 3; ++i) {
457 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
458 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
459 RunTasks(33);
461 const int number_of_packets_sent = transport_.number_of_rtp_packets();
463 // Send duplicated ACKs and mix some invalid NACKs.
464 for (int i = 0; i < 10; ++i) {
465 RtcpCastMessage ack_feedback(1);
466 ack_feedback.media_ssrc = 2;
467 ack_feedback.ack_frame_id = 0;
468 RtcpCastMessage nack_feedback(1);
469 nack_feedback.media_ssrc = 2;
470 nack_feedback.missing_frames_and_packets[255] = PacketIdSet();
471 video_sender_->OnReceivedCastFeedback(ack_feedback);
472 video_sender_->OnReceivedCastFeedback(nack_feedback);
474 EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
476 // Re-transmit one packet because of duplicated ACKs.
477 for (int i = 0; i < 3; ++i) {
478 RtcpCastMessage ack_feedback(1);
479 ack_feedback.media_ssrc = 2;
480 ack_feedback.ack_frame_id = 0;
481 video_sender_->OnReceivedCastFeedback(ack_feedback);
483 EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
486 TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
487 InitEncoder(false, true);
488 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
490 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
491 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
492 RunTasks(33);
493 RtcpCastMessage cast_feedback(1);
494 cast_feedback.media_ssrc = 2;
495 cast_feedback.ack_frame_id = 0;
497 // Send 2 more frames but don't ACK.
498 for (int i = 0; i < 2; ++i) {
499 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
500 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
501 RunTasks(33);
503 // Pause the transport
504 transport_.SetPause(true);
506 // Insert one more video frame.
507 video_frame = GetLargeNewVideoFrame();
508 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
509 RunTasks(33);
511 const int number_of_packets_sent = transport_.number_of_rtp_packets();
513 // Send duplicated ACKs and mix some invalid NACKs.
514 for (int i = 0; i < 10; ++i) {
515 RtcpCastMessage ack_feedback(1);
516 ack_feedback.media_ssrc = 2;
517 ack_feedback.ack_frame_id = 0;
518 RtcpCastMessage nack_feedback(1);
519 nack_feedback.media_ssrc = 2;
520 nack_feedback.missing_frames_and_packets[255] = PacketIdSet();
521 video_sender_->OnReceivedCastFeedback(ack_feedback);
522 video_sender_->OnReceivedCastFeedback(nack_feedback);
524 EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
526 // Re-transmit one packet because of duplicated ACKs.
527 for (int i = 0; i < 3; ++i) {
528 RtcpCastMessage ack_feedback(1);
529 ack_feedback.media_ssrc = 2;
530 ack_feedback.ack_frame_id = 0;
531 video_sender_->OnReceivedCastFeedback(ack_feedback);
534 transport_.SetPause(false);
535 RunTasks(100);
536 EXPECT_LT(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
539 TEST_F(VideoSenderTest, AcksCancelRetransmits) {
540 InitEncoder(false, true);
541 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
543 transport_.SetPause(true);
544 scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
545 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
546 RunTasks(33);
548 // Frame should be in buffer, waiting. Now let's ack it.
549 RtcpCastMessage cast_feedback(1);
550 cast_feedback.media_ssrc = 2;
551 cast_feedback.ack_frame_id = 0;
552 video_sender_->OnReceivedCastFeedback(cast_feedback);
554 transport_.SetPause(false);
555 RunTasks(33);
556 EXPECT_EQ(0, transport_.number_of_rtp_packets());
559 TEST_F(VideoSenderTest, CheckVideoFrameFactoryIsNull) {
560 InitEncoder(false, true);
561 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
563 EXPECT_EQ(nullptr, video_sender_->CreateVideoFrameFactory().get());
566 TEST_F(VideoSenderTest, PopulatesResourceUtilizationInFrameMetadata) {
567 InitEncoder(false, true);
568 ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
570 for (int i = 0; i < 3; ++i) {
571 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
572 ASSERT_FALSE(video_frame->metadata()->HasKey(
573 media::VideoFrameMetadata::RESOURCE_UTILIZATION));
575 const base::TimeTicks reference_time = testing_clock_->NowTicks();
576 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
578 // Run encode tasks. VideoSender::OnEncodedVideoFrame() will be called once
579 // encoding of the frame is complete, and this is when the
580 // RESOURCE_UTILIZATION metadata is populated.
581 RunTasks(33);
583 // Check that the RESOURCE_UTILIZATION value is set and non-negative. Don't
584 // check for specific values because they are dependent on real-world CPU
585 // encode time, which can vary across test runs.
586 double utilization = -1.0;
587 EXPECT_TRUE(video_frame->metadata()->GetDouble(
588 media::VideoFrameMetadata::RESOURCE_UTILIZATION, &utilization));
589 EXPECT_LE(0.0, utilization);
590 if (i == 0)
591 EXPECT_GE(1.0, utilization); // Key frames never exceed 1.0.
592 DVLOG(1) << "Utilization computed by VideoSender is: " << utilization;
596 } // namespace cast
597 } // namespace media