mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 22:00:47 +01:00

This change adds the writing and parsing of the `abs-capture-time` RTP header extension defined at: http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time We are still missing the code to: - Negotiate the header extension. - Collect capture time for audio and video and have the info sent with the header extension. - Receive the header extension and use its info. Bug: webrtc:10739 Change-Id: I75af492e994367f45a5bdc110af199900327b126 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/144221 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Commit-Queue: Chen Xing <chxg@google.com> Cr-Commit-Position: refs/heads/master@{#28468}
150 lines
5.1 KiB
C++
150 lines
5.1 KiB
C++
/*
|
|
* 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/include/rtp_header_extension_map.h"
|
|
|
|
#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
|
|
#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
|
|
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
|
|
#include "rtc_base/arraysize.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/logging.h"
|
|
|
|
namespace webrtc {
|
|
namespace {
|
|
|
|
struct ExtensionInfo {
|
|
RTPExtensionType type;
|
|
const char* uri;
|
|
};
|
|
|
|
template <typename Extension>
|
|
constexpr ExtensionInfo CreateExtensionInfo() {
|
|
return {Extension::kId, Extension::kUri};
|
|
}
|
|
|
|
constexpr ExtensionInfo kExtensions[] = {
|
|
CreateExtensionInfo<TransmissionOffset>(),
|
|
CreateExtensionInfo<AudioLevel>(),
|
|
CreateExtensionInfo<AbsoluteSendTime>(),
|
|
CreateExtensionInfo<AbsoluteCaptureTimeExtension>(),
|
|
CreateExtensionInfo<VideoOrientation>(),
|
|
CreateExtensionInfo<TransportSequenceNumber>(),
|
|
CreateExtensionInfo<TransportSequenceNumberV2>(),
|
|
CreateExtensionInfo<PlayoutDelayLimits>(),
|
|
CreateExtensionInfo<VideoContentTypeExtension>(),
|
|
CreateExtensionInfo<VideoTimingExtension>(),
|
|
CreateExtensionInfo<FrameMarkingExtension>(),
|
|
CreateExtensionInfo<RtpStreamId>(),
|
|
CreateExtensionInfo<RepairedRtpStreamId>(),
|
|
CreateExtensionInfo<RtpMid>(),
|
|
CreateExtensionInfo<RtpGenericFrameDescriptorExtension00>(),
|
|
CreateExtensionInfo<RtpGenericFrameDescriptorExtension01>(),
|
|
CreateExtensionInfo<RtpDependencyDescriptorExtension>(),
|
|
CreateExtensionInfo<ColorSpaceExtension>(),
|
|
};
|
|
|
|
// Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual
|
|
// number of known extensions.
|
|
static_assert(arraysize(kExtensions) ==
|
|
static_cast<int>(kRtpExtensionNumberOfExtensions) - 1,
|
|
"kExtensions expect to list all known extensions");
|
|
|
|
} // namespace
|
|
|
|
constexpr RTPExtensionType RtpHeaderExtensionMap::kInvalidType;
|
|
constexpr int RtpHeaderExtensionMap::kInvalidId;
|
|
|
|
RtpHeaderExtensionMap::RtpHeaderExtensionMap() : RtpHeaderExtensionMap(false) {}
|
|
|
|
RtpHeaderExtensionMap::RtpHeaderExtensionMap(bool extmap_allow_mixed)
|
|
: extmap_allow_mixed_(extmap_allow_mixed) {
|
|
for (auto& id : ids_)
|
|
id = kInvalidId;
|
|
}
|
|
|
|
RtpHeaderExtensionMap::RtpHeaderExtensionMap(
|
|
rtc::ArrayView<const RtpExtension> extensions)
|
|
: RtpHeaderExtensionMap(false) {
|
|
for (const RtpExtension& extension : extensions)
|
|
RegisterByUri(extension.id, extension.uri);
|
|
}
|
|
|
|
bool RtpHeaderExtensionMap::RegisterByType(int id, RTPExtensionType type) {
|
|
for (const ExtensionInfo& extension : kExtensions)
|
|
if (type == extension.type)
|
|
return Register(id, extension.type, extension.uri);
|
|
RTC_NOTREACHED();
|
|
return false;
|
|
}
|
|
|
|
bool RtpHeaderExtensionMap::RegisterByUri(int id, const std::string& uri) {
|
|
for (const ExtensionInfo& extension : kExtensions)
|
|
if (uri == extension.uri)
|
|
return Register(id, extension.type, extension.uri);
|
|
RTC_LOG(LS_WARNING) << "Unknown extension uri:'" << uri << "', id: " << id
|
|
<< '.';
|
|
return false;
|
|
}
|
|
|
|
RTPExtensionType RtpHeaderExtensionMap::GetType(int id) const {
|
|
RTC_DCHECK_GE(id, RtpExtension::kMinId);
|
|
RTC_DCHECK_LE(id, RtpExtension::kMaxId);
|
|
for (int type = kRtpExtensionNone + 1; type < kRtpExtensionNumberOfExtensions;
|
|
++type) {
|
|
if (ids_[type] == id) {
|
|
return static_cast<RTPExtensionType>(type);
|
|
}
|
|
}
|
|
return kInvalidType;
|
|
}
|
|
|
|
int32_t RtpHeaderExtensionMap::Deregister(RTPExtensionType type) {
|
|
if (IsRegistered(type)) {
|
|
ids_[type] = kInvalidId;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool RtpHeaderExtensionMap::Register(int id,
|
|
RTPExtensionType type,
|
|
const char* uri) {
|
|
RTC_DCHECK_GT(type, kRtpExtensionNone);
|
|
RTC_DCHECK_LT(type, kRtpExtensionNumberOfExtensions);
|
|
|
|
if (id < RtpExtension::kMinId || id > RtpExtension::kMaxId) {
|
|
RTC_LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
|
|
<< "' with invalid id:" << id << ".";
|
|
return false;
|
|
}
|
|
|
|
RTPExtensionType registered_type = GetType(id);
|
|
if (registered_type == type) { // Same type/id pair already registered.
|
|
RTC_LOG(LS_VERBOSE) << "Reregistering extension uri:'" << uri
|
|
<< "', id:" << id;
|
|
return true;
|
|
}
|
|
|
|
if (registered_type !=
|
|
kInvalidType) { // |id| used by another extension type.
|
|
RTC_LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
|
|
<< "', id:" << id
|
|
<< ". Id already in use by extension type "
|
|
<< static_cast<int>(registered_type);
|
|
return false;
|
|
}
|
|
RTC_DCHECK(!IsRegistered(type));
|
|
|
|
// There is a run-time check above id fits into uint8_t.
|
|
ids_[type] = static_cast<uint8_t>(id);
|
|
return true;
|
|
}
|
|
|
|
} // namespace webrtc
|