RtpPacketizer::NextPacket fills RtpPacket instead of just payload.
This push decision if Marker bit should be set into packetizers fixing issue where returned last_packet flag was ambiguous for some VP9 packets. Added test for VP9 where last_packet != marker_bit BUG=webrtc:6723 Review-Url: https://codereview.webrtc.org/2522553002 Cr-Commit-Position: refs/heads/master@{#15415}
This commit is contained in:
parent
f00082da37
commit
e545e5d062
@ -18,6 +18,7 @@
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
class RtpPacketToSend;
|
||||
|
||||
class RtpPacketizer {
|
||||
public:
|
||||
@ -33,15 +34,11 @@ class RtpPacketizer {
|
||||
const RTPFragmentationHeader* fragmentation) = 0;
|
||||
|
||||
// Get the next payload with payload header.
|
||||
// buffer is a pointer to where the output will be written.
|
||||
// bytes_to_send is an output variable that will contain number of bytes
|
||||
// written to buffer. The parameter last_packet is true for the last packet of
|
||||
// the frame, false otherwise (i.e., call the function again to get the
|
||||
// next packet).
|
||||
// Returns true on success or false if there was no payload to packetize.
|
||||
virtual bool NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) = 0;
|
||||
// Write payload and set marker bit of the |packet|.
|
||||
// The parameter |last_packet| is true for the last packet of the frame, false
|
||||
// otherwise (i.e., call the function again to get the next packet).
|
||||
// Returns true on success, false otherwise.
|
||||
virtual bool NextPacket(RtpPacketToSend* packet, bool* last_packet) = 0;
|
||||
|
||||
virtual ProtectionType GetProtectionType() = 0;
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "webrtc/common_video/h264/sps_vui_rewriter.h"
|
||||
#include "webrtc/common_video/h264/h264_common.h"
|
||||
#include "webrtc/common_video/h264/pps_parser.h"
|
||||
@ -229,54 +230,50 @@ size_t RtpPacketizerH264::PacketizeStapA(size_t fragment_index) {
|
||||
return fragment_index;
|
||||
}
|
||||
|
||||
bool RtpPacketizerH264::NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool RtpPacketizerH264::NextPacket(RtpPacketToSend* rtp_packet,
|
||||
bool* last_packet) {
|
||||
*bytes_to_send = 0;
|
||||
RTC_DCHECK(rtp_packet);
|
||||
RTC_DCHECK(last_packet);
|
||||
if (packets_.empty()) {
|
||||
*bytes_to_send = 0;
|
||||
*last_packet = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
PacketUnit packet = packets_.front();
|
||||
|
||||
if (packet.first_fragment && packet.last_fragment) {
|
||||
// Single NAL unit packet.
|
||||
*bytes_to_send = packet.source_fragment.length;
|
||||
memcpy(buffer, packet.source_fragment.buffer, *bytes_to_send);
|
||||
size_t bytes_to_send = packet.source_fragment.length;
|
||||
uint8_t* buffer = rtp_packet->AllocatePayload(bytes_to_send);
|
||||
memcpy(buffer, packet.source_fragment.buffer, bytes_to_send);
|
||||
packets_.pop();
|
||||
input_fragments_.pop_front();
|
||||
RTC_CHECK_LE(*bytes_to_send, max_payload_len_);
|
||||
} else if (packet.aggregated) {
|
||||
NextAggregatePacket(buffer, bytes_to_send);
|
||||
RTC_CHECK_LE(*bytes_to_send, max_payload_len_);
|
||||
NextAggregatePacket(rtp_packet);
|
||||
} else {
|
||||
NextFragmentPacket(buffer, bytes_to_send);
|
||||
RTC_CHECK_LE(*bytes_to_send, max_payload_len_);
|
||||
NextFragmentPacket(rtp_packet);
|
||||
}
|
||||
RTC_DCHECK_LE(rtp_packet->payload_size(), max_payload_len_);
|
||||
*last_packet = packets_.empty();
|
||||
rtp_packet->SetMarker(*last_packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RtpPacketizerH264::NextAggregatePacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send) {
|
||||
void RtpPacketizerH264::NextAggregatePacket(RtpPacketToSend* rtp_packet) {
|
||||
uint8_t* buffer = rtp_packet->AllocatePayload(max_payload_len_);
|
||||
RTC_DCHECK(buffer);
|
||||
PacketUnit* packet = &packets_.front();
|
||||
RTC_CHECK(packet->first_fragment);
|
||||
// STAP-A NALU header.
|
||||
buffer[0] = (packet->header & (kFBit | kNriMask)) | H264::NaluType::kStapA;
|
||||
int index = kNalHeaderSize;
|
||||
*bytes_to_send += kNalHeaderSize;
|
||||
size_t index = kNalHeaderSize;
|
||||
while (packet->aggregated) {
|
||||
const Fragment& fragment = packet->source_fragment;
|
||||
// Add NAL unit length field.
|
||||
ByteWriter<uint16_t>::WriteBigEndian(&buffer[index], fragment.length);
|
||||
index += kLengthFieldSize;
|
||||
*bytes_to_send += kLengthFieldSize;
|
||||
// Add NAL unit.
|
||||
memcpy(&buffer[index], fragment.buffer, fragment.length);
|
||||
index += fragment.length;
|
||||
*bytes_to_send += fragment.length;
|
||||
packets_.pop();
|
||||
input_fragments_.pop_front();
|
||||
if (packet->last_fragment)
|
||||
@ -284,10 +281,10 @@ void RtpPacketizerH264::NextAggregatePacket(uint8_t* buffer,
|
||||
packet = &packets_.front();
|
||||
}
|
||||
RTC_CHECK(packet->last_fragment);
|
||||
rtp_packet->SetPayloadSize(index);
|
||||
}
|
||||
|
||||
void RtpPacketizerH264::NextFragmentPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send) {
|
||||
void RtpPacketizerH264::NextFragmentPacket(RtpPacketToSend* rtp_packet) {
|
||||
PacketUnit* packet = &packets_.front();
|
||||
// NAL unit fragmented over multiple packets (FU-A).
|
||||
// We do not send original NALU header, so it will be replaced by the
|
||||
@ -301,11 +298,11 @@ void RtpPacketizerH264::NextFragmentPacket(uint8_t* buffer,
|
||||
fu_header |= (packet->last_fragment ? kEBit : 0);
|
||||
uint8_t type = packet->header & kTypeMask;
|
||||
fu_header |= type;
|
||||
const Fragment& fragment = packet->source_fragment;
|
||||
uint8_t* buffer =
|
||||
rtp_packet->AllocatePayload(kFuAHeaderSize + fragment.length);
|
||||
buffer[0] = fu_indicator;
|
||||
buffer[1] = fu_header;
|
||||
|
||||
const Fragment& fragment = packet->source_fragment;
|
||||
*bytes_to_send = fragment.length + kFuAHeaderSize;
|
||||
memcpy(buffer + kFuAHeaderSize, fragment.buffer, fragment.length);
|
||||
if (packet->last_fragment)
|
||||
input_fragments_.pop_front();
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
@ -34,15 +35,11 @@ class RtpPacketizerH264 : public RtpPacketizer {
|
||||
const RTPFragmentationHeader* fragmentation) override;
|
||||
|
||||
// Get the next payload with H264 payload header.
|
||||
// buffer is a pointer to where the output will be written.
|
||||
// bytes_to_send is an output variable that will contain number of bytes
|
||||
// written to buffer. The parameter last_packet is true for the last packet of
|
||||
// the frame, false otherwise (i.e., call the function again to get the
|
||||
// next packet).
|
||||
// Returns true on success or false if there was no payload to packetize.
|
||||
bool NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) override;
|
||||
// Write payload and set marker bit of the |packet|.
|
||||
// The parameter |last_packet| is true for the last packet of the frame, false
|
||||
// otherwise (i.e., call the function again to get the next packet).
|
||||
// Returns true on success, false otherwise.
|
||||
bool NextPacket(RtpPacketToSend* rtp_packet, bool* last_packet) override;
|
||||
|
||||
ProtectionType GetProtectionType() override;
|
||||
|
||||
@ -89,8 +86,8 @@ class RtpPacketizerH264 : public RtpPacketizer {
|
||||
void GeneratePackets();
|
||||
void PacketizeFuA(size_t fragment_index);
|
||||
size_t PacketizeStapA(size_t fragment_index);
|
||||
void NextAggregatePacket(uint8_t* buffer, size_t* bytes_to_send);
|
||||
void NextFragmentPacket(uint8_t* buffer, size_t* bytes_to_send);
|
||||
void NextAggregatePacket(RtpPacketToSend* rtp_packet);
|
||||
void NextFragmentPacket(RtpPacketToSend* rtp_packet);
|
||||
|
||||
const size_t max_payload_len_;
|
||||
std::deque<Fragment> input_fragments_;
|
||||
|
||||
@ -11,16 +11,22 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/array_view.h"
|
||||
#include "webrtc/common_video/h264/h264_common.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::ElementsAreArray;
|
||||
|
||||
constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
|
||||
const size_t kMaxPayloadSize = 1200;
|
||||
const size_t kLengthFieldLength = 2;
|
||||
|
||||
@ -46,10 +52,9 @@ enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 };
|
||||
void VerifyFua(size_t fua_index,
|
||||
const uint8_t* expected_payload,
|
||||
int offset,
|
||||
const uint8_t* packet,
|
||||
size_t length,
|
||||
rtc::ArrayView<const uint8_t> packet,
|
||||
const std::vector<size_t>& expected_sizes) {
|
||||
ASSERT_EQ(expected_sizes[fua_index] + kFuAHeaderSize, length)
|
||||
ASSERT_EQ(expected_sizes[fua_index] + kFuAHeaderSize, packet.size())
|
||||
<< "FUA index: " << fua_index;
|
||||
const uint8_t kFuIndicator = 0x1C; // F=0, NRI=0, Type=28.
|
||||
EXPECT_EQ(kFuIndicator, packet[0]) << "FUA index: " << fua_index;
|
||||
@ -65,9 +70,8 @@ void VerifyFua(size_t fua_index,
|
||||
std::vector<uint8_t> expected_packet_payload(
|
||||
&expected_payload[offset],
|
||||
&expected_payload[offset + expected_sizes[fua_index]]);
|
||||
EXPECT_THAT(
|
||||
expected_packet_payload,
|
||||
::testing::ElementsAreArray(&packet[2], expected_sizes[fua_index]))
|
||||
EXPECT_THAT(expected_packet_payload,
|
||||
ElementsAreArray(&packet[2], expected_sizes[fua_index]))
|
||||
<< "FUA index: " << fua_index;
|
||||
}
|
||||
|
||||
@ -88,18 +92,18 @@ void TestFua(size_t frame_size,
|
||||
kRtpVideoH264, max_payload_size, NULL, kEmptyFrame));
|
||||
packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation);
|
||||
|
||||
std::unique_ptr<uint8_t[]> packet(new uint8_t[max_payload_size]);
|
||||
size_t length = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(max_payload_size, packet.FreeCapacity());
|
||||
bool last = false;
|
||||
size_t offset = kNalHeaderSize;
|
||||
for (size_t i = 0; i < expected_sizes.size(); ++i) {
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet.get(), &length, &last));
|
||||
VerifyFua(i, frame.get(), offset, packet.get(), length, expected_sizes);
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
VerifyFua(i, frame.get(), offset, packet.payload(), expected_sizes);
|
||||
EXPECT_EQ(i == expected_sizes.size() - 1, last) << "FUA index: " << i;
|
||||
offset += expected_sizes[i];
|
||||
}
|
||||
|
||||
EXPECT_FALSE(packetizer->NextPacket(packet.get(), &length, &last));
|
||||
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
|
||||
}
|
||||
|
||||
size_t GetExpectedNaluOffset(const RTPFragmentationHeader& fragmentation,
|
||||
@ -117,10 +121,8 @@ size_t GetExpectedNaluOffset(const RTPFragmentationHeader& fragmentation,
|
||||
void VerifyStapAPayload(const RTPFragmentationHeader& fragmentation,
|
||||
size_t first_stapa_index,
|
||||
size_t nalu_index,
|
||||
const uint8_t* frame,
|
||||
size_t frame_length,
|
||||
const uint8_t* packet,
|
||||
size_t packet_length) {
|
||||
rtc::ArrayView<const uint8_t> frame,
|
||||
rtc::ArrayView<const uint8_t> packet) {
|
||||
size_t expected_payload_offset =
|
||||
GetExpectedNaluOffset(fragmentation, first_stapa_index, nalu_index) +
|
||||
kLengthFieldLength;
|
||||
@ -128,27 +130,22 @@ void VerifyStapAPayload(const RTPFragmentationHeader& fragmentation,
|
||||
const uint8_t* expected_payload = &frame[offset];
|
||||
size_t expected_payload_length =
|
||||
fragmentation.fragmentationLength[nalu_index];
|
||||
ASSERT_LE(offset + expected_payload_length, frame_length);
|
||||
ASSERT_LE(expected_payload_offset + expected_payload_length, packet_length);
|
||||
ASSERT_LE(offset + expected_payload_length, frame.size());
|
||||
ASSERT_LE(expected_payload_offset + expected_payload_length, packet.size());
|
||||
std::vector<uint8_t> expected_payload_vector(
|
||||
expected_payload, &expected_payload[expected_payload_length]);
|
||||
EXPECT_THAT(expected_payload_vector,
|
||||
::testing::ElementsAreArray(&packet[expected_payload_offset],
|
||||
expected_payload_length));
|
||||
ElementsAreArray(&packet[expected_payload_offset],
|
||||
expected_payload_length));
|
||||
}
|
||||
|
||||
void VerifySingleNaluPayload(const RTPFragmentationHeader& fragmentation,
|
||||
size_t nalu_index,
|
||||
const uint8_t* frame,
|
||||
size_t frame_length,
|
||||
const uint8_t* packet,
|
||||
size_t packet_length) {
|
||||
std::vector<uint8_t> expected_payload_vector(
|
||||
&frame[fragmentation.fragmentationOffset[nalu_index]],
|
||||
&frame[fragmentation.fragmentationOffset[nalu_index] +
|
||||
fragmentation.fragmentationLength[nalu_index]]);
|
||||
EXPECT_THAT(expected_payload_vector,
|
||||
::testing::ElementsAreArray(packet, packet_length));
|
||||
rtc::ArrayView<const uint8_t> frame,
|
||||
rtc::ArrayView<const uint8_t> packet) {
|
||||
auto fragment = frame.subview(fragmentation.fragmentationOffset[nalu_index],
|
||||
fragmentation.fragmentationLength[nalu_index]);
|
||||
EXPECT_THAT(packet, ElementsAreArray(fragment.begin(), fragment.end()));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -161,15 +158,14 @@ TEST(RtpPacketizerH264Test, TestSingleNalu) {
|
||||
std::unique_ptr<RtpPacketizer> packetizer(
|
||||
RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
|
||||
packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation);
|
||||
uint8_t packet[kMaxPayloadSize] = {0};
|
||||
size_t length = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity());
|
||||
bool last = false;
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
EXPECT_EQ(2u, length);
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
EXPECT_EQ(2u, packet.payload_size());
|
||||
EXPECT_TRUE(last);
|
||||
VerifySingleNaluPayload(
|
||||
fragmentation, 0, frame, sizeof(frame), packet, length);
|
||||
EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last));
|
||||
VerifySingleNaluPayload(fragmentation, 0, frame, packet.payload());
|
||||
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
|
||||
}
|
||||
|
||||
TEST(RtpPacketizerH264Test, TestSingleNaluTwoPackets) {
|
||||
@ -191,19 +187,18 @@ TEST(RtpPacketizerH264Test, TestSingleNaluTwoPackets) {
|
||||
RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
|
||||
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
|
||||
|
||||
uint8_t packet[kMaxPayloadSize] = {0};
|
||||
size_t length = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
bool last = false;
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
ASSERT_EQ(fragmentation.fragmentationOffset[1], length);
|
||||
VerifySingleNaluPayload(fragmentation, 0, frame, kFrameSize, packet, length);
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
ASSERT_EQ(fragmentation.fragmentationOffset[1], packet.payload_size());
|
||||
VerifySingleNaluPayload(fragmentation, 0, frame, packet.payload());
|
||||
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
ASSERT_EQ(fragmentation.fragmentationLength[1], length);
|
||||
VerifySingleNaluPayload(fragmentation, 1, frame, kFrameSize, packet, length);
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
ASSERT_EQ(fragmentation.fragmentationLength[1], packet.payload_size());
|
||||
VerifySingleNaluPayload(fragmentation, 1, frame, packet.payload());
|
||||
EXPECT_TRUE(last);
|
||||
|
||||
EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last));
|
||||
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
|
||||
}
|
||||
|
||||
TEST(RtpPacketizerH264Test, TestStapA) {
|
||||
@ -228,18 +223,18 @@ TEST(RtpPacketizerH264Test, TestStapA) {
|
||||
RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
|
||||
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
|
||||
|
||||
uint8_t packet[kMaxPayloadSize] = {0};
|
||||
size_t length = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity());
|
||||
bool last = false;
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
size_t expected_packet_size =
|
||||
kNalHeaderSize + 3 * kLengthFieldLength + kFrameSize;
|
||||
ASSERT_EQ(expected_packet_size, length);
|
||||
ASSERT_EQ(expected_packet_size, packet.payload_size());
|
||||
EXPECT_TRUE(last);
|
||||
for (size_t i = 0; i < fragmentation.fragmentationVectorSize; ++i)
|
||||
VerifyStapAPayload(fragmentation, 0, i, frame, kFrameSize, packet, length);
|
||||
VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload());
|
||||
|
||||
EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last));
|
||||
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
|
||||
}
|
||||
|
||||
TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) {
|
||||
@ -263,27 +258,27 @@ TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) {
|
||||
RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
|
||||
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
|
||||
|
||||
uint8_t packet[kMaxPayloadSize] = {0};
|
||||
size_t length = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity());
|
||||
bool last = false;
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
size_t expected_packet_size = kNalHeaderSize;
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
expected_packet_size +=
|
||||
kLengthFieldLength + fragmentation.fragmentationLength[i];
|
||||
}
|
||||
ASSERT_EQ(expected_packet_size, length);
|
||||
ASSERT_EQ(expected_packet_size, packet.payload_size());
|
||||
EXPECT_FALSE(last);
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
VerifyStapAPayload(fragmentation, 0, i, frame, kFrameSize, packet, length);
|
||||
VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload());
|
||||
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
expected_packet_size = fragmentation.fragmentationLength[2];
|
||||
ASSERT_EQ(expected_packet_size, length);
|
||||
ASSERT_EQ(expected_packet_size, packet.payload_size());
|
||||
EXPECT_TRUE(last);
|
||||
VerifySingleNaluPayload(fragmentation, 2, frame, kFrameSize, packet, length);
|
||||
VerifySingleNaluPayload(fragmentation, 2, frame, packet.payload());
|
||||
|
||||
EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last));
|
||||
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
|
||||
}
|
||||
|
||||
TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) {
|
||||
@ -315,26 +310,26 @@ TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) {
|
||||
std::vector<size_t> fua_sizes;
|
||||
fua_sizes.push_back(1100);
|
||||
fua_sizes.push_back(1099);
|
||||
uint8_t packet[kMaxPayloadSize] = {0};
|
||||
size_t length = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity());
|
||||
bool last = false;
|
||||
int fua_offset = kNalHeaderSize;
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
VerifyFua(i, frame, fua_offset, packet, length, fua_sizes);
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
VerifyFua(i, frame, fua_offset, packet.payload(), fua_sizes);
|
||||
EXPECT_FALSE(last);
|
||||
fua_offset += fua_sizes[i];
|
||||
}
|
||||
// Then expecting one STAP-A packet with two nal units.
|
||||
ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last));
|
||||
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
|
||||
size_t expected_packet_size =
|
||||
kNalHeaderSize + 2 * kLengthFieldLength + 2 * kStapANaluSize;
|
||||
ASSERT_EQ(expected_packet_size, length);
|
||||
ASSERT_EQ(expected_packet_size, packet.payload_size());
|
||||
EXPECT_TRUE(last);
|
||||
for (size_t i = 1; i < fragmentation.fragmentationVectorSize; ++i)
|
||||
VerifyStapAPayload(fragmentation, 1, i, frame, kFrameSize, packet, length);
|
||||
VerifyStapAPayload(fragmentation, 1, i, frame, packet.payload());
|
||||
|
||||
EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last));
|
||||
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
|
||||
}
|
||||
|
||||
TEST(RtpPacketizerH264Test, TestFUAOddSize) {
|
||||
@ -429,24 +424,20 @@ TEST_F(RtpPacketizerH264TestSpsRewriting, FuASps) {
|
||||
&fragmentation_header_);
|
||||
|
||||
bool last_packet = true;
|
||||
uint8_t buffer[sizeof(kOriginalSps) + kHeaderOverhead] = {};
|
||||
size_t num_bytes = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(sizeof(kOriginalSps) + kHeaderOverhead, packet.FreeCapacity());
|
||||
|
||||
EXPECT_TRUE(packetizer_->NextPacket(buffer, &num_bytes, &last_packet));
|
||||
EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet));
|
||||
size_t offset = H264::kNaluTypeSize;
|
||||
size_t length = num_bytes - kFuAHeaderSize;
|
||||
std::vector<uint8_t> expected_payload(&kRewrittenSps[offset],
|
||||
&kRewrittenSps[offset + length]);
|
||||
EXPECT_THAT(expected_payload,
|
||||
::testing::ElementsAreArray(&buffer[kFuAHeaderSize], length));
|
||||
size_t length = packet.payload_size() - kFuAHeaderSize;
|
||||
EXPECT_THAT(packet.payload().subview(kFuAHeaderSize),
|
||||
ElementsAreArray(&kRewrittenSps[offset], length));
|
||||
offset += length;
|
||||
|
||||
EXPECT_TRUE(packetizer_->NextPacket(buffer, &num_bytes, &last_packet));
|
||||
length = num_bytes - kFuAHeaderSize;
|
||||
expected_payload = std::vector<uint8_t>(&kRewrittenSps[offset],
|
||||
&kRewrittenSps[offset + length]);
|
||||
EXPECT_THAT(expected_payload,
|
||||
::testing::ElementsAreArray(&buffer[kFuAHeaderSize], length));
|
||||
EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet));
|
||||
length = packet.payload_size() - kFuAHeaderSize;
|
||||
EXPECT_THAT(packet.payload().subview(kFuAHeaderSize),
|
||||
ElementsAreArray(&kRewrittenSps[offset], length));
|
||||
offset += length;
|
||||
|
||||
EXPECT_EQ(offset, sizeof(kRewrittenSps));
|
||||
@ -467,18 +458,14 @@ TEST_F(RtpPacketizerH264TestSpsRewriting, StapASps) {
|
||||
&fragmentation_header_);
|
||||
|
||||
bool last_packet = true;
|
||||
uint8_t buffer[kExpectedTotalSize + kHeaderOverhead] = {};
|
||||
size_t num_bytes = 0;
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
ASSERT_LE(kExpectedTotalSize + kHeaderOverhead, packet.FreeCapacity());
|
||||
|
||||
EXPECT_TRUE(packetizer_->NextPacket(buffer, &num_bytes, &last_packet));
|
||||
EXPECT_EQ(kExpectedTotalSize, num_bytes);
|
||||
|
||||
std::vector<uint8_t> expected_payload(kRewrittenSps,
|
||||
&kRewrittenSps[sizeof(kRewrittenSps)]);
|
||||
EXPECT_THAT(expected_payload,
|
||||
::testing::ElementsAreArray(
|
||||
&buffer[H264::kNaluTypeSize + kLengthFieldLength],
|
||||
sizeof(kRewrittenSps)));
|
||||
EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet));
|
||||
EXPECT_EQ(kExpectedTotalSize, packet.payload_size());
|
||||
EXPECT_THAT(packet.payload().subview(H264::kNaluTypeSize + kLengthFieldLength,
|
||||
sizeof(kRewrittenSps)),
|
||||
ElementsAreArray(kRewrittenSps));
|
||||
}
|
||||
|
||||
class RtpDepacketizerH264Test : public ::testing::Test {
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -45,32 +46,33 @@ void RtpPacketizerGeneric::SetPayloadData(
|
||||
generic_header_ = RtpFormatVideoGeneric::kFirstPacketBit;
|
||||
}
|
||||
|
||||
bool RtpPacketizerGeneric::NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool RtpPacketizerGeneric::NextPacket(RtpPacketToSend* packet,
|
||||
bool* last_packet) {
|
||||
RTC_DCHECK(packet);
|
||||
RTC_DCHECK(last_packet);
|
||||
if (payload_size_ < payload_length_) {
|
||||
payload_length_ = payload_size_;
|
||||
}
|
||||
|
||||
payload_size_ -= payload_length_;
|
||||
*bytes_to_send = payload_length_ + kGenericHeaderLength;
|
||||
assert(payload_length_ <= max_payload_len_);
|
||||
RTC_DCHECK_LE(payload_length_, max_payload_len_);
|
||||
|
||||
uint8_t* out_ptr = buffer;
|
||||
uint8_t* out_ptr =
|
||||
packet->AllocatePayload(kGenericHeaderLength + payload_length_);
|
||||
// Put generic header in packet
|
||||
if (frame_type_ == kVideoFrameKey) {
|
||||
generic_header_ |= RtpFormatVideoGeneric::kKeyFrameBit;
|
||||
}
|
||||
*out_ptr++ = generic_header_;
|
||||
out_ptr[0] = generic_header_;
|
||||
// Remove first-packet bit, following packets are intermediate
|
||||
generic_header_ &= ~RtpFormatVideoGeneric::kFirstPacketBit;
|
||||
|
||||
// Put payload in packet
|
||||
memcpy(out_ptr, payload_data_, payload_length_);
|
||||
memcpy(out_ptr + kGenericHeaderLength, payload_data_, payload_length_);
|
||||
payload_data_ += payload_length_;
|
||||
|
||||
*last_packet = payload_size_ <= 0;
|
||||
|
||||
packet->SetMarker(*last_packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -36,15 +36,11 @@ class RtpPacketizerGeneric : public RtpPacketizer {
|
||||
const RTPFragmentationHeader* fragmentation) override;
|
||||
|
||||
// Get the next payload with generic payload header.
|
||||
// buffer is a pointer to where the output will be written.
|
||||
// bytes_to_send is an output variable that will contain number of bytes
|
||||
// written to buffer. The parameter last_packet is true for the last packet of
|
||||
// the frame, false otherwise (i.e., call the function again to get the
|
||||
// next packet).
|
||||
// Returns true on success or false if there was no payload to packetize.
|
||||
bool NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) override;
|
||||
// Write payload and set marker bit of the |packet|.
|
||||
// The parameter |last_packet| is true for the last packet of the frame, false
|
||||
// otherwise (i.e., call the function again to get the next packet).
|
||||
// Returns true on success, false otherwise.
|
||||
bool NextPacket(RtpPacketToSend* packet, bool* last_packet) override;
|
||||
|
||||
ProtectionType GetProtectionType() override;
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
@ -197,9 +198,9 @@ void RtpPacketizerVp8::SetPayloadData(
|
||||
}
|
||||
}
|
||||
|
||||
bool RtpPacketizerVp8::NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) {
|
||||
bool RtpPacketizerVp8::NextPacket(RtpPacketToSend* packet, bool* last_packet) {
|
||||
RTC_DCHECK(packet);
|
||||
RTC_DCHECK(last_packet);
|
||||
if (!packets_calculated_) {
|
||||
int ret = 0;
|
||||
if (aggr_mode_ == kAggrPartitions && balance_) {
|
||||
@ -217,13 +218,14 @@ bool RtpPacketizerVp8::NextPacket(uint8_t* buffer,
|
||||
InfoStruct packet_info = packets_.front();
|
||||
packets_.pop();
|
||||
|
||||
uint8_t* buffer = packet->AllocatePayload(max_payload_len_);
|
||||
int bytes = WriteHeaderAndPayload(packet_info, buffer, max_payload_len_);
|
||||
if (bytes < 0) {
|
||||
return false;
|
||||
}
|
||||
*bytes_to_send = static_cast<size_t>(bytes);
|
||||
|
||||
packet->SetPayloadSize(bytes);
|
||||
*last_packet = packets_.empty();
|
||||
packet->SetMarker(*last_packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -65,19 +65,11 @@ class RtpPacketizerVp8 : public RtpPacketizer {
|
||||
const RTPFragmentationHeader* fragmentation) override;
|
||||
|
||||
// Get the next payload with VP8 payload header.
|
||||
// max_payload_len limits the sum length of payload and VP8 payload header.
|
||||
// buffer is a pointer to where the output will be written.
|
||||
// bytes_to_send is an output variable that will contain number of bytes
|
||||
// written to buffer. Parameter last_packet is true for the last packet of
|
||||
// the frame, false otherwise (i.e., call the function again to get the
|
||||
// next packet).
|
||||
// For the kStrict and kAggregate mode: returns the partition index from which
|
||||
// the first payload byte in the packet is taken, with the first partition
|
||||
// having index 0; returns negative on error.
|
||||
// For the kEqualSize mode: returns 0 on success, return negative on error.
|
||||
bool NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) override;
|
||||
// Write payload and set marker bit of the |packet|.
|
||||
// The parameter |last_packet| is true for the last packet of the frame, false
|
||||
// otherwise (i.e., call the function again to get the next packet).
|
||||
// Returns true on success, false otherwise.
|
||||
bool NextPacket(RtpPacketToSend* packet, bool* last_packet) override;
|
||||
|
||||
ProtectionType GetProtectionType() override;
|
||||
|
||||
|
||||
@ -17,22 +17,22 @@ namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
|
||||
constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
|
||||
|
||||
RtpFormatVp8TestHelper::RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr)
|
||||
: payload_data_(NULL),
|
||||
buffer_(NULL),
|
||||
: packet_(kNoExtensions),
|
||||
payload_data_(NULL),
|
||||
data_ptr_(NULL),
|
||||
fragmentation_(NULL),
|
||||
hdr_info_(hdr),
|
||||
payload_start_(0),
|
||||
payload_size_(0),
|
||||
buffer_size_(0),
|
||||
sloppy_partitioning_(false),
|
||||
inited_(false) {}
|
||||
|
||||
RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() {
|
||||
delete fragmentation_;
|
||||
delete [] payload_data_;
|
||||
delete [] buffer_;
|
||||
}
|
||||
|
||||
bool RtpFormatVp8TestHelper::Init(const size_t* partition_sizes,
|
||||
@ -45,9 +45,7 @@ bool RtpFormatVp8TestHelper::Init(const size_t* partition_sizes,
|
||||
for (size_t p = 0; p < num_partitions; ++p) {
|
||||
payload_size_ += partition_sizes[p];
|
||||
}
|
||||
buffer_size_ = payload_size_ + 6; // Add space for payload descriptor.
|
||||
payload_data_ = new uint8_t[payload_size_];
|
||||
buffer_ = new uint8_t[buffer_size_];
|
||||
size_t j = 0;
|
||||
// Loop through the partitions again.
|
||||
for (size_t p = 0; p < num_partitions; ++p) {
|
||||
@ -70,15 +68,13 @@ void RtpFormatVp8TestHelper::GetAllPacketsAndCheck(
|
||||
const bool* expected_frag_start,
|
||||
size_t expected_num_packets) {
|
||||
ASSERT_TRUE(inited_);
|
||||
size_t send_bytes = 0;
|
||||
bool last = false;
|
||||
for (size_t i = 0; i < expected_num_packets; ++i) {
|
||||
std::ostringstream ss;
|
||||
ss << "Checking packet " << i;
|
||||
SCOPED_TRACE(ss.str());
|
||||
EXPECT_TRUE(packetizer->NextPacket(buffer_, &send_bytes, &last));
|
||||
CheckPacket(send_bytes, expected_sizes[i], last,
|
||||
expected_frag_start[i]);
|
||||
EXPECT_TRUE(packetizer->NextPacket(&packet_, &last));
|
||||
CheckPacket(expected_sizes[i], last, expected_frag_start[i]);
|
||||
}
|
||||
EXPECT_TRUE(last);
|
||||
}
|
||||
@ -127,67 +123,68 @@ void RtpFormatVp8TestHelper::GetAllPacketsAndCheck(
|
||||
|
||||
void RtpFormatVp8TestHelper::CheckHeader(bool frag_start) {
|
||||
payload_start_ = 1;
|
||||
EXPECT_BIT_EQ(buffer_[0], 6, 0); // Check reserved bit.
|
||||
rtc::ArrayView<const uint8_t> buffer = packet_.payload();
|
||||
EXPECT_BIT_EQ(buffer[0], 6, 0); // Check reserved bit.
|
||||
|
||||
if (hdr_info_->pictureId != kNoPictureId ||
|
||||
hdr_info_->temporalIdx != kNoTemporalIdx ||
|
||||
hdr_info_->tl0PicIdx != kNoTl0PicIdx ||
|
||||
hdr_info_->keyIdx != kNoKeyIdx) {
|
||||
EXPECT_BIT_X_EQ(buffer_[0], 1);
|
||||
EXPECT_BIT_X_EQ(buffer[0], 1);
|
||||
++payload_start_;
|
||||
CheckPictureID();
|
||||
CheckTl0PicIdx();
|
||||
CheckTIDAndKeyIdx();
|
||||
} else {
|
||||
EXPECT_BIT_X_EQ(buffer_[0], 0);
|
||||
EXPECT_BIT_X_EQ(buffer[0], 0);
|
||||
}
|
||||
|
||||
EXPECT_BIT_N_EQ(buffer_[0], hdr_info_->nonReference ? 1 : 0);
|
||||
EXPECT_BIT_S_EQ(buffer_[0], frag_start ? 1 : 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], hdr_info_->nonReference ? 1 : 0);
|
||||
EXPECT_BIT_S_EQ(buffer[0], frag_start ? 1 : 0);
|
||||
|
||||
// Check partition index.
|
||||
if (!sloppy_partitioning_) {
|
||||
// The test payload data is constructed such that the payload value is the
|
||||
// same as the partition index.
|
||||
EXPECT_EQ(buffer_[0] & 0x0F, buffer_[payload_start_]);
|
||||
EXPECT_EQ(buffer[0] & 0x0F, buffer[payload_start_]);
|
||||
} else {
|
||||
// Partition should be set to 0.
|
||||
EXPECT_EQ(buffer_[0] & 0x0F, 0);
|
||||
EXPECT_EQ(buffer[0] & 0x0F, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the I bit and the PictureID field are both set in accordance
|
||||
// with the information in hdr_info_->pictureId.
|
||||
void RtpFormatVp8TestHelper::CheckPictureID() {
|
||||
auto buffer = packet_.payload();
|
||||
if (hdr_info_->pictureId != kNoPictureId) {
|
||||
EXPECT_BIT_I_EQ(buffer_[1], 1);
|
||||
EXPECT_BIT_I_EQ(buffer[1], 1);
|
||||
if (hdr_info_->pictureId > 0x7F) {
|
||||
EXPECT_BIT_EQ(buffer_[payload_start_], 7, 1);
|
||||
EXPECT_EQ(buffer_[payload_start_] & 0x7F,
|
||||
EXPECT_BIT_EQ(buffer[payload_start_], 7, 1);
|
||||
EXPECT_EQ(buffer[payload_start_] & 0x7F,
|
||||
(hdr_info_->pictureId >> 8) & 0x7F);
|
||||
EXPECT_EQ(buffer_[payload_start_ + 1],
|
||||
hdr_info_->pictureId & 0xFF);
|
||||
EXPECT_EQ(buffer[payload_start_ + 1], hdr_info_->pictureId & 0xFF);
|
||||
payload_start_ += 2;
|
||||
} else {
|
||||
EXPECT_BIT_EQ(buffer_[payload_start_], 7, 0);
|
||||
EXPECT_EQ(buffer_[payload_start_] & 0x7F,
|
||||
(hdr_info_->pictureId) & 0x7F);
|
||||
EXPECT_BIT_EQ(buffer[payload_start_], 7, 0);
|
||||
EXPECT_EQ(buffer[payload_start_] & 0x7F, (hdr_info_->pictureId) & 0x7F);
|
||||
payload_start_ += 1;
|
||||
}
|
||||
} else {
|
||||
EXPECT_BIT_I_EQ(buffer_[1], 0);
|
||||
EXPECT_BIT_I_EQ(buffer[1], 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the L bit and the TL0PICIDX field are both set in accordance
|
||||
// with the information in hdr_info_->tl0PicIdx.
|
||||
void RtpFormatVp8TestHelper::CheckTl0PicIdx() {
|
||||
auto buffer = packet_.payload();
|
||||
if (hdr_info_->tl0PicIdx != kNoTl0PicIdx) {
|
||||
EXPECT_BIT_L_EQ(buffer_[1], 1);
|
||||
EXPECT_EQ(buffer_[payload_start_], hdr_info_->tl0PicIdx);
|
||||
EXPECT_BIT_L_EQ(buffer[1], 1);
|
||||
EXPECT_EQ(buffer[payload_start_], hdr_info_->tl0PicIdx);
|
||||
++payload_start_;
|
||||
} else {
|
||||
EXPECT_BIT_L_EQ(buffer_[1], 0);
|
||||
EXPECT_BIT_L_EQ(buffer[1], 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,36 +192,39 @@ void RtpFormatVp8TestHelper::CheckTl0PicIdx() {
|
||||
// field are all set in accordance with the information in
|
||||
// hdr_info_->temporalIdx and hdr_info_->keyIdx, respectively.
|
||||
void RtpFormatVp8TestHelper::CheckTIDAndKeyIdx() {
|
||||
auto buffer = packet_.payload();
|
||||
if (hdr_info_->temporalIdx == kNoTemporalIdx &&
|
||||
hdr_info_->keyIdx == kNoKeyIdx) {
|
||||
EXPECT_BIT_T_EQ(buffer_[1], 0);
|
||||
EXPECT_BIT_K_EQ(buffer_[1], 0);
|
||||
EXPECT_BIT_T_EQ(buffer[1], 0);
|
||||
EXPECT_BIT_K_EQ(buffer[1], 0);
|
||||
return;
|
||||
}
|
||||
if (hdr_info_->temporalIdx != kNoTemporalIdx) {
|
||||
EXPECT_BIT_T_EQ(buffer_[1], 1);
|
||||
EXPECT_TID_EQ(buffer_[payload_start_], hdr_info_->temporalIdx);
|
||||
EXPECT_BIT_Y_EQ(buffer_[payload_start_], hdr_info_->layerSync ? 1 : 0);
|
||||
EXPECT_BIT_T_EQ(buffer[1], 1);
|
||||
EXPECT_TID_EQ(buffer[payload_start_], hdr_info_->temporalIdx);
|
||||
EXPECT_BIT_Y_EQ(buffer[payload_start_], hdr_info_->layerSync ? 1 : 0);
|
||||
} else {
|
||||
EXPECT_BIT_T_EQ(buffer_[1], 0);
|
||||
EXPECT_TID_EQ(buffer_[payload_start_], 0);
|
||||
EXPECT_BIT_Y_EQ(buffer_[payload_start_], 0);
|
||||
EXPECT_BIT_T_EQ(buffer[1], 0);
|
||||
EXPECT_TID_EQ(buffer[payload_start_], 0);
|
||||
EXPECT_BIT_Y_EQ(buffer[payload_start_], 0);
|
||||
}
|
||||
if (hdr_info_->keyIdx != kNoKeyIdx) {
|
||||
EXPECT_BIT_K_EQ(buffer_[1], 1);
|
||||
EXPECT_KEYIDX_EQ(buffer_[payload_start_], hdr_info_->keyIdx);
|
||||
EXPECT_BIT_K_EQ(buffer[1], 1);
|
||||
EXPECT_KEYIDX_EQ(buffer[payload_start_], hdr_info_->keyIdx);
|
||||
} else {
|
||||
EXPECT_BIT_K_EQ(buffer_[1], 0);
|
||||
EXPECT_KEYIDX_EQ(buffer_[payload_start_], 0);
|
||||
EXPECT_BIT_K_EQ(buffer[1], 0);
|
||||
EXPECT_KEYIDX_EQ(buffer[payload_start_], 0);
|
||||
}
|
||||
++payload_start_;
|
||||
}
|
||||
|
||||
// Verify that the payload (i.e., after the headers) of the packet stored in
|
||||
// buffer_ is identical to the expected (as found in data_ptr_).
|
||||
void RtpFormatVp8TestHelper::CheckPayload(size_t payload_end) {
|
||||
void RtpFormatVp8TestHelper::CheckPayload() {
|
||||
auto buffer = packet_.payload();
|
||||
size_t payload_end = buffer.size();
|
||||
for (size_t i = payload_start_; i < payload_end; ++i, ++data_ptr_)
|
||||
EXPECT_EQ(buffer_[i], *data_ptr_);
|
||||
EXPECT_EQ(buffer[i], *data_ptr_);
|
||||
}
|
||||
|
||||
// Verify that the input variable "last" agrees with the position of data_ptr_.
|
||||
@ -236,13 +236,12 @@ void RtpFormatVp8TestHelper::CheckLast(bool last) const {
|
||||
|
||||
// Verify the contents of a packet. Check the length versus expected_bytes,
|
||||
// the header, payload, and "last" flag.
|
||||
void RtpFormatVp8TestHelper::CheckPacket(size_t send_bytes,
|
||||
size_t expect_bytes,
|
||||
void RtpFormatVp8TestHelper::CheckPacket(size_t expect_bytes,
|
||||
bool last,
|
||||
bool frag_start) {
|
||||
EXPECT_EQ(expect_bytes, send_bytes);
|
||||
EXPECT_EQ(expect_bytes, packet_.payload_size());
|
||||
CheckHeader(frag_start);
|
||||
CheckPayload(send_bytes);
|
||||
CheckPayload();
|
||||
CheckLast(last);
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -41,7 +42,10 @@ class RtpFormatVp8TestHelper {
|
||||
uint8_t* payload_data() const { return payload_data_; }
|
||||
size_t payload_size() const { return payload_size_; }
|
||||
RTPFragmentationHeader* fragmentation() const { return fragmentation_; }
|
||||
size_t buffer_size() const { return buffer_size_; }
|
||||
size_t buffer_size() const {
|
||||
static constexpr size_t kVp8PayloadDescriptorMaxSize = 6;
|
||||
return payload_size_ + kVp8PayloadDescriptorMaxSize;
|
||||
}
|
||||
void set_sloppy_partitioning(bool value) { sloppy_partitioning_ = value; }
|
||||
|
||||
private:
|
||||
@ -49,19 +53,17 @@ class RtpFormatVp8TestHelper {
|
||||
void CheckPictureID();
|
||||
void CheckTl0PicIdx();
|
||||
void CheckTIDAndKeyIdx();
|
||||
void CheckPayload(size_t payload_end);
|
||||
void CheckPayload();
|
||||
void CheckLast(bool last) const;
|
||||
void CheckPacket(size_t send_bytes, size_t expect_bytes, bool last,
|
||||
bool frag_start);
|
||||
void CheckPacket(size_t expect_bytes, bool last, bool frag_start);
|
||||
|
||||
RtpPacketToSend packet_;
|
||||
uint8_t* payload_data_;
|
||||
uint8_t* buffer_;
|
||||
uint8_t* data_ptr_;
|
||||
RTPFragmentationHeader* fragmentation_;
|
||||
const RTPVideoHeaderVP8* hdr_info_;
|
||||
int payload_start_;
|
||||
size_t payload_size_;
|
||||
size_t buffer_size_;
|
||||
bool sloppy_partitioning_;
|
||||
bool inited_;
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
@ -22,6 +23,11 @@
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::ElementsAreArray;
|
||||
using ::testing::make_tuple;
|
||||
|
||||
constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
|
||||
// Payload descriptor
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
@ -100,8 +106,8 @@ TEST_F(RtpPacketizerVp8Test, TestStrictMode) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID.
|
||||
const size_t kMaxSize = 13;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kStrict);
|
||||
const size_t kMaxPayloadSize = 13;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kStrict);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -131,8 +137,8 @@ TEST_F(RtpPacketizerVp8Test, DISABLED_TestStrictEqualTightPartitions) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID.
|
||||
const int kMaxSize = 14;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kStrict);
|
||||
const int kMaxPayloadSize = 14;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kStrict);
|
||||
packetizer.SetPayloadData(helper_->payload_data(), helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
|
||||
@ -154,8 +160,8 @@ TEST_F(RtpPacketizerVp8Test, TestAggregateMode) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 20; // <= 0x7F should produce 1-byte PictureID.
|
||||
const size_t kMaxSize = 25;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
const size_t kMaxPayloadSize = 25;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -181,8 +187,8 @@ TEST_F(RtpPacketizerVp8Test, TestAggregateModeManyPartitions1) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 20; // <= 0x7F should produce 1-byte PictureID.
|
||||
const size_t kMaxSize = 1500;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
const size_t kMaxPayloadSize = 1000;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -208,8 +214,8 @@ TEST_F(RtpPacketizerVp8Test, TestAggregateModeManyPartitions2) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 20; // <= 0x7F should produce 1-byte PictureID.
|
||||
const size_t kMaxSize = 1500;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
const size_t kMaxPayloadSize = 1000;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -235,8 +241,8 @@ TEST_F(RtpPacketizerVp8Test, TestAggregateModeTwoLargePartitions) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 20; // <= 0x7F should produce 1-byte PictureID.
|
||||
const size_t kMaxSize = 1460;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
const size_t kMaxPayloadSize = 1460;
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -262,9 +268,9 @@ TEST_F(RtpPacketizerVp8Test, TestEqualSizeModeFallback) {
|
||||
const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID
|
||||
const size_t kMaxSize = 12; // Small enough to produce 4 packets.
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize);
|
||||
hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID
|
||||
const size_t kMaxPayloadSize = 12; // Small enough to produce 4 packets.
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize);
|
||||
packetizer.SetPayloadData(
|
||||
helper_->payload_data(), helper_->payload_size(), NULL);
|
||||
|
||||
@ -292,8 +298,8 @@ TEST_F(RtpPacketizerVp8Test, TestNonReferenceBit) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.nonReference = true;
|
||||
const size_t kMaxSize = 25; // Small enough to produce two packets.
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize);
|
||||
const size_t kMaxPayloadSize = 25; // Small enough to produce two packets.
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize);
|
||||
packetizer.SetPayloadData(
|
||||
helper_->payload_data(), helper_->payload_size(), NULL);
|
||||
|
||||
@ -323,9 +329,9 @@ TEST_F(RtpPacketizerVp8Test, TestTl0PicIdxAndTID) {
|
||||
hdr_info_.tl0PicIdx = 117;
|
||||
hdr_info_.temporalIdx = 2;
|
||||
hdr_info_.layerSync = true;
|
||||
// kMaxSize is only limited by allocated buffer size.
|
||||
const size_t kMaxSize = helper_->buffer_size();
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
// kMaxPayloadSize is only limited by allocated buffer size.
|
||||
const size_t kMaxPayloadSize = helper_->buffer_size();
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -352,9 +358,9 @@ TEST_F(RtpPacketizerVp8Test, TestKeyIdx) {
|
||||
ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
|
||||
|
||||
hdr_info_.keyIdx = 17;
|
||||
// kMaxSize is only limited by allocated buffer size.
|
||||
const size_t kMaxSize = helper_->buffer_size();
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
// kMaxPayloadSize is only limited by allocated buffer size.
|
||||
const size_t kMaxPayloadSize = helper_->buffer_size();
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -382,9 +388,9 @@ TEST_F(RtpPacketizerVp8Test, TestTIDAndKeyIdx) {
|
||||
|
||||
hdr_info_.temporalIdx = 1;
|
||||
hdr_info_.keyIdx = 5;
|
||||
// kMaxSize is only limited by allocated buffer size.
|
||||
const size_t kMaxSize = helper_->buffer_size();
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
|
||||
// kMaxPayloadSize is only limited by allocated buffer size.
|
||||
const size_t kMaxPayloadSize = helper_->buffer_size();
|
||||
RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kAggregate);
|
||||
packetizer.SetPayloadData(helper_->payload_data(),
|
||||
helper_->payload_size(),
|
||||
helper_->fragmentation());
|
||||
@ -432,6 +438,7 @@ TEST_F(RtpDepacketizerVp8Test, BasicHeader) {
|
||||
ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
|
||||
ExpectPacket(
|
||||
&payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
|
||||
|
||||
EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
|
||||
EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
|
||||
VerifyBasicHeader(&payload.type, 0, 1, 4);
|
||||
@ -564,7 +571,7 @@ TEST_F(RtpDepacketizerVp8Test, TooShortHeader) {
|
||||
TEST_F(RtpDepacketizerVp8Test, TestWithPacketizer) {
|
||||
const uint8_t kHeaderLength = 5;
|
||||
uint8_t data[10] = {0};
|
||||
uint8_t packet[20] = {0};
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
RTPVideoHeaderVP8 input_header;
|
||||
input_header.nonReference = true;
|
||||
input_header.pictureId = 300;
|
||||
@ -575,14 +582,16 @@ TEST_F(RtpDepacketizerVp8Test, TestWithPacketizer) {
|
||||
RtpPacketizerVp8 packetizer(input_header, 20);
|
||||
packetizer.SetPayloadData(data, 10, NULL);
|
||||
bool last;
|
||||
size_t send_bytes;
|
||||
ASSERT_TRUE(packetizer.NextPacket(packet, &send_bytes, &last));
|
||||
ASSERT_TRUE(last);
|
||||
RtpDepacketizer::ParsedPayload payload;
|
||||
ASSERT_TRUE(packetizer.NextPacket(&packet, &last));
|
||||
EXPECT_TRUE(last);
|
||||
EXPECT_TRUE(packet.Marker());
|
||||
|
||||
ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
|
||||
ExpectPacket(
|
||||
&payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
|
||||
auto rtp_payload = packet.payload();
|
||||
RtpDepacketizer::ParsedPayload payload;
|
||||
ASSERT_TRUE(
|
||||
depacketizer_->Parse(&payload, rtp_payload.data(), rtp_payload.size()));
|
||||
auto vp8_payload = rtp_payload.subview(kHeaderLength);
|
||||
ExpectPacket(&payload, vp8_payload.data(), vp8_payload.size());
|
||||
EXPECT_EQ(kVideoFrameKey, payload.frame_type);
|
||||
EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
|
||||
VerifyBasicHeader(&payload.type, 1, 1, 0);
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "webrtc/base/bitbuffer.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
|
||||
#define RETURN_FALSE_ON_ERROR(x) \
|
||||
if (!(x)) { \
|
||||
@ -545,21 +546,22 @@ void RtpPacketizerVp9::GeneratePackets() {
|
||||
assert(bytes_processed == payload_size_);
|
||||
}
|
||||
|
||||
bool RtpPacketizerVp9::NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) {
|
||||
bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet, bool* last_packet) {
|
||||
RTC_DCHECK(packet);
|
||||
RTC_DCHECK(last_packet);
|
||||
if (packets_.empty()) {
|
||||
return false;
|
||||
}
|
||||
PacketInfo packet_info = packets_.front();
|
||||
packets_.pop();
|
||||
|
||||
if (!WriteHeaderAndPayload(packet_info, buffer, bytes_to_send)) {
|
||||
if (!WriteHeaderAndPayload(packet_info, packet)) {
|
||||
return false;
|
||||
}
|
||||
*last_packet =
|
||||
packets_.empty() && (hdr_.spatial_idx == kNoSpatialIdx ||
|
||||
hdr_.spatial_idx == hdr_.num_spatial_layers - 1);
|
||||
*last_packet = packets_.empty();
|
||||
packet->SetMarker(packets_.empty() &&
|
||||
(hdr_.spatial_idx == kNoSpatialIdx ||
|
||||
hdr_.spatial_idx == hdr_.num_spatial_layers - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -600,8 +602,9 @@ bool RtpPacketizerVp9::NextPacket(uint8_t* buffer,
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
|
||||
bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info,
|
||||
uint8_t* buffer,
|
||||
size_t* bytes_to_send) const {
|
||||
RtpPacketToSend* packet) const {
|
||||
uint8_t* buffer = packet->AllocatePayload(max_payload_length_);
|
||||
RTC_DCHECK(buffer);
|
||||
size_t header_length;
|
||||
if (!WriteHeader(packet_info, buffer, &header_length))
|
||||
return false;
|
||||
@ -610,7 +613,7 @@ bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info,
|
||||
memcpy(&buffer[header_length],
|
||||
&payload_[packet_info.payload_start_pos], packet_info.size);
|
||||
|
||||
*bytes_to_send = header_length + packet_info.size;
|
||||
packet->SetPayloadSize(header_length + packet_info.size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -49,15 +49,11 @@ class RtpPacketizerVp9 : public RtpPacketizer {
|
||||
const RTPFragmentationHeader* fragmentation) override;
|
||||
|
||||
// Gets the next payload with VP9 payload header.
|
||||
// |buffer| is a pointer to where the output will be written.
|
||||
// |bytes_to_send| is an output variable that will contain number of bytes
|
||||
// written to buffer.
|
||||
// |last_packet| is true for the last packet of the frame, false otherwise
|
||||
// (i.e. call the function again to get the next packet).
|
||||
// Write payload and set marker bit of the |packet|.
|
||||
// The parameter |last_packet| is true for the last packet of the frame, false
|
||||
// otherwise (i.e., call the function again to get the next packet).
|
||||
// Returns true on success, false otherwise.
|
||||
bool NextPacket(uint8_t* buffer,
|
||||
size_t* bytes_to_send,
|
||||
bool* last_packet) override;
|
||||
bool NextPacket(RtpPacketToSend* packet, bool* last_packet) override;
|
||||
|
||||
typedef struct {
|
||||
size_t payload_start_pos;
|
||||
@ -76,8 +72,7 @@ class RtpPacketizerVp9 : public RtpPacketizer {
|
||||
// |bytes_to_send| contains the number of written bytes to the buffer.
|
||||
// Returns true on success, false otherwise.
|
||||
bool WriteHeaderAndPayload(const PacketInfo& packet_info,
|
||||
uint8_t* buffer,
|
||||
size_t* bytes_to_send) const;
|
||||
RtpPacketToSend* packet) const;
|
||||
|
||||
// Writes payload descriptor header to |buffer|.
|
||||
// Returns true on success, false otherwise.
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
@ -123,12 +124,15 @@ void ParseAndCheckPacket(const uint8_t* packet,
|
||||
|
||||
class RtpPacketizerVp9Test : public ::testing::Test {
|
||||
protected:
|
||||
RtpPacketizerVp9Test() {}
|
||||
static constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
|
||||
static constexpr size_t kMaxPacketSize = 1200;
|
||||
|
||||
RtpPacketizerVp9Test() : packet_(kNoExtensions, kMaxPacketSize) {}
|
||||
virtual void SetUp() {
|
||||
expected_.InitRTPVideoHeaderVP9();
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> packet_;
|
||||
RtpPacketToSend packet_;
|
||||
std::unique_ptr<uint8_t[]> payload_;
|
||||
size_t payload_size_;
|
||||
size_t payload_pos_;
|
||||
@ -142,9 +146,6 @@ class RtpPacketizerVp9Test : public ::testing::Test {
|
||||
payload_pos_ = 0;
|
||||
packetizer_.reset(new RtpPacketizerVp9(expected_, packet_size));
|
||||
packetizer_->SetPayloadData(payload_.get(), payload_size_, NULL);
|
||||
|
||||
const int kMaxPayloadDescriptorLength = 100;
|
||||
packet_.reset(new uint8_t[payload_size_ + kMaxPayloadDescriptorLength]);
|
||||
}
|
||||
|
||||
void CheckPayload(const uint8_t* packet,
|
||||
@ -161,20 +162,22 @@ class RtpPacketizerVp9Test : public ::testing::Test {
|
||||
const size_t* expected_sizes,
|
||||
size_t expected_num_packets) {
|
||||
ASSERT_TRUE(packetizer_.get() != NULL);
|
||||
size_t length = 0;
|
||||
bool last = false;
|
||||
if (expected_num_packets == 0) {
|
||||
EXPECT_FALSE(packetizer_->NextPacket(packet_.get(), &length, &last));
|
||||
EXPECT_FALSE(packetizer_->NextPacket(&packet_, &last));
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < expected_num_packets; ++i) {
|
||||
EXPECT_TRUE(packetizer_->NextPacket(packet_.get(), &length, &last));
|
||||
EXPECT_EQ(expected_sizes[i], length);
|
||||
EXPECT_TRUE(packetizer_->NextPacket(&packet_, &last));
|
||||
auto rtp_payload = packet_.payload();
|
||||
EXPECT_EQ(expected_sizes[i], rtp_payload.size());
|
||||
RTPVideoHeaderVP9 hdr = expected_;
|
||||
hdr.beginning_of_frame = (i == 0);
|
||||
hdr.end_of_frame = last;
|
||||
ParseAndCheckPacket(packet_.get(), hdr, expected_hdr_sizes[i], length);
|
||||
CheckPayload(packet_.get(), expected_hdr_sizes[i], length, last);
|
||||
ParseAndCheckPacket(rtp_payload.data(), hdr, expected_hdr_sizes[i],
|
||||
rtp_payload.size());
|
||||
CheckPayload(rtp_payload.data(), expected_hdr_sizes[i],
|
||||
rtp_payload.size(), last);
|
||||
}
|
||||
EXPECT_TRUE(last);
|
||||
}
|
||||
@ -429,6 +432,51 @@ TEST_F(RtpPacketizerVp9Test, TestSsData) {
|
||||
CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum);
|
||||
}
|
||||
|
||||
TEST_F(RtpPacketizerVp9Test, TestOnlyHighestSpatialLayerSetMarker) {
|
||||
const size_t kFrameSize = 10;
|
||||
const size_t kPacketSize = 9; // 2 packet per frame.
|
||||
const uint8_t kFrame[kFrameSize] = {7};
|
||||
const RTPFragmentationHeader* kNoFragmentation = nullptr;
|
||||
|
||||
RTPVideoHeaderVP9 vp9_header;
|
||||
vp9_header.InitRTPVideoHeaderVP9();
|
||||
vp9_header.flexible_mode = true;
|
||||
vp9_header.num_spatial_layers = 3;
|
||||
|
||||
RtpPacketToSend packet(kNoExtensions);
|
||||
bool last;
|
||||
|
||||
vp9_header.spatial_idx = 0;
|
||||
RtpPacketizerVp9 packetizer0(vp9_header, kPacketSize);
|
||||
packetizer0.SetPayloadData(kFrame, sizeof(kFrame), kNoFragmentation);
|
||||
ASSERT_TRUE(packetizer0.NextPacket(&packet, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_FALSE(packet.Marker());
|
||||
ASSERT_TRUE(packetizer0.NextPacket(&packet, &last));
|
||||
EXPECT_TRUE(last);
|
||||
EXPECT_FALSE(packet.Marker());
|
||||
|
||||
vp9_header.spatial_idx = 1;
|
||||
RtpPacketizerVp9 packetizer1(vp9_header, kPacketSize);
|
||||
packetizer1.SetPayloadData(kFrame, sizeof(kFrame), kNoFragmentation);
|
||||
ASSERT_TRUE(packetizer1.NextPacket(&packet, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_FALSE(packet.Marker());
|
||||
ASSERT_TRUE(packetizer1.NextPacket(&packet, &last));
|
||||
EXPECT_TRUE(last);
|
||||
EXPECT_FALSE(packet.Marker());
|
||||
|
||||
vp9_header.spatial_idx = 2;
|
||||
RtpPacketizerVp9 packetizer2(vp9_header, kPacketSize);
|
||||
packetizer2.SetPayloadData(kFrame, sizeof(kFrame), kNoFragmentation);
|
||||
ASSERT_TRUE(packetizer2.NextPacket(&packet, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_FALSE(packet.Marker());
|
||||
ASSERT_TRUE(packetizer2.NextPacket(&packet, &last));
|
||||
EXPECT_TRUE(last);
|
||||
EXPECT_TRUE(packet.Marker());
|
||||
}
|
||||
|
||||
TEST_F(RtpPacketizerVp9Test, TestBaseLayerProtectionAndStorageType) {
|
||||
const size_t kFrameSize = 10;
|
||||
const size_t kPacketSize = 12;
|
||||
|
||||
@ -362,15 +362,11 @@ bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
|
||||
bool last = false;
|
||||
while (!last) {
|
||||
std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header));
|
||||
uint8_t* payload = packet->AllocatePayload(max_data_payload_length);
|
||||
RTC_DCHECK(payload);
|
||||
|
||||
size_t payload_bytes_in_packet = 0;
|
||||
if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last))
|
||||
if (!packetizer->NextPacket(packet.get(), &last))
|
||||
return false;
|
||||
RTC_DCHECK_LE(packet->payload_size(), max_data_payload_length);
|
||||
|
||||
packet->SetPayloadSize(payload_bytes_in_packet);
|
||||
packet->SetMarker(last);
|
||||
if (!rtp_sender_->AssignSequenceNumber(packet.get()))
|
||||
return false;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user