blob: be8d6c6f3e8db4becf645aa168be19762333ddf5 [file] [log] [blame]
// Copyright (c) 2010 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 <string>
#include <vector>
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/fake_session.h"
#include "remoting/protocol/rtp_reader.h"
#include "remoting/protocol/rtp_utils.h"
#include "remoting/protocol/rtp_video_writer.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::IOBuffer;
using std::string;
using std::vector;
namespace remoting {
namespace protocol {
namespace {
bool ParsePacket(const string& data, RtpPacket* packet) {
int header_size = UnpackRtpHeader(
reinterpret_cast<const uint8*>(&*data.begin()),
data.size(), packet->mutable_header());
if (header_size < 0) {
return false;
}
int descriptor_size = UnpackVp8Descriptor(
reinterpret_cast<const uint8*>(&*data.begin()) + header_size,
data.size() - header_size, packet->mutable_vp8_descriptor());
if (descriptor_size < 0) {
return false;
}
packet->mutable_payload()->AppendCopyOf(
&*data.begin() + header_size + descriptor_size,
data.size() - header_size - descriptor_size);
return true;
}
} // namespace
class RtpVideoWriterTest : public testing::Test {
protected:
struct ExpectedPacket {
bool first;
Vp8Descriptor::FragmentationInfo fragmentation_info;
bool last;
};
virtual void SetUp() {
session_ = new FakeSession();
writer_.Init(session_);
}
void InitData(int size) {
data_.resize(size);
for (int i = 0; i < size; ++i) {
data_[i] = static_cast<char>(i);
}
}
void InitPacket(int size, bool first, bool last) {
InitData(size);
packet_ = new VideoPacket();
packet_->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8);
if (first)
packet_->set_flags(packet_->flags() | VideoPacket::FIRST_PACKET);
if (last)
packet_->set_flags(packet_->flags() | VideoPacket::LAST_PACKET);
packet_->mutable_data()->assign(data_.begin(), data_.end());
}
bool CompareData(const CompoundBuffer& buffer, char* data, int size) {
scoped_refptr<IOBuffer> buffer_data = buffer.ToIOBufferWithSize();
return buffer.total_bytes() == size &&
memcmp(buffer_data->data(), data, size) == 0;
}
void VerifyResult(const ExpectedPacket expected[],
int count) {
const vector<string>& rtp_packets =
session_->video_rtp_channel()->written_packets();
ASSERT_EQ(count, static_cast<int>(rtp_packets.size()));
int pos = 0;
for (int i = 0; i < count; ++i) {
SCOPED_TRACE("Packet " + base::IntToString(i));
RtpPacket packet;
ASSERT_TRUE(ParsePacket(rtp_packets[i], &packet));
EXPECT_EQ(expected[i].first, packet.vp8_descriptor().frame_beginning);
EXPECT_EQ(expected[i].last, packet.header().marker);
EXPECT_EQ(expected[i].fragmentation_info,
packet.vp8_descriptor().fragmentation_info);
EXPECT_TRUE(CompareData(packet.payload(), &*data_.begin() + pos,
packet.payload().total_bytes()));
pos += packet.payload().total_bytes();
}
EXPECT_EQ(pos, static_cast<int>(data_.size()));
}
scoped_refptr<FakeSession> session_;
RtpVideoWriter writer_;
MessageLoop message_loop_;
vector<char> data_;
VideoPacket* packet_;
};
TEST_F(RtpVideoWriterTest, NotFragmented_FirstPacket) {
InitPacket(1024, true, false);
writer_.ProcessVideoPacket(packet_, new DeleteTask<VideoPacket>(packet_));
message_loop_.RunAllPending();
ExpectedPacket expected[] = {
{ true, Vp8Descriptor::NOT_FRAGMENTED, false }
};
VerifyResult(expected, arraysize(expected));
}
TEST_F(RtpVideoWriterTest, NotFragmented_LastPackes) {
InitPacket(1024, false, true);
writer_.ProcessVideoPacket(packet_, new DeleteTask<VideoPacket>(packet_));
message_loop_.RunAllPending();
ExpectedPacket expected[] = {
{ false, Vp8Descriptor::NOT_FRAGMENTED, true }
};
VerifyResult(expected, arraysize(expected));
}
TEST_F(RtpVideoWriterTest, TwoFragments_FirstPacket) {
InitPacket(2000, true, false);
writer_.ProcessVideoPacket(packet_, new DeleteTask<VideoPacket>(packet_));
message_loop_.RunAllPending();
ExpectedPacket expected[] = {
{ true, Vp8Descriptor::FIRST_FRAGMENT, false },
{ false, Vp8Descriptor::LAST_FRAGMENT, false },
};
VerifyResult(expected, arraysize(expected));
}
TEST_F(RtpVideoWriterTest, TwoFragments_LastPacket) {
InitPacket(2000, false, true);
writer_.ProcessVideoPacket(packet_, new DeleteTask<VideoPacket>(packet_));
message_loop_.RunAllPending();
ExpectedPacket expected[] = {
{ false, Vp8Descriptor::FIRST_FRAGMENT, false },
{ false, Vp8Descriptor::LAST_FRAGMENT, true },
};
VerifyResult(expected, arraysize(expected));
}
TEST_F(RtpVideoWriterTest, ThreeFragments) {
InitPacket(3000, true, true);
writer_.ProcessVideoPacket(packet_, new DeleteTask<VideoPacket>(packet_));
message_loop_.RunAllPending();
ExpectedPacket expected[] = {
{ true, Vp8Descriptor::FIRST_FRAGMENT, false },
{ false, Vp8Descriptor::MIDDLE_FRAGMENT, false },
{ false, Vp8Descriptor::LAST_FRAGMENT, true },
};
VerifyResult(expected, arraysize(expected));
}
} // namespace protocol
} // namespace remoting