Add Parsing/Building generic frame descriptor extension
Bug: webrtc:9361 Change-Id: I7e85826117348e2d4f4726e8d515bb1d4a289966 Reviewed-on: https://webrtc-review.googlesource.com/83622 Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23662}
This commit is contained in:
committed by
Commit Bot
parent
709c82200f
commit
faf282700c
@ -41,6 +41,7 @@ rtc_source_set("rtp_rtcp_format") {
|
||||
"source/rtcp_packet/transport_feedback.h",
|
||||
"source/rtcp_packet/voip_metric.h",
|
||||
"source/rtp_generic_frame_descriptor.h",
|
||||
"source/rtp_generic_frame_descriptor_extension.h",
|
||||
"source/rtp_header_extensions.h",
|
||||
"source/rtp_packet.h",
|
||||
"source/rtp_packet_received.h",
|
||||
@ -75,6 +76,7 @@ rtc_source_set("rtp_rtcp_format") {
|
||||
"source/rtcp_packet/transport_feedback.cc",
|
||||
"source/rtcp_packet/voip_metric.cc",
|
||||
"source/rtp_generic_frame_descriptor.cc",
|
||||
"source/rtp_generic_frame_descriptor_extension.cc",
|
||||
"source/rtp_header_extension_map.cc",
|
||||
"source/rtp_header_extensions.cc",
|
||||
"source/rtp_packet.cc",
|
||||
@ -381,6 +383,7 @@ if (rtc_include_tests) {
|
||||
"source/rtp_format_vp8_test_helper.h",
|
||||
"source/rtp_format_vp8_unittest.cc",
|
||||
"source/rtp_format_vp9_unittest.cc",
|
||||
"source/rtp_generic_frame_descriptor_extension_unittest.cc",
|
||||
"source/rtp_header_extension_map_unittest.cc",
|
||||
"source/rtp_packet_history_unittest.cc",
|
||||
"source/rtp_packet_unittest.cc",
|
||||
|
||||
@ -51,7 +51,7 @@ void RtpGenericFrameDescriptor::SetFrameId(uint16_t frame_id) {
|
||||
}
|
||||
|
||||
rtc::ArrayView<const uint16_t>
|
||||
RtpGenericFrameDescriptor::FrameDepedenciesDiffs() const {
|
||||
RtpGenericFrameDescriptor::FrameDependenciesDiffs() const {
|
||||
RTC_DCHECK(FirstPacketInSubFrame());
|
||||
return rtc::MakeArrayView(frame_deps_id_diffs_, num_frame_deps_);
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class RtpGenericFrameDescriptor {
|
||||
uint16_t FrameId() const;
|
||||
void SetFrameId(uint16_t frame_id);
|
||||
|
||||
rtc::ArrayView<const uint16_t> FrameDepedenciesDiffs() const;
|
||||
rtc::ArrayView<const uint16_t> FrameDependenciesDiffs() const;
|
||||
void ClearFrameDependencies() { num_frame_deps_ = 0; }
|
||||
// Returns false on failure, i.e. number of dependencies is too large.
|
||||
bool AddFrameDependencyDiff(uint16_t fdiff);
|
||||
|
||||
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
constexpr uint8_t kFlagBeginOfSubframe = 0x80;
|
||||
constexpr uint8_t kFlagEndOfSubframe = 0x40;
|
||||
constexpr uint8_t kFlagFirstSubframe = 0x20;
|
||||
constexpr uint8_t kFlagLastSubframe = 0x10;
|
||||
constexpr uint8_t kFlagDependencies = 0x08;
|
||||
constexpr uint8_t kMaskTemporalLayer = 0x07;
|
||||
|
||||
constexpr uint8_t kFlagMoreDependencies = 0x01;
|
||||
constexpr uint8_t kFlageXtendedOffset = 0x02;
|
||||
|
||||
} // namespace
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |B|E|F|L|D| T |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// B: | S |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// B: + FID +
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// D: | FDIFF |X|M|
|
||||
// +---------------+
|
||||
// X: | ... |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// M: | FDIFF |X|M|
|
||||
// +---------------+
|
||||
// | ... |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
|
||||
bool RtpGenericFrameDescriptorExtension::Parse(
|
||||
rtc::ArrayView<const uint8_t> data,
|
||||
RtpGenericFrameDescriptor* descriptor) {
|
||||
if (data.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool begins_subframe = (data[0] & kFlagBeginOfSubframe) != 0;
|
||||
descriptor->SetFirstPacketInSubFrame(begins_subframe);
|
||||
descriptor->SetLastPacketInSubFrame((data[0] & kFlagEndOfSubframe) != 0);
|
||||
descriptor->SetFirstSubFrameInFrame((data[0] & kFlagFirstSubframe) != 0);
|
||||
descriptor->SetLastSubFrameInFrame((data[0] & kFlagLastSubframe) != 0);
|
||||
|
||||
// Parse Subframe details provided in 1st packet of subframe.
|
||||
if (!begins_subframe) {
|
||||
return data.size() == 1;
|
||||
}
|
||||
if (data.size() < 4) {
|
||||
return false;
|
||||
}
|
||||
descriptor->SetTemporalLayer(data[0] & kMaskTemporalLayer);
|
||||
descriptor->SetSpatialLayersBitmask(data[1]);
|
||||
descriptor->SetFrameId(data[2] | (data[3] << 8));
|
||||
|
||||
// Parse dependencies.
|
||||
descriptor->ClearFrameDependencies();
|
||||
size_t offset = 4;
|
||||
bool has_more_dependencies = (data[0] & kFlagDependencies) != 0;
|
||||
while (has_more_dependencies) {
|
||||
if (data.size() == offset)
|
||||
return false;
|
||||
has_more_dependencies = (data[offset] & kFlagMoreDependencies) != 0;
|
||||
bool extended = (data[offset] & kFlageXtendedOffset) != 0;
|
||||
uint16_t fdiff = data[offset] >> 2;
|
||||
offset++;
|
||||
if (extended) {
|
||||
if (data.size() == offset)
|
||||
return false;
|
||||
fdiff |= (data[offset] << 6);
|
||||
offset++;
|
||||
}
|
||||
if (!descriptor->AddFrameDependencyDiff(fdiff))
|
||||
return false;
|
||||
}
|
||||
return data.size() == offset;
|
||||
}
|
||||
|
||||
size_t RtpGenericFrameDescriptorExtension::ValueSize(
|
||||
const RtpGenericFrameDescriptor& descriptor) {
|
||||
if (!descriptor.FirstPacketInSubFrame())
|
||||
return 1;
|
||||
|
||||
size_t size = 4;
|
||||
for (uint16_t fdiff : descriptor.FrameDependenciesDiffs()) {
|
||||
size += (fdiff >= (1 << 6)) ? 2 : 1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool RtpGenericFrameDescriptorExtension::Write(
|
||||
rtc::ArrayView<uint8_t> data,
|
||||
const RtpGenericFrameDescriptor& descriptor) {
|
||||
RTC_CHECK_EQ(data.size(), ValueSize(descriptor));
|
||||
uint8_t base_header =
|
||||
(descriptor.FirstPacketInSubFrame() ? kFlagBeginOfSubframe : 0) |
|
||||
(descriptor.LastPacketInSubFrame() ? kFlagEndOfSubframe : 0) |
|
||||
(descriptor.FirstSubFrameInFrame() ? kFlagFirstSubframe : 0) |
|
||||
(descriptor.LastSubFrameInFrame() ? kFlagLastSubframe : 0);
|
||||
if (!descriptor.FirstPacketInSubFrame()) {
|
||||
data[0] = base_header;
|
||||
return true;
|
||||
}
|
||||
data[0] =
|
||||
base_header |
|
||||
(descriptor.FrameDependenciesDiffs().empty() ? 0 : kFlagDependencies) |
|
||||
descriptor.TemporalLayer();
|
||||
data[1] = descriptor.SpatialLayersBitmask();
|
||||
uint16_t frame_id = descriptor.FrameId();
|
||||
data[2] = frame_id & 0xff;
|
||||
data[3] = frame_id >> 8;
|
||||
rtc::ArrayView<const uint16_t> fdiffs = descriptor.FrameDependenciesDiffs();
|
||||
size_t offset = 4;
|
||||
for (size_t i = 0; i < fdiffs.size(); i++) {
|
||||
bool extended = fdiffs[i] >= (1 << 6);
|
||||
bool more = i < fdiffs.size() - 1;
|
||||
data[offset++] = ((fdiffs[i] & 0x3f) << 2) |
|
||||
(extended ? kFlageXtendedOffset : 0) |
|
||||
(more ? kFlagMoreDependencies : 0);
|
||||
if (extended) {
|
||||
data[offset++] = fdiffs[i] >> 6;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_GENERIC_FRAME_DESCRIPTOR_EXTENSION_H_
|
||||
#define MODULES_RTP_RTCP_SOURCE_RTP_GENERIC_FRAME_DESCRIPTOR_EXTENSION_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RtpGenericFrameDescriptorExtension {
|
||||
public:
|
||||
// TODO(bugs.webrtc.org/9361): Add kId and kUri to make it extension trait.
|
||||
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data,
|
||||
RtpGenericFrameDescriptor* descriptor);
|
||||
static size_t ValueSize(const RtpGenericFrameDescriptor&);
|
||||
static bool Write(rtc::ArrayView<uint8_t> data,
|
||||
const RtpGenericFrameDescriptor& descriptor);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_RTP_RTCP_SOURCE_RTP_GENERIC_FRAME_DESCRIPTOR_EXTENSION_H_
|
||||
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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 "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
|
||||
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::ElementsAreArray;
|
||||
using ::testing::IsEmpty;
|
||||
|
||||
// TODO(danilchap): Add fuzzer to test for various invalid inputs.
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest,
|
||||
ParseFirstPacketOfIndependenSubFrame) {
|
||||
const int kTemporalLayer = 5;
|
||||
constexpr uint8_t kRaw[] = {0x80 | kTemporalLayer, 0x49, 0x12, 0x34};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
|
||||
EXPECT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_FALSE(descriptor.LastPacketInSubFrame());
|
||||
EXPECT_FALSE(descriptor.FirstSubFrameInFrame());
|
||||
EXPECT_FALSE(descriptor.LastSubFrameInFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), IsEmpty());
|
||||
EXPECT_EQ(descriptor.TemporalLayer(), kTemporalLayer);
|
||||
EXPECT_EQ(descriptor.SpatialLayersBitmask(), 0x49);
|
||||
EXPECT_EQ(descriptor.FrameId(), 0x3412);
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest,
|
||||
WriteFirstPacketOfIndependenSubFrame) {
|
||||
const int kTemporalLayer = 5;
|
||||
constexpr uint8_t kRaw[] = {0x80 | kTemporalLayer, 0x49, 0x12, 0x34};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.SetTemporalLayer(kTemporalLayer);
|
||||
descriptor.SetSpatialLayersBitmask(0x49);
|
||||
descriptor.SetFrameId(0x3412);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseLastPacketOfSubFrame) {
|
||||
constexpr uint8_t kRaw[] = {0x40};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
|
||||
EXPECT_FALSE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_TRUE(descriptor.LastPacketInSubFrame());
|
||||
EXPECT_FALSE(descriptor.FirstSubFrameInFrame());
|
||||
EXPECT_FALSE(descriptor.LastSubFrameInFrame());
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteLastPacketOfSubFrame) {
|
||||
constexpr uint8_t kRaw[] = {0x40};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetLastPacketInSubFrame(true);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseFirstSubFrameInFrame) {
|
||||
constexpr uint8_t kRaw[] = {0x20};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
|
||||
EXPECT_FALSE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_FALSE(descriptor.LastPacketInSubFrame());
|
||||
EXPECT_TRUE(descriptor.FirstSubFrameInFrame());
|
||||
EXPECT_FALSE(descriptor.LastSubFrameInFrame());
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteFirstSubFrameInFrame) {
|
||||
constexpr uint8_t kRaw[] = {0x20};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstSubFrameInFrame(true);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseLastSubFrameInFrame) {
|
||||
constexpr uint8_t kRaw[] = {0x10};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
|
||||
EXPECT_FALSE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_FALSE(descriptor.LastPacketInSubFrame());
|
||||
EXPECT_FALSE(descriptor.FirstSubFrameInFrame());
|
||||
EXPECT_TRUE(descriptor.LastSubFrameInFrame());
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteLastSubFrameInFrame) {
|
||||
constexpr uint8_t kRaw[] = {0x10};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetLastSubFrameInFrame(true);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseMinShortFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 1;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x04};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteMinShortFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 1;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x04};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.AddFrameDependencyDiff(kDiff);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseMaxShortFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 0x3f;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfc};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteMaxShortFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 0x3f;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfc};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.AddFrameDependencyDiff(kDiff);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseMinLongFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 0x40;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x02, 0x01};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteMinLongFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 0x40;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x02, 0x01};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.AddFrameDependencyDiff(kDiff);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest,
|
||||
ParseLongFrameDependenciesAsBigEndian) {
|
||||
constexpr uint16_t kDiff = 0x7654 >> 2;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x54 | 0x02, 0x76};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest,
|
||||
WriteLongFrameDependenciesAsBigEndian) {
|
||||
constexpr uint16_t kDiff = 0x7654 >> 2;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x54 | 0x02, 0x76};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.AddFrameDependencyDiff(kDiff);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseMaxLongFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 0x3fff;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfe, 0xff};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteMaxLongFrameDependencies) {
|
||||
constexpr uint16_t kDiff = 0x3fff;
|
||||
constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfe, 0xff};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.AddFrameDependencyDiff(kDiff);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, ParseTwoFrameDependencies) {
|
||||
constexpr uint16_t kDiff1 = 9;
|
||||
constexpr uint16_t kDiff2 = 15;
|
||||
constexpr uint8_t kRaw[] = {
|
||||
0x88, 0x01, 0x00, 0x00, (kDiff1 << 2) | 0x01, kDiff2 << 2};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
|
||||
ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
|
||||
ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
|
||||
EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff1, kDiff2));
|
||||
}
|
||||
|
||||
TEST(RtpGenericFrameDescriptorExtensionTest, WriteTwoFrameDependencies) {
|
||||
constexpr uint16_t kDiff1 = 9;
|
||||
constexpr uint16_t kDiff2 = 15;
|
||||
constexpr uint8_t kRaw[] = {
|
||||
0x88, 0x01, 0x00, 0x00, (kDiff1 << 2) | 0x01, kDiff2 << 2};
|
||||
RtpGenericFrameDescriptor descriptor;
|
||||
descriptor.SetFirstPacketInSubFrame(true);
|
||||
descriptor.AddFrameDependencyDiff(kDiff1);
|
||||
descriptor.AddFrameDependencyDiff(kDiff2);
|
||||
|
||||
ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
|
||||
sizeof(kRaw));
|
||||
uint8_t buffer[sizeof(kRaw)];
|
||||
EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
|
||||
EXPECT_THAT(buffer, ElementsAreArray(kRaw));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
Reference in New Issue
Block a user