Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

185 lines
6.6 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdlib.h>
#include <algorithm>
#include <memory>
#include <vector>
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h"
#include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h"
#include "webrtc/rtc_base/rate_limiter.h"
#include "webrtc/test/gtest.h"
namespace {
const unsigned char kPayloadType = 100;
};
namespace webrtc {
class RtpRtcpVideoTest : public ::testing::Test {
protected:
RtpRtcpVideoTest()
Reland of move RTPPayloadStrategy and simplify RTPPayloadRegistry (patchset #1 id:1 of https://codereview.webrtc.org/2528993002/ ) Reason for revert: Downstream code has been updated. Original issue's description: > Revert of Remove RTPPayloadStrategy and simplify RTPPayloadRegistry (patchset #7 id:240001 of https://codereview.webrtc.org/2524923002/ ) > > Reason for revert: > Breaks downstream projects. > > Original issue's description: > > Remove RTPPayloadStrategy and simplify RTPPayloadRegistry > > > > This CL removes RTPPayloadStrategy that is currently used to handle > > audio/video specific aspects of payload handling. Instead, the audio and > > video specific aspects will now have different functions, with linear > > code flow. > > > > This CL does not contain any functional changes, and is just a > > preparation for future CL:s. > > > > The main purpose with this CL is to add this function: > > bool PayloadIsCompatible(const RtpUtility::Payload& payload, > > const webrtc::VideoCodec& video_codec); > > that can easily be extended in a future CL to look at video codec > > specific information. > > > > BUG=webrtc:6743 > > > > Committed: https://crrev.com/b881254dc86d2cc80a52e08155433458be002166 > > Cr-Commit-Position: refs/heads/master@{#15232} > > TBR=danilchap@webrtc.org,solenberg@webrtc.org,mflodman@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:6743 > > Committed: https://crrev.com/33c81d05613f45f65ee17224ed381c6cdd1c6c6f > Cr-Commit-Position: refs/heads/master@{#15234} TBR=danilchap@webrtc.org,solenberg@webrtc.org,mflodman@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:6743 Review-Url: https://codereview.webrtc.org/2531043002 Cr-Commit-Position: refs/heads/master@{#15245}
2016-11-25 06:40:25 -08:00
: test_ssrc_(3456),
test_timestamp_(4567),
test_sequence_number_(2345),
fake_clock(123456),
retransmission_rate_limiter_(&fake_clock, 1000) {}
~RtpRtcpVideoTest() {}
virtual void SetUp() {
transport_ = new LoopBackTransport();
receiver_ = new TestRtpReceiver();
receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock));
RtpRtcp::Configuration configuration;
configuration.audio = false;
configuration.clock = &fake_clock;
configuration.outgoing_transport = transport_;
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
video_module_ = RtpRtcp::CreateRtpRtcp(configuration);
rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
&fake_clock, receiver_, NULL, &rtp_payload_registry_));
video_module_->SetRTCPStatus(RtcpMode::kCompound);
video_module_->SetSSRC(test_ssrc_);
video_module_->SetStorePacketsStatus(true, 600);
EXPECT_EQ(0, video_module_->SetSendingStatus(true));
transport_->SetSendModule(video_module_, &rtp_payload_registry_,
rtp_receiver_.get(), receive_statistics_.get());
VideoCodec video_codec;
memset(&video_codec, 0, sizeof(video_codec));
video_codec.plType = 123;
memcpy(video_codec.plName, "I420", 5);
EXPECT_EQ(0, video_module_->RegisterSendPayload(video_codec));
EXPECT_EQ(0, rtp_payload_registry_.RegisterReceivePayload(video_codec));
payload_data_length_ = sizeof(video_frame_);
for (size_t n = 0; n < payload_data_length_; n++) {
video_frame_[n] = n%10;
}
}
size_t BuildRTPheader(uint8_t* dataBuffer,
uint32_t timestamp,
uint32_t sequence_number) {
dataBuffer[0] = static_cast<uint8_t>(0x80); // version 2
dataBuffer[1] = static_cast<uint8_t>(kPayloadType);
ByteWriter<uint16_t>::WriteBigEndian(dataBuffer + 2, sequence_number);
ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + 4, timestamp);
ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + 8, 0x1234); // SSRC.
size_t rtpHeaderLength = 12;
return rtpHeaderLength;
}
size_t PaddingPacket(uint8_t* buffer,
uint32_t timestamp,
uint32_t sequence_number,
size_t bytes) {
// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
size_t max_length = 224;
size_t padding_bytes_in_packet = max_length;
if (bytes < max_length) {
padding_bytes_in_packet = (bytes + 16) & 0xffe0; // Keep our modulus 32.
}
// Correct seq num, timestamp and payload type.
size_t header_length = BuildRTPheader(buffer, timestamp, sequence_number);
buffer[0] |= 0x20; // Set padding bit.
int32_t* data =
reinterpret_cast<int32_t*>(&(buffer[header_length]));
// Fill data buffer with random data.
for (size_t j = 0; j < (padding_bytes_in_packet >> 2); j++) {
data[j] = rand(); // NOLINT
}
// Set number of padding bytes in the last byte of the packet.
buffer[header_length + padding_bytes_in_packet - 1] =
padding_bytes_in_packet;
return padding_bytes_in_packet + header_length;
}
virtual void TearDown() {
delete video_module_;
delete transport_;
delete receiver_;
}
int test_id_;
std::unique_ptr<ReceiveStatistics> receive_statistics_;
RTPPayloadRegistry rtp_payload_registry_;
std::unique_ptr<RtpReceiver> rtp_receiver_;
RtpRtcp* video_module_;
LoopBackTransport* transport_;
TestRtpReceiver* receiver_;
uint32_t test_ssrc_;
uint32_t test_timestamp_;
uint16_t test_sequence_number_;
uint8_t video_frame_[65000];
size_t payload_data_length_;
SimulatedClock fake_clock;
RateLimiter retransmission_rate_limiter_;
};
TEST_F(RtpRtcpVideoTest, BasicVideo) {
uint32_t timestamp = 3000;
EXPECT_TRUE(video_module_->SendOutgoingData(
kVideoFrameDelta, 123, timestamp, timestamp / 90, video_frame_,
payload_data_length_, nullptr, nullptr, nullptr));
}
TEST_F(RtpRtcpVideoTest, PaddingOnlyFrames) {
const size_t kPadSize = 255;
uint8_t padding_packet[kPadSize];
uint32_t seq_num = 0;
uint32_t timestamp = 3000;
VideoCodec codec;
codec.codecType = kVideoCodecVP8;
codec.plType = kPayloadType;
strncpy(codec.plName, "VP8", 4);
EXPECT_EQ(0, rtp_payload_registry_.RegisterReceivePayload(codec));
for (int frame_idx = 0; frame_idx < 10; ++frame_idx) {
for (int packet_idx = 0; packet_idx < 5; ++packet_idx) {
size_t packet_size = PaddingPacket(padding_packet, timestamp, seq_num,
kPadSize);
++seq_num;
RTPHeader header;
std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
EXPECT_TRUE(parser->Parse(padding_packet, packet_size, &header));
PayloadUnion payload_specific;
EXPECT_TRUE(rtp_payload_registry_.GetPayloadSpecifics(header.payloadType,
&payload_specific));
const uint8_t* payload = padding_packet + header.headerLength;
const size_t payload_length = packet_size - header.headerLength;
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, payload,
payload_length,
payload_specific, true));
EXPECT_EQ(0u, receiver_->payload_size());
EXPECT_EQ(payload_length, receiver_->rtp_header().header.paddingLength);
}
timestamp += 3000;
fake_clock.AdvanceTimeMilliseconds(33);
}
}
} // namespace webrtc