Include H.265 support in RTP video frame assembler.
This adds support of H.265 into the RTP video frame assembler, which is now a public interface. Bug: chromium:41480904 Change-Id: I74fd761949d0b095ba4526d2fa887e963f48abcb Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/367603 Commit-Queue: Jianlin Qiu <jianlin.qiu@intel.com> Reviewed-by: Erik Språng <sprang@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43374}
This commit is contained in:
parent
f4abc03ca2
commit
ff9e7cb182
@ -1606,6 +1606,10 @@ if (rtc_include_tests) {
|
|||||||
"//third_party/abseil-cpp/absl/strings",
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
"//third_party/abseil-cpp/absl/strings:string_view",
|
"//third_party/abseil-cpp/absl/strings:string_view",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (rtc_use_h265) {
|
||||||
|
deps += [ "video:rtp_video_frame_h265_assembler_unittests" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_library("compile_all_headers") {
|
rtc_library("compile_all_headers") {
|
||||||
|
|||||||
@ -233,6 +233,27 @@ rtc_library("rtp_video_frame_assembler_unittests") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rtc_use_h265) {
|
||||||
|
rtc_library("rtp_video_frame_h265_assembler_unittests") {
|
||||||
|
testonly = true
|
||||||
|
sources = [ "rtp_video_frame_h265_assembler_unittests.cc" ]
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
":encoded_frame",
|
||||||
|
":rtp_video_frame_assembler",
|
||||||
|
":video_frame",
|
||||||
|
":video_frame_type",
|
||||||
|
"..:array_view",
|
||||||
|
"../../modules/rtp_rtcp:rtp_rtcp",
|
||||||
|
"../../modules/rtp_rtcp:rtp_rtcp_format",
|
||||||
|
"../../modules/rtp_rtcp:rtp_video_header",
|
||||||
|
"../../modules/video_coding:codec_globals_headers",
|
||||||
|
"../../rtc_base:checks",
|
||||||
|
"../../test:test_support",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rtc_source_set("video_codec_constants") {
|
rtc_source_set("video_codec_constants") {
|
||||||
visibility = [ "*" ]
|
visibility = [ "*" ]
|
||||||
sources = [ "video_codec_constants.h" ]
|
sources = [ "video_codec_constants.h" ]
|
||||||
|
|||||||
@ -43,6 +43,10 @@
|
|||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/numerics/sequence_number_unwrapper.h"
|
#include "rtc_base/numerics/sequence_number_unwrapper.h"
|
||||||
|
|
||||||
|
#ifdef RTC_ENABLE_H265
|
||||||
|
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h265.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
std::unique_ptr<VideoRtpDepacketizer> CreateDepacketizer(
|
std::unique_ptr<VideoRtpDepacketizer> CreateDepacketizer(
|
||||||
@ -61,9 +65,11 @@ std::unique_ptr<VideoRtpDepacketizer> CreateDepacketizer(
|
|||||||
case RtpVideoFrameAssembler::kGeneric:
|
case RtpVideoFrameAssembler::kGeneric:
|
||||||
return std::make_unique<VideoRtpDepacketizerGeneric>();
|
return std::make_unique<VideoRtpDepacketizerGeneric>();
|
||||||
case RtpVideoFrameAssembler::kH265:
|
case RtpVideoFrameAssembler::kH265:
|
||||||
// TODO(bugs.webrtc.org/13485): Implement VideoRtpDepacketizerH265
|
#ifdef RTC_ENABLE_H265
|
||||||
RTC_DCHECK_NOTREACHED();
|
return std::make_unique<VideoRtpDepacketizerH265>();
|
||||||
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
RTC_DCHECK_NOTREACHED();
|
RTC_DCHECK_NOTREACHED();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
156
api/video/rtp_video_frame_h265_assembler_unittests.cc
Normal file
156
api/video/rtp_video_frame_h265_assembler_unittests.cc
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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 <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "api/array_view.h"
|
||||||
|
#include "api/video/encoded_frame.h"
|
||||||
|
#include "api/video/rtp_video_frame_assembler.h"
|
||||||
|
#include "api/video/video_codec_type.h"
|
||||||
|
#include "api/video/video_frame_type.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtp_format.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtp_video_header.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
#include "test/gmock.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::ElementsAreArray;
|
||||||
|
using ::testing::Eq;
|
||||||
|
using ::testing::IsEmpty;
|
||||||
|
using ::testing::SizeIs;
|
||||||
|
using ::testing::UnorderedElementsAre;
|
||||||
|
using PayloadFormat = RtpVideoFrameAssembler::PayloadFormat;
|
||||||
|
|
||||||
|
class PacketBuilder {
|
||||||
|
public:
|
||||||
|
explicit PacketBuilder(PayloadFormat format)
|
||||||
|
: format_(format), packet_to_send_(&extension_manager_) {}
|
||||||
|
|
||||||
|
PacketBuilder& WithSeqNum(uint16_t seq_num) {
|
||||||
|
seq_num_ = seq_num;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketBuilder& WithPayload(rtc::ArrayView<const uint8_t> payload) {
|
||||||
|
payload_.assign(payload.begin(), payload.end());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketBuilder& WithVideoHeader(const RTPVideoHeader& video_header) {
|
||||||
|
video_header_ = video_header;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
PacketBuilder& WithExtension(int id, const Args&... args) {
|
||||||
|
extension_manager_.Register<T>(id);
|
||||||
|
packet_to_send_.IdentifyExtensions(extension_manager_);
|
||||||
|
packet_to_send_.SetExtension<T>(std::forward<const Args>(args)...);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtpPacketReceived Build() {
|
||||||
|
auto packetizer =
|
||||||
|
RtpPacketizer::Create(GetVideoCodecType(), payload_, {}, video_header_);
|
||||||
|
packetizer->NextPacket(&packet_to_send_);
|
||||||
|
packet_to_send_.SetSequenceNumber(seq_num_);
|
||||||
|
|
||||||
|
RtpPacketReceived received(&extension_manager_);
|
||||||
|
received.Parse(packet_to_send_.Buffer());
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<VideoCodecType> GetVideoCodecType() {
|
||||||
|
switch (format_) {
|
||||||
|
case PayloadFormat::kH265: {
|
||||||
|
return kVideoCodecH265;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
RTC_DCHECK_NOTREACHED();
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RtpVideoFrameAssembler::PayloadFormat format_;
|
||||||
|
uint16_t seq_num_ = 0;
|
||||||
|
std::vector<uint8_t> payload_;
|
||||||
|
RTPVideoHeader video_header_;
|
||||||
|
RtpPacketReceived::ExtensionManager extension_manager_;
|
||||||
|
RtpPacketToSend packet_to_send_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AppendFrames(RtpVideoFrameAssembler::FrameVector&& from,
|
||||||
|
RtpVideoFrameAssembler::FrameVector& to) {
|
||||||
|
to.insert(to.end(), std::make_move_iterator(from.begin()),
|
||||||
|
std::make_move_iterator(from.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::ArrayView<int64_t> References(const std::unique_ptr<EncodedFrame>& frame) {
|
||||||
|
return rtc::MakeArrayView(frame->references, frame->num_references);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::ArrayView<uint8_t> Payload(const std::unique_ptr<EncodedFrame>& frame) {
|
||||||
|
return rtc::ArrayView<uint8_t>(*frame->GetEncodedData());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RtpVideoFrameH265Assembler, H265Packetization) {
|
||||||
|
RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kH265);
|
||||||
|
RtpVideoFrameAssembler::FrameVector frames;
|
||||||
|
|
||||||
|
// Key and delta frames generated on linux with ffmpeg command:
|
||||||
|
// `ffmpeg -i /dev/video0 -r 30 -c:v libx265 -s 1280x720 camera.h265`,
|
||||||
|
// truncated for test.
|
||||||
|
// IDR_N_LP(key) frame with start code included.
|
||||||
|
uint8_t kIdrPayload[] = {0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xaf,
|
||||||
|
0x08, 0x4a, 0x31, 0x11, 0x15, 0xe5, 0xc0};
|
||||||
|
// TRAIL_R(delta) frame with start code included.
|
||||||
|
uint8_t kDeltaPayload[] = {0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0xd0,
|
||||||
|
0x09, 0x7e, 0x10, 0xc6, 0x1c, 0x8c, 0x17};
|
||||||
|
|
||||||
|
RTPVideoHeader video_header;
|
||||||
|
video_header.frame_type = VideoFrameType::kVideoFrameKey;
|
||||||
|
RtpVideoFrameAssembler::FrameVector idr_frames =
|
||||||
|
assembler.InsertPacket(PacketBuilder(PayloadFormat::kH265)
|
||||||
|
.WithPayload(kIdrPayload)
|
||||||
|
.WithVideoHeader(video_header)
|
||||||
|
.WithSeqNum(10)
|
||||||
|
.Build());
|
||||||
|
AppendFrames(std::move(idr_frames), frames);
|
||||||
|
|
||||||
|
RtpVideoFrameAssembler::FrameVector delta_frames =
|
||||||
|
assembler.InsertPacket(PacketBuilder(PayloadFormat::kH265)
|
||||||
|
.WithPayload(kDeltaPayload)
|
||||||
|
.WithSeqNum(11)
|
||||||
|
.Build());
|
||||||
|
AppendFrames(std::move(delta_frames), frames);
|
||||||
|
ASSERT_THAT(frames, SizeIs(2));
|
||||||
|
|
||||||
|
auto first_frame = frames[0].ExtractFrame();
|
||||||
|
EXPECT_THAT(first_frame->Id(), Eq(10));
|
||||||
|
EXPECT_THAT(Payload(first_frame), ElementsAreArray(kIdrPayload));
|
||||||
|
EXPECT_THAT(References(first_frame), IsEmpty());
|
||||||
|
|
||||||
|
auto second_frame = frames[1].ExtractFrame();
|
||||||
|
EXPECT_THAT(second_frame->Id(), Eq(11));
|
||||||
|
EXPECT_THAT(Payload(second_frame), ElementsAreArray(kDeltaPayload));
|
||||||
|
EXPECT_THAT(References(second_frame), UnorderedElementsAre(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace webrtc
|
||||||
Loading…
x
Reference in New Issue
Block a user