Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(973)

Unified Diff: media/cast/video_receiver/video_receiver_unittest.cc

Issue 225023010: [Cast] Refactor/clean-up VideoReceiver to match AudioReceiver as closely as possible. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/cast/video_receiver/video_receiver.gypi ('k') | media/cast/video_sender/codecs/vp8/vp8_encoder.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/cast/video_receiver/video_receiver_unittest.cc
diff --git a/media/cast/video_receiver/video_receiver_unittest.cc b/media/cast/video_receiver/video_receiver_unittest.cc
index 7bea5013201821f60e934d4451c6f3bd11a214c9..4fe834ce889fb4d7b7f875c12422995dfcb86094 100644
--- a/media/cast/video_receiver/video_receiver_unittest.cc
+++ b/media/cast/video_receiver/video_receiver_unittest.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <stdint.h>
-
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -16,45 +14,47 @@
#include "media/cast/video_receiver/video_receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
-static const int kPacketSize = 1500;
-static const int64 kStartMillisecond = INT64_C(12345678900000);
-
namespace media {
namespace cast {
-using testing::_;
+using ::testing::_;
namespace {
-// Was thread counted thread safe.
-class TestVideoReceiverCallback
- : public base::RefCountedThreadSafe<TestVideoReceiverCallback> {
+
+const int kPacketSize = 1500;
+const int64 kStartMillisecond = INT64_C(12345678900000);
+const uint32 kFirstFrameId = 1234;
+
+class FakeVideoClient {
public:
- TestVideoReceiverCallback() : num_called_(0) {}
+ FakeVideoClient() : num_called_(0) {}
+ virtual ~FakeVideoClient() {}
- // TODO(mikhal): Set and check expectations.
- void DecodeComplete(const scoped_refptr<media::VideoFrame>& video_frame,
- const base::TimeTicks& render_time) {
- ++num_called_;
+ void SetNextExpectedResult(uint32 expected_frame_id,
+ const base::TimeTicks& expected_playout_time) {
+ expected_frame_id_ = expected_frame_id;
+ expected_playout_time_ = expected_playout_time;
}
- void FrameToDecode(scoped_ptr<transport::EncodedVideoFrame> video_frame,
- const base::TimeTicks& render_time) {
- EXPECT_TRUE(video_frame->key_frame);
+ void DeliverEncodedVideoFrame(
+ scoped_ptr<transport::EncodedVideoFrame> video_frame,
+ const base::TimeTicks& playout_time) {
+ ASSERT_FALSE(!video_frame)
+ << "If at shutdown: There were unsatisfied requests enqueued.";
+ EXPECT_EQ(expected_frame_id_, video_frame->frame_id);
EXPECT_EQ(transport::kVp8, video_frame->codec);
+ EXPECT_EQ(expected_playout_time_, playout_time);
++num_called_;
}
int number_times_called() const { return num_called_; }
- protected:
- virtual ~TestVideoReceiverCallback() {}
-
private:
- friend class base::RefCountedThreadSafe<TestVideoReceiverCallback>;
-
int num_called_;
+ uint32 expected_frame_id_;
+ base::TimeTicks expected_playout_time_;
- DISALLOW_COPY_AND_ASSIGN(TestVideoReceiverCallback);
+ DISALLOW_COPY_AND_ASSIGN(FakeVideoClient);
};
} // namespace
@@ -62,88 +62,85 @@ class VideoReceiverTest : public ::testing::Test {
protected:
VideoReceiverTest() {
// Configure to use vp8 software implementation.
- config_.codec = transport::kVp8;
+ config_.rtp_max_delay_ms = 100;
config_.use_external_decoder = false;
+ // Note: Frame rate must divide 1000 without remainder so the test code
+ // doesn't have to account for rounding errors.
+ config_.max_frame_rate = 25;
+ config_.codec = transport::kVp8;
testing_clock_ = new base::SimpleTestTickClock();
+ testing_clock_->Advance(
+ base::TimeDelta::FromMilliseconds(kStartMillisecond));
task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
+
cast_environment_ =
new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
task_runner_,
task_runner_,
task_runner_);
+
receiver_.reset(new VideoReceiver(
- cast_environment_, config_, &mock_transport_, target_delay_cb_));
- testing_clock_->Advance(
- base::TimeDelta::FromMilliseconds(kStartMillisecond));
- video_receiver_callback_ = new TestVideoReceiverCallback();
+ cast_environment_, config_, &mock_transport_));
+ }
+ virtual ~VideoReceiverTest() {}
+
+ virtual void SetUp() {
payload_.assign(kPacketSize, 0);
// Always start with a key frame.
rtp_header_.is_key_frame = true;
- rtp_header_.frame_id = 1234;
+ rtp_header_.frame_id = kFirstFrameId;
rtp_header_.packet_id = 0;
rtp_header_.max_packet_id = 0;
rtp_header_.is_reference = false;
rtp_header_.reference_frame_id = 0;
- rtp_header_.webrtc.header.timestamp = 9000;
+ rtp_header_.webrtc.header.timestamp = 0;
}
- virtual ~VideoReceiverTest() {}
+ void FeedOneFrameIntoReceiver() {
+ receiver_->OnReceivedPayloadData(
+ payload_.data(), payload_.size(), rtp_header_);
+ }
- transport::MockPacedPacketSender mock_transport_;
VideoReceiverConfig config_;
- scoped_ptr<VideoReceiver> receiver_;
std::vector<uint8> payload_;
RtpCastHeader rtp_header_;
base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
-
+ transport::MockPacedPacketSender mock_transport_;
scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
scoped_refptr<CastEnvironment> cast_environment_;
- scoped_refptr<TestVideoReceiverCallback> video_receiver_callback_;
- SetTargetDelayCallback target_delay_cb_;
+ FakeVideoClient fake_video_client_;
+
+ // Important for the VideoReceiver to be declared last, since its dependencies
+ // must remain alive until after its destruction.
+ scoped_ptr<VideoReceiver> receiver_;
DISALLOW_COPY_AND_ASSIGN(VideoReceiverTest);
};
-TEST_F(VideoReceiverTest, GetOnePacketEncodedframe) {
- EXPECT_CALL(mock_transport_, SendRtcpPacket(_))
- .WillRepeatedly(testing::Return(true));
- receiver_->OnReceivedPayloadData(
- payload_.data(), payload_.size(), rtp_header_);
-
- VideoFrameEncodedCallback frame_to_decode_callback = base::Bind(
- &TestVideoReceiverCallback::FrameToDecode, video_receiver_callback_);
-
- receiver_->GetEncodedVideoFrame(frame_to_decode_callback);
- task_runner_->RunTasks();
- EXPECT_EQ(video_receiver_callback_->number_times_called(), 1);
-}
-
-TEST_F(VideoReceiverTest, MultiplePackets) {
+TEST_F(VideoReceiverTest, GetOnePacketEncodedFrame) {
SimpleEventSubscriber event_subscriber;
cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
EXPECT_CALL(mock_transport_, SendRtcpPacket(_))
.WillRepeatedly(testing::Return(true));
- rtp_header_.max_packet_id = 2;
- receiver_->OnReceivedPayloadData(
- payload_.data(), payload_.size(), rtp_header_);
- ++rtp_header_.packet_id;
- ++rtp_header_.webrtc.header.sequenceNumber;
- receiver_->OnReceivedPayloadData(
- payload_.data(), payload_.size(), rtp_header_);
- ++rtp_header_.packet_id;
- receiver_->OnReceivedPayloadData(
- payload_.data(), payload_.size(), rtp_header_);
-
- VideoFrameEncodedCallback frame_to_decode_callback = base::Bind(
- &TestVideoReceiverCallback::FrameToDecode, video_receiver_callback_);
-
- receiver_->GetEncodedVideoFrame(frame_to_decode_callback);
+ // Enqueue a request for a video frame.
+ receiver_->GetEncodedVideoFrame(
+ base::Bind(&FakeVideoClient::DeliverEncodedVideoFrame,
+ base::Unretained(&fake_video_client_)));
+
+ // The request should not be satisfied since no packets have been received.
+ task_runner_->RunTasks();
+ EXPECT_EQ(0, fake_video_client_.number_times_called());
+
+ // Deliver one video frame to the receiver and expect to get one frame back.
+ fake_video_client_.SetNextExpectedResult(kFirstFrameId,
+ testing_clock_->NowTicks());
+ FeedOneFrameIntoReceiver();
task_runner_->RunTasks();
- EXPECT_EQ(video_receiver_callback_->number_times_called(), 1);
+ EXPECT_EQ(1, fake_video_client_.number_times_called());
std::vector<FrameEvent> frame_events;
event_subscriber.GetFrameEventsAndReset(&frame_events);
@@ -153,23 +150,89 @@ TEST_F(VideoReceiverTest, MultiplePackets) {
EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id);
EXPECT_EQ(rtp_header_.webrtc.header.timestamp,
frame_events.begin()->rtp_timestamp);
+
cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
}
-TEST_F(VideoReceiverTest, GetOnePacketRawframe) {
+TEST_F(VideoReceiverTest, MultiplePendingGetCalls) {
EXPECT_CALL(mock_transport_, SendRtcpPacket(_))
.WillRepeatedly(testing::Return(true));
- receiver_->OnReceivedPayloadData(
- payload_.data(), payload_.size(), rtp_header_);
- // Decode error - requires legal input.
- VideoFrameDecodedCallback frame_decoded_callback = base::Bind(
- &TestVideoReceiverCallback::DecodeComplete, video_receiver_callback_);
- receiver_->GetRawVideoFrame(frame_decoded_callback);
+
+ // Enqueue a request for an video frame.
+ const VideoFrameEncodedCallback frame_encoded_callback =
+ base::Bind(&FakeVideoClient::DeliverEncodedVideoFrame,
+ base::Unretained(&fake_video_client_));
+ receiver_->GetEncodedVideoFrame(frame_encoded_callback);
task_runner_->RunTasks();
- EXPECT_EQ(video_receiver_callback_->number_times_called(), 0);
-}
+ EXPECT_EQ(0, fake_video_client_.number_times_called());
-// TODO(pwestin): add encoded frames.
+ // Receive one video frame and expect to see the first request satisfied.
+ fake_video_client_.SetNextExpectedResult(kFirstFrameId,
+ testing_clock_->NowTicks());
+ const base::TimeTicks time_at_first_frame_feed = testing_clock_->NowTicks();
+ FeedOneFrameIntoReceiver();
+ task_runner_->RunTasks();
+ EXPECT_EQ(1, fake_video_client_.number_times_called());
+
+ testing_clock_->Advance(
+ base::TimeDelta::FromSeconds(1) / config_.max_frame_rate);
+
+ // Enqueue a second request for an video frame, but it should not be
+ // fulfilled yet.
+ receiver_->GetEncodedVideoFrame(frame_encoded_callback);
+ task_runner_->RunTasks();
+ EXPECT_EQ(1, fake_video_client_.number_times_called());
+
+ // Receive one video frame out-of-order: Make sure that we are not continuous
+ // and that the RTP timestamp represents a time in the future.
+ rtp_header_.is_key_frame = false;
+ rtp_header_.frame_id = kFirstFrameId + 2;
+ rtp_header_.is_reference = true;
+ rtp_header_.reference_frame_id = 0;
+ rtp_header_.webrtc.header.timestamp +=
+ config_.rtp_max_delay_ms * kVideoFrequency / 1000;
+ fake_video_client_.SetNextExpectedResult(
+ kFirstFrameId + 2,
+ time_at_first_frame_feed +
+ base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms));
+ FeedOneFrameIntoReceiver();
+
+ // Frame 2 should not come out at this point in time.
+ task_runner_->RunTasks();
+ EXPECT_EQ(1, fake_video_client_.number_times_called());
+
+ // Enqueue a third request for an video frame.
+ receiver_->GetEncodedVideoFrame(frame_encoded_callback);
+ task_runner_->RunTasks();
+ EXPECT_EQ(1, fake_video_client_.number_times_called());
+
+ // After |rtp_max_delay_ms| has elapsed, Frame 2 is emitted (to satisfy the
+ // second request) because a decision was made to skip over the no-show Frame
+ // 1.
+ testing_clock_->Advance(
+ base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms));
+ task_runner_->RunTasks();
+ EXPECT_EQ(2, fake_video_client_.number_times_called());
+
+ // Receive Frame 3 and expect it to fulfill the third request immediately.
+ rtp_header_.frame_id = kFirstFrameId + 3;
+ rtp_header_.is_reference = false;
+ rtp_header_.reference_frame_id = 0;
+ rtp_header_.webrtc.header.timestamp +=
+ kVideoFrequency / config_.max_frame_rate;
+ fake_video_client_.SetNextExpectedResult(kFirstFrameId + 3,
+ testing_clock_->NowTicks());
+ FeedOneFrameIntoReceiver();
+ task_runner_->RunTasks();
+ EXPECT_EQ(3, fake_video_client_.number_times_called());
+
+ // Move forward another |rtp_max_delay_ms| and run any pending tasks (there
+ // should be none). Expect no additional frames where emitted.
+ testing_clock_->Advance(
+ base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms));
+ task_runner_->RunTasks();
+ EXPECT_EQ(3, fake_video_client_.number_times_called());
+}
} // namespace cast
} // namespace media
« no previous file with comments | « media/cast/video_receiver/video_receiver.gypi ('k') | media/cast/video_sender/codecs/vp8/vp8_encoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698