Add VideoRtpDepacketizerGeneric

Bug: webrtc:11152
Change-Id: I27d6a62093d36a4e77dd35d4c115af8cdcc0178a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/162202
Reviewed-by: Markus Handell <handellm@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30160}
This commit is contained in:
Danil Chapovalov 2019-12-23 13:14:28 +01:00 committed by Commit Bot
parent dc7fe40f49
commit 27f4d325ad
5 changed files with 181 additions and 3 deletions

View File

@ -213,6 +213,8 @@ rtc_library("rtp_rtcp") {
"source/ulpfec_receiver_impl.cc",
"source/ulpfec_receiver_impl.h",
"source/video_rtp_depacketizer.h",
"source/video_rtp_depacketizer_generic.cc",
"source/video_rtp_depacketizer_generic.h",
"source/video_rtp_depacketizer_raw.cc",
"source/video_rtp_depacketizer_raw.h",
"source/video_rtp_depacketizer_vp8.cc",
@ -483,6 +485,7 @@ if (rtc_include_tests) {
"source/ulpfec_generator_unittest.cc",
"source/ulpfec_header_reader_writer_unittest.cc",
"source/ulpfec_receiver_unittest.cc",
"source/video_rtp_depacketizer_generic_unittest.cc",
"source/video_rtp_depacketizer_raw_unittest.cc",
"source/video_rtp_depacketizer_vp8_unittest.cc",
"source/video_rtp_depacketizer_vp9_unittest.cc",

View File

@ -16,6 +16,7 @@
#include "absl/types/optional.h"
#include "modules/rtp_rtcp/source/rtp_format.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_generic.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp8.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.h"
#include "rtc_base/checks.h"
@ -56,15 +57,18 @@ class LegacyRtpDepacketizer : public VideoRtpDepacketizer {
std::unique_ptr<VideoRtpDepacketizer> CreateVideoRtpDepacketizer(
VideoCodecType codec) {
// TODO(bugs.webrtc.org/11152): switch on codec and create specialized
// VideoRtpDepacketizers when they are migrated to new interface.
switch (codec) {
case kVideoCodecH264:
return std::make_unique<LegacyRtpDepacketizer>(codec);
case kVideoCodecVP8:
return std::make_unique<VideoRtpDepacketizerVp8>();
case kVideoCodecVP9:
return std::make_unique<VideoRtpDepacketizerVp9>();
default:
case kVideoCodecAV1:
return std::make_unique<LegacyRtpDepacketizer>(codec);
case kVideoCodecGeneric:
case kVideoCodecMultiplex:
return std::make_unique<VideoRtpDepacketizerGeneric>();
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2019 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/video_rtp_depacketizer_generic.h"
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "absl/types/optional.h"
#include "modules/rtp_rtcp/source/rtp_video_header.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/logging.h"
namespace webrtc {
namespace {
constexpr uint8_t kKeyFrameBit = 0b0000'0001;
constexpr uint8_t kFirstPacketBit = 0b0000'0010;
// If this bit is set, there will be an extended header contained in this
// packet. This was added later so old clients will not send this.
constexpr uint8_t kExtendedHeaderBit = 0b0000'0100;
constexpr size_t kGenericHeaderLength = 1;
constexpr size_t kExtendedHeaderLength = 2;
} // namespace
absl::optional<VideoRtpDepacketizer::ParsedRtpPayload>
VideoRtpDepacketizerGeneric::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
if (rtp_payload.size() == 0) {
RTC_LOG(LS_WARNING) << "Empty payload.";
return absl::nullopt;
}
absl::optional<ParsedRtpPayload> parsed(absl::in_place);
const uint8_t* payload_data = rtp_payload.cdata();
uint8_t generic_header = payload_data[0];
size_t offset = kGenericHeaderLength;
parsed->video_header.frame_type = (generic_header & kKeyFrameBit)
? VideoFrameType::kVideoFrameKey
: VideoFrameType::kVideoFrameDelta;
parsed->video_header.is_first_packet_in_frame =
(generic_header & kFirstPacketBit) != 0;
parsed->video_header.codec = kVideoCodecGeneric;
parsed->video_header.width = 0;
parsed->video_header.height = 0;
if (generic_header & kExtendedHeaderBit) {
if (rtp_payload.size() < offset + kExtendedHeaderLength) {
RTC_LOG(LS_WARNING) << "Too short payload for generic header.";
return absl::nullopt;
}
parsed->video_header.generic.emplace();
parsed->video_header.generic->frame_id =
((payload_data[1] & 0x7F) << 8) | payload_data[2];
offset += kExtendedHeaderLength;
}
parsed->video_payload =
rtp_payload.Slice(offset, rtp_payload.size() - offset);
return parsed;
}
} // namespace webrtc

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2019 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_VIDEO_RTP_DEPACKETIZER_GENERIC_H_
#define MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_GENERIC_H_
#include "absl/types/optional.h"
#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
#include "rtc_base/copy_on_write_buffer.h"
namespace webrtc {
class VideoRtpDepacketizerGeneric : public VideoRtpDepacketizer {
public:
~VideoRtpDepacketizerGeneric() override = default;
absl::optional<ParsedRtpPayload> Parse(
rtc::CopyOnWriteBuffer rtp_payload) override;
};
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_GENERIC_H_

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2019 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/video_rtp_depacketizer_generic.h"
#include <stdint.h>
#include "absl/types/optional.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::testing::SizeIs;
TEST(VideoRtpDepacketizerGeneric, NonExtendedHeaderNoFrameId) {
const size_t kRtpPayloadSize = 10;
const uint8_t kPayload[kRtpPayloadSize] = {0x01};
rtc::CopyOnWriteBuffer rtp_payload(kPayload);
VideoRtpDepacketizerGeneric depacketizer;
absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
depacketizer.Parse(rtp_payload);
ASSERT_TRUE(parsed);
EXPECT_EQ(parsed->video_header.generic, absl::nullopt);
EXPECT_THAT(parsed->video_payload, SizeIs(kRtpPayloadSize - 1));
}
TEST(VideoRtpDepacketizerGeneric, ExtendedHeaderParsesFrameId) {
const size_t kRtpPayloadSize = 10;
const uint8_t kPayload[kRtpPayloadSize] = {0x05, 0x13, 0x37};
rtc::CopyOnWriteBuffer rtp_payload(kPayload);
VideoRtpDepacketizerGeneric depacketizer;
absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
depacketizer.Parse(rtp_payload);
ASSERT_TRUE(parsed);
ASSERT_TRUE(parsed->video_header.generic);
EXPECT_EQ(parsed->video_header.generic->frame_id, 0x1337);
EXPECT_THAT(parsed->video_payload, SizeIs(kRtpPayloadSize - 3));
}
TEST(VideoRtpDepacketizerGeneric, PassRtpPayloadAsVideoPayload) {
const uint8_t kPayload[] = {0x01, 0x25, 0x52};
rtc::CopyOnWriteBuffer rtp_payload(kPayload);
VideoRtpDepacketizerGeneric depacketizer;
absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
depacketizer.Parse(rtp_payload);
ASSERT_TRUE(parsed);
// Check there was no memcpy involved by verifying return and original buffers
// point to the same buffer.
EXPECT_EQ(parsed->video_payload.cdata(), rtp_payload.cdata() + 1);
}
} // namespace
} // namespace webrtc