Use parsed packet from RtpTransport::DemuxPacket in engine and call

With this cl, a packet is only parsed once in RtpTransport::DemuxPacket and the metadata is reused.
Extensions are still identified twice- one for demuxing based on mid. The second time in Channel::OnReceivedPacket in order to use extensions specific to that mid.

Bug: webrtc:7135, webrtc:14795
Change-Id: I50e3814af92ca4378f148876b20a54bcfac1e146
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290540
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39058}
This commit is contained in:
Per K 2023-01-10 14:28:25 +01:00 committed by WebRTC LUCI CQ
parent 7ef0c1aff5
commit 89ca299161
17 changed files with 291 additions and 196 deletions

View File

@ -26,9 +26,13 @@ class PacketReceiver {
DELIVERY_PACKET_ERROR, DELIVERY_PACKET_ERROR,
}; };
// TODO(perkj, https://bugs.webrtc.org/7135): Remove this method. This method
// is no longer used by PeerConnections. Some tests still use it.
virtual DeliveryStatus DeliverPacket(MediaType media_type, virtual DeliveryStatus DeliverPacket(MediaType media_type,
rtc::CopyOnWriteBuffer packet, rtc::CopyOnWriteBuffer packet,
int64_t packet_time_us) = 0; int64_t packet_time_us) {
RTC_CHECK_NOTREACHED();
}
// Demux RTCP packets. Must be called on the worker thread. // Demux RTCP packets. Must be called on the worker thread.
virtual void DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) { virtual void DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) {

View File

@ -541,6 +541,7 @@ rtc_library("rtc_audio_video") {
] ]
absl_deps = [ absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/functional:bind_front",
"//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional", "//third_party/abseil-cpp/absl/types:optional",
] ]

View File

@ -28,6 +28,7 @@
#include "media/base/stream_params.h" #include "media/base/stream_params.h"
#include "media/engine/webrtc_video_engine.h" #include "media/engine/webrtc_video_engine.h"
#include "modules/audio_processing/include/audio_processing.h" #include "modules/audio_processing/include/audio_processing.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/network_route.h" #include "rtc_base/network_route.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
@ -296,9 +297,9 @@ class RtpHelper : public Base {
void set_recv_rtcp_parameters(const RtcpParameters& params) { void set_recv_rtcp_parameters(const RtcpParameters& params) {
recv_rtcp_parameters_ = params; recv_rtcp_parameters_ = params;
} }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override {
int64_t packet_time_us) override { rtp_packets_.push_back(
rtp_packets_.push_back(std::string(packet.cdata<char>(), packet.size())); std::string(packet.Buffer().cdata<char>(), packet.size()));
} }
void OnPacketSent(const rtc::SentPacket& sent_packet) override {} void OnPacketSent(const rtc::SentPacket& sent_packet) override {}
void OnReadyToSend(bool ready) override { ready_to_send_ = ready; } void OnReadyToSend(bool ready) override { ready_to_send_ = ready; }

View File

@ -20,6 +20,7 @@
#include "api/task_queue/task_queue_base.h" #include "api/task_queue/task_queue_base.h"
#include "media/base/media_channel.h" #include "media/base/media_channel.h"
#include "media/base/rtp_utils.h" #include "media/base/rtp_utils.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/rtp_rtcp/source/rtp_util.h" #include "modules/rtp_rtcp/source/rtp_util.h"
#include "rtc_base/byte_order.h" #include "rtc_base/byte_order.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
@ -27,6 +28,7 @@
#include "rtc_base/dscp.h" #include "rtc_base/dscp.h"
#include "rtc_base/synchronization/mutex.h" #include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
namespace cricket { namespace cricket {
@ -167,7 +169,14 @@ class FakeNetworkInterface : public MediaChannelNetworkInterface {
thread_->PostTask( thread_->PostTask(
SafeTask(safety_.flag(), [this, packet = std::move(packet)]() mutable { SafeTask(safety_.flag(), [this, packet = std::move(packet)]() mutable {
if (dest_) { if (dest_) {
dest_->OnPacketReceived(std::move(packet), rtc::TimeMicros()); webrtc::RtpPacketReceived parsed_packet;
if (parsed_packet.Parse(packet)) {
parsed_packet.set_arrival_time(
webrtc::Timestamp::Micros(rtc::TimeMicros()));
dest_->OnPacketReceived(std::move(parsed_packet));
} else {
RTC_DCHECK_NOTREACHED();
}
} }
})); }));
} }

View File

@ -46,6 +46,7 @@
#include "media/base/stream_params.h" #include "media/base/stream_params.h"
#include "modules/audio_processing/include/audio_processing_statistics.h" #include "modules/audio_processing/include/audio_processing_statistics.h"
#include "modules/rtp_rtcp/include/report_block_data.h" #include "modules/rtp_rtcp/include/report_block_data.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/async_packet_socket.h" #include "rtc_base/async_packet_socket.h"
#include "rtc_base/buffer.h" #include "rtc_base/buffer.h"
#include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/copy_on_write_buffer.h"
@ -194,8 +195,7 @@ class MediaBaseChannelInterface {
// channel). // channel).
// Called on the network when an RTP packet is received. // Called on the network when an RTP packet is received.
virtual void OnPacketReceived(rtc::CopyOnWriteBuffer packet, virtual void OnPacketReceived(const webrtc::RtpPacketReceived& packet) = 0;
int64_t packet_time_us) = 0;
// Called on the network thread after a transport has finished sending a // Called on the network thread after a transport has finished sending a
// packet. // packet.
virtual void OnPacketSent(const rtc::SentPacket& sent_packet) = 0; virtual void OnPacketSent(const rtc::SentPacket& sent_packet) = 0;

View File

@ -45,6 +45,7 @@
#include "media/base/codec.h" #include "media/base/codec.h"
#include "media/base/media_channel.h" #include "media/base/media_channel.h"
#include "media/base/stream_params.h" #include "media/base/stream_params.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/async_packet_socket.h" #include "rtc_base/async_packet_socket.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/copy_on_write_buffer.h"
@ -89,8 +90,7 @@ class MediaChannel : public MediaSendChannelInterface,
// even when abstract, to tell the compiler that all instances of the name // even when abstract, to tell the compiler that all instances of the name
// referred to by subclasses of this share the same implementation. // referred to by subclasses of this share the same implementation.
cricket::MediaType media_type() const override = 0; cricket::MediaType media_type() const override = 0;
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override = 0;
int64_t packet_time_us) override = 0;
void OnPacketSent(const rtc::SentPacket& sent_packet) override = 0; void OnPacketSent(const rtc::SentPacket& sent_packet) override = 0;
void OnReadyToSend(bool ready) override = 0; void OnReadyToSend(bool ready) override = 0;
void OnNetworkRouteChanged(absl::string_view transport_name, void OnNetworkRouteChanged(absl::string_view transport_name,
@ -305,9 +305,8 @@ class VoiceMediaSendChannel : public VoiceMediaSendChannelInterface {
// Implementation of MediaBaseChannelInterface // Implementation of MediaBaseChannelInterface
cricket::MediaType media_type() const override { return MEDIA_TYPE_AUDIO; } cricket::MediaType media_type() const override { return MEDIA_TYPE_AUDIO; }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override {
int64_t packet_time_us) override { impl()->OnPacketReceived(packet);
impl()->OnPacketReceived(packet, packet_time_us);
} }
void OnPacketSent(const rtc::SentPacket& sent_packet) override { void OnPacketSent(const rtc::SentPacket& sent_packet) override {
impl()->OnPacketSent(sent_packet); impl()->OnPacketSent(sent_packet);
@ -386,9 +385,8 @@ class VoiceMediaReceiveChannel : public VoiceMediaReceiveChannelInterface {
virtual ~VoiceMediaReceiveChannel() {} virtual ~VoiceMediaReceiveChannel() {}
// Implementation of MediaBaseChannelInterface // Implementation of MediaBaseChannelInterface
cricket::MediaType media_type() const override { return MEDIA_TYPE_AUDIO; } cricket::MediaType media_type() const override { return MEDIA_TYPE_AUDIO; }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override {
int64_t packet_time_us) override { impl()->OnPacketReceived(packet);
impl()->OnPacketReceived(packet, packet_time_us);
} }
void OnPacketSent(const rtc::SentPacket& sent_packet) override { void OnPacketSent(const rtc::SentPacket& sent_packet) override {
impl()->OnPacketSent(sent_packet); impl()->OnPacketSent(sent_packet);
@ -491,9 +489,8 @@ class VideoMediaSendChannel : public VideoMediaSendChannelInterface {
// Implementation of MediaBaseChannelInterface // Implementation of MediaBaseChannelInterface
cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; } cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override {
int64_t packet_time_us) override { impl()->OnPacketReceived(packet);
impl()->OnPacketReceived(packet, packet_time_us);
} }
void OnPacketSent(const rtc::SentPacket& sent_packet) override { void OnPacketSent(const rtc::SentPacket& sent_packet) override {
impl()->OnPacketSent(sent_packet); impl()->OnPacketSent(sent_packet);
@ -580,9 +577,8 @@ class VideoMediaReceiveChannel : public VideoMediaReceiveChannelInterface {
explicit VideoMediaReceiveChannel(VideoMediaChannel* impl) : impl_(impl) {} explicit VideoMediaReceiveChannel(VideoMediaChannel* impl) : impl_(impl) {}
// Implementation of MediaBaseChannelInterface // Implementation of MediaBaseChannelInterface
cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; } cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override {
int64_t packet_time_us) override { impl()->OnPacketReceived(packet);
impl()->OnPacketReceived(packet, packet_time_us);
} }
void OnPacketSent(const rtc::SentPacket& sent_packet) override { void OnPacketSent(const rtc::SentPacket& sent_packet) override {
impl()->OnPacketSent(sent_packet); impl()->OnPacketSent(sent_packet);

View File

@ -696,6 +696,7 @@ void FakeCall::DeliverRtpPacket(
packet.arrival_time()); packet.arrival_time());
} }
} }
last_received_rtp_packet_ = packet;
} }
bool FakeCall::DeliverPacketInternal(webrtc::MediaType media_type, bool FakeCall::DeliverPacketInternal(webrtc::MediaType media_type,

View File

@ -384,6 +384,9 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
const std::vector<FakeFlexfecReceiveStream*>& GetFlexfecReceiveStreams(); const std::vector<FakeFlexfecReceiveStream*>& GetFlexfecReceiveStreams();
rtc::SentPacket last_sent_packet() const { return last_sent_packet_; } rtc::SentPacket last_sent_packet() const { return last_sent_packet_; }
const webrtc::RtpPacketReceived& last_received_rtp_packet() const {
return last_received_rtp_packet_;
}
size_t GetDeliveredPacketsForSsrc(uint32_t ssrc) const { size_t GetDeliveredPacketsForSsrc(uint32_t ssrc) const {
auto it = delivered_packets_by_ssrc_.find(ssrc); auto it = delivered_packets_by_ssrc_.find(ssrc);
return it != delivered_packets_by_ssrc_.end() ? it->second : 0u; return it != delivered_packets_by_ssrc_.end() ? it->second : 0u;
@ -489,6 +492,7 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
webrtc::NetworkState audio_network_state_; webrtc::NetworkState audio_network_state_;
webrtc::NetworkState video_network_state_; webrtc::NetworkState video_network_state_;
rtc::SentPacket last_sent_packet_; rtc::SentPacket last_sent_packet_;
webrtc::RtpPacketReceived last_received_rtp_packet_;
int last_sent_nonnegative_packet_id_ = -1; int last_sent_nonnegative_packet_id_ = -1;
int next_stream_id_ = 665; int next_stream_id_ = 665;
webrtc::Call::Stats stats_; webrtc::Call::Stats stats_;

View File

@ -18,6 +18,7 @@
#include <utility> #include <utility>
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "absl/functional/bind_front.h"
#include "absl/strings/match.h" #include "absl/strings/match.h"
#include "api/media_stream_interface.h" #include "api/media_stream_interface.h"
#include "api/video/video_codec_constants.h" #include "api/video/video_codec_constants.h"
@ -29,6 +30,7 @@
#include "call/call.h" #include "call/call.h"
#include "media/engine/webrtc_media_engine.h" #include "media/engine/webrtc_media_engine.h"
#include "media/engine/webrtc_voice_engine.h" #include "media/engine/webrtc_voice_engine.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_util.h" #include "modules/rtp_rtcp/source/rtp_util.h"
#include "modules/video_coding/codecs/vp9/svc_config.h" #include "modules/video_coding/codecs/vp9/svc_config.h"
#include "modules/video_coding/svc/scalability_mode_util.h" #include "modules/video_coding/svc/scalability_mode_util.h"
@ -1196,6 +1198,8 @@ bool WebRtcVideoChannel::SetRecvParameters(const VideoRecvParameters& params) {
} }
if (changed_params.rtp_header_extensions) { if (changed_params.rtp_header_extensions) {
recv_rtp_extensions_ = *changed_params.rtp_header_extensions; recv_rtp_extensions_ = *changed_params.rtp_header_extensions;
recv_rtp_extension_map_ =
webrtc::RtpHeaderExtensionMap(recv_rtp_extensions_);
} }
if (changed_params.codec_settings) { if (changed_params.codec_settings) {
RTC_DLOG(LS_INFO) << "Changing recv codecs from " RTC_DLOG(LS_INFO) << "Changing recv codecs from "
@ -1718,111 +1722,111 @@ void WebRtcVideoChannel::FillReceiveCodecStats(
} }
} }
void WebRtcVideoChannel::OnPacketReceived(rtc::CopyOnWriteBuffer packet, void WebRtcVideoChannel::OnPacketReceived(
int64_t packet_time_us) { const webrtc::RtpPacketReceived& packet) {
RTC_DCHECK_RUN_ON(&network_thread_checker_); RTC_DCHECK_RUN_ON(&network_thread_checker_);
// TODO(bugs.webrtc.org/11993): This code is very similar to what // TODO(bugs.webrtc.org/11993): This code is very similar to what
// WebRtcVoiceMediaChannel::OnPacketReceived does. For maintainability and // WebRtcVoiceMediaChannel::OnPacketReceived does. For maintainability and
// consistency it would be good to move the interaction with call_->Receiver() // consistency it would be good to move the interaction with call_->Receiver()
// to a common implementation and provide a callback on the worker thread // to a common implementation and provide a callback on the worker thread
// for the exception case (DELIVERY_UNKNOWN_SSRC) and how retry is attempted. // for the exception case (DELIVERY_UNKNOWN_SSRC) and how retry is attempted.
worker_thread_->PostTask( worker_thread_->PostTask(
SafeTask(task_safety_.flag(), [this, packet, packet_time_us] { SafeTask(task_safety_.flag(), [this, packet = packet]() mutable {
RTC_DCHECK_RUN_ON(&thread_checker_); RTC_DCHECK_RUN_ON(&thread_checker_);
const webrtc::PacketReceiver::DeliveryStatus delivery_result =
call_->Receiver()->DeliverPacket(webrtc::MediaType::VIDEO, packet, // TODO(bugs.webrtc.org/7135): extensions in `packet` is currently set
packet_time_us); // in RtpTransport and does not neccessarily include extensions specific
switch (delivery_result) { // to this channel/MID. Also see comment in
case webrtc::PacketReceiver::DELIVERY_OK: // BaseChannel::MaybeUpdateDemuxerAndRtpExtensions_w.
return; // It would likely be good if extensions where merged per BUNDLE and
case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR: // applied directly in RtpTransport::DemuxPacket;
return; packet.IdentifyExtensions(recv_rtp_extension_map_);
case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC: packet.set_payload_type_frequency(webrtc::kVideoPayloadTypeFrequency);
break; if (!packet.arrival_time().IsFinite()) {
packet.set_arrival_time(webrtc::Timestamp::Micros(rtc::TimeMicros()));
} }
absl::optional<uint32_t> rtx_ssrc; call_->Receiver()->DeliverRtpPacket(
uint32_t ssrc = ParseRtpSsrc(packet); webrtc::MediaType::VIDEO, std::move(packet),
absl::bind_front(
&WebRtcVideoChannel::MaybeCreateDefaultReceiveStream, this));
if (discard_unknown_ssrc_packets_) {
return;
}
int payload_type = ParseRtpPayloadType(packet);
// See if this payload_type is registered as one that usually gets its
// own SSRC (RTX) or at least is safe to drop either way (FEC). If it
// is, and it wasn't handled above by DeliverPacket, that means we don't
// know what stream it associates with, and we shouldn't ever create an
// implicit channel for these.
for (auto& codec : recv_codecs_) {
if (payload_type == codec.ulpfec.red_rtx_payload_type ||
payload_type == codec.ulpfec.ulpfec_payload_type) {
return;
}
if (payload_type == codec.rtx_payload_type) {
// As we don't support receiving simulcast there can only be one RTX
// stream, which will be associated with unsignaled media stream.
// It is not possible to update the ssrcs of a receive stream, so we
// recreate it insead if found.
auto default_ssrc = GetUnsignaledSsrc();
if (!default_ssrc) {
return;
}
rtx_ssrc = ssrc;
ssrc = *default_ssrc;
// Allow recreating the receive stream even if the RTX packet is
// received just after the media packet.
last_unsignalled_ssrc_creation_time_ms_.reset();
break;
}
}
if (payload_type == recv_flexfec_payload_type_) {
return;
}
// Ignore unknown ssrcs if there is a demuxer criteria update pending.
// During a demuxer update we may receive ssrcs that were recently
// removed or we may receve ssrcs that were recently configured for a
// different video channel.
if (demuxer_criteria_id_ != demuxer_criteria_completed_id_) {
return;
}
// Ignore unknown ssrcs if we recently created an unsignalled receive
// stream since this shouldn't happen frequently. Getting into a state
// of creating decoders on every packet eats up processing time (e.g.
// https://crbug.com/1069603) and this cooldown prevents that.
if (last_unsignalled_ssrc_creation_time_ms_.has_value()) {
int64_t now_ms = rtc::TimeMillis();
if (now_ms - last_unsignalled_ssrc_creation_time_ms_.value() <
kUnsignaledSsrcCooldownMs) {
// We've already created an unsignalled ssrc stream within the last
// 0.5 s, ignore with a warning.
RTC_LOG(LS_WARNING)
<< "Another unsignalled ssrc packet arrived shortly after the "
<< "creation of an unsignalled ssrc stream. Dropping packet.";
return;
}
}
// Let the unsignalled ssrc handler decide whether to drop or deliver.
switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc,
rtx_ssrc)) {
case UnsignalledSsrcHandler::kDropPacket:
return;
case UnsignalledSsrcHandler::kDeliverPacket:
break;
}
if (call_->Receiver()->DeliverPacket(webrtc::MediaType::VIDEO, packet,
packet_time_us) !=
webrtc::PacketReceiver::DELIVERY_OK) {
RTC_LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
}
last_unsignalled_ssrc_creation_time_ms_ = rtc::TimeMillis();
})); }));
} }
bool WebRtcVideoChannel::MaybeCreateDefaultReceiveStream(
const webrtc::RtpPacketReceived& packet) {
if (discard_unknown_ssrc_packets_) {
return false;
}
absl::optional<uint32_t> rtx_ssrc;
uint32_t ssrc = packet.Ssrc();
// See if this payload_type is registered as one that usually gets its
// own SSRC (RTX) or at least is safe to drop either way (FEC). If it
// is, and it wasn't handled above by DeliverPacket, that means we don't
// know what stream it associates with, and we shouldn't ever create an
// implicit channel for these.
for (auto& codec : recv_codecs_) {
if (packet.PayloadType() == codec.ulpfec.red_rtx_payload_type ||
packet.PayloadType() == codec.ulpfec.ulpfec_payload_type) {
return false;
}
if (packet.PayloadType() == codec.rtx_payload_type) {
// As we don't support receiving simulcast there can only be one RTX
// stream, which will be associated with unsignaled media stream.
// It is not possible to update the ssrcs of a receive stream, so we
// recreate it insead if found.
auto default_ssrc = GetUnsignaledSsrc();
if (!default_ssrc) {
return false;
}
rtx_ssrc = ssrc;
ssrc = *default_ssrc;
// Allow recreating the receive stream even if the RTX packet is
// received just after the media packet.
last_unsignalled_ssrc_creation_time_ms_.reset();
break;
}
}
if (packet.PayloadType() == recv_flexfec_payload_type_) {
return false;
}
// Ignore unknown ssrcs if there is a demuxer criteria update pending.
// During a demuxer update we may receive ssrcs that were recently
// removed or we may receve ssrcs that were recently configured for a
// different video channel.
if (demuxer_criteria_id_ != demuxer_criteria_completed_id_) {
return false;
}
// Ignore unknown ssrcs if we recently created an unsignalled receive
// stream since this shouldn't happen frequently. Getting into a state
// of creating decoders on every packet eats up processing time (e.g.
// https://crbug.com/1069603) and this cooldown prevents that.
if (last_unsignalled_ssrc_creation_time_ms_.has_value()) {
int64_t now_ms = rtc::TimeMillis();
if (now_ms - last_unsignalled_ssrc_creation_time_ms_.value() <
kUnsignaledSsrcCooldownMs) {
// We've already created an unsignalled ssrc stream within the last
// 0.5 s, ignore with a warning.
RTC_LOG(LS_WARNING)
<< "Another unsignalled ssrc packet arrived shortly after the "
<< "creation of an unsignalled ssrc stream. Dropping packet.";
return false;
}
}
// Let the unsignalled ssrc handler decide whether to drop or deliver.
switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc, rtx_ssrc)) {
case UnsignalledSsrcHandler::kDropPacket:
return false;
case UnsignalledSsrcHandler::kDeliverPacket:
break;
}
last_unsignalled_ssrc_creation_time_ms_ = rtc::TimeMillis();
return true;
}
void WebRtcVideoChannel::OnPacketSent(const rtc::SentPacket& sent_packet) { void WebRtcVideoChannel::OnPacketSent(const rtc::SentPacket& sent_packet) {
RTC_DCHECK_RUN_ON(&network_thread_checker_); RTC_DCHECK_RUN_ON(&network_thread_checker_);
// TODO(tommi): We shouldn't need to go through call_ to deliver this // TODO(tommi): We shouldn't need to go through call_ to deliver this

View File

@ -176,8 +176,7 @@ class WebRtcVideoChannel : public VideoMediaChannel,
bool GetSendStats(VideoMediaSendInfo* info) override; bool GetSendStats(VideoMediaSendInfo* info) override;
bool GetReceiveStats(VideoMediaReceiveInfo* info) override; bool GetReceiveStats(VideoMediaReceiveInfo* info) override;
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override;
int64_t packet_time_us) override;
void OnPacketSent(const rtc::SentPacket& sent_packet) override; void OnPacketSent(const rtc::SentPacket& sent_packet) override;
void OnReadyToSend(bool ready) override; void OnReadyToSend(bool ready) override;
void OnNetworkRouteChanged(absl::string_view transport_name, void OnNetworkRouteChanged(absl::string_view transport_name,
@ -316,6 +315,12 @@ class WebRtcVideoChannel : public VideoMediaChannel,
ChangedRecvParameters* changed_params) const ChangedRecvParameters* changed_params) const
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_); RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
// Expected to be invoked once per packet that belongs to this channel that
// can not be demuxed.
// Returns true if a new default stream has been created.
bool MaybeCreateDefaultReceiveStream(
const webrtc::RtpPacketReceived& parsed_packet)
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
void ConfigureReceiverRtp( void ConfigureReceiverRtp(
webrtc::VideoReceiveStreamInterface::Config* config, webrtc::VideoReceiveStreamInterface::Config* config,
webrtc::FlexfecReceiveStream::Config* flexfec_config, webrtc::FlexfecReceiveStream::Config* flexfec_config,
@ -646,6 +651,8 @@ class WebRtcVideoChannel : public VideoMediaChannel,
webrtc::VideoBitrateAllocatorFactory* const bitrate_allocator_factory_ webrtc::VideoBitrateAllocatorFactory* const bitrate_allocator_factory_
RTC_GUARDED_BY(thread_checker_); RTC_GUARDED_BY(thread_checker_);
std::vector<VideoCodecSettings> recv_codecs_ RTC_GUARDED_BY(thread_checker_); std::vector<VideoCodecSettings> recv_codecs_ RTC_GUARDED_BY(thread_checker_);
webrtc::RtpHeaderExtensionMap recv_rtp_extension_map_
RTC_GUARDED_BY(thread_checker_);
std::vector<webrtc::RtpExtension> recv_rtp_extensions_ std::vector<webrtc::RtpExtension> recv_rtp_extensions_
RTC_GUARDED_BY(thread_checker_); RTC_GUARDED_BY(thread_checker_);
// See reason for keeping track of the FlexFEC payload type separately in // See reason for keeping track of the FlexFEC payload type separately in

View File

@ -11,6 +11,7 @@
#include "media/engine/webrtc_video_engine.h" #include "media/engine/webrtc_video_engine.h"
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
@ -1471,7 +1472,7 @@ class WebRtcVideoChannelEncodedFrameCallbackTest : public ::testing::Test {
buf_ptr[8] = height & 255; buf_ptr[8] = height & 255;
buf_ptr[9] = height >> 8; buf_ptr[9] = height >> 8;
channel_->OnPacketReceived(packet.Buffer(), /*packet_time_us=*/-1); channel_->OnPacketReceived(packet);
} }
void DeliverKeyFrameAndWait(uint32_t ssrc) { void DeliverKeyFrameAndWait(uint32_t ssrc) {
@ -2065,7 +2066,7 @@ TEST_F(WebRtcVideoChannelBaseTest, SetSink) {
EXPECT_TRUE(SetDefaultCodec()); EXPECT_TRUE(SetDefaultCodec());
EXPECT_TRUE(SetSend(true)); EXPECT_TRUE(SetSend(true));
EXPECT_EQ(0, renderer_.num_rendered_frames()); EXPECT_EQ(0, renderer_.num_rendered_frames());
channel_->OnPacketReceived(packet.Buffer(), /*packet_time_us=*/-1); channel_->OnPacketReceived(packet);
channel_->SetDefaultSink(&renderer_); channel_->SetDefaultSink(&renderer_);
SendFrame(); SendFrame();
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
@ -2501,7 +2502,7 @@ class WebRtcVideoChannelTest : public WebRtcVideoEngineTest {
// After receciving and processing the packet, enough time is advanced that // After receciving and processing the packet, enough time is advanced that
// the unsignalled receive stream cooldown is no longer in effect. // the unsignalled receive stream cooldown is no longer in effect.
void ReceivePacketAndAdvanceTime(const RtpPacketReceived& packet) { void ReceivePacketAndAdvanceTime(const RtpPacketReceived& packet) {
receive_channel_->OnPacketReceived(packet.Buffer(), /*packet_time_us=*/-1); receive_channel_->OnPacketReceived(packet);
rtc::Thread::Current()->ProcessMessages(0); rtc::Thread::Current()->ProcessMessages(0);
time_controller_.AdvanceTime( time_controller_.AdvanceTime(
webrtc::TimeDelta::Millis(kUnsignalledReceiveStreamCooldownMs)); webrtc::TimeDelta::Millis(kUnsignalledReceiveStreamCooldownMs));
@ -3106,6 +3107,27 @@ TEST_F(WebRtcVideoChannelTest, SetRecvRtpHeaderExtensionsRejectsDuplicateIds) {
EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_)); EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_));
} }
TEST_F(WebRtcVideoChannelTest, OnPacketReceivedIdentifiesExtensions) {
cricket::VideoRecvParameters parameters = recv_parameters_;
parameters.extensions.push_back(
RtpExtension(RtpExtension::kVideoRotationUri, /*id=*/1));
ASSERT_TRUE(channel_->SetRecvParameters(parameters));
webrtc::RtpHeaderExtensionMap extension_map(parameters.extensions);
RtpPacketReceived reference_packet(&extension_map);
reference_packet.SetExtension<webrtc::VideoOrientation>(
webrtc::VideoRotation::kVideoRotation_270);
// Create a packet without the extension map but with the same content.
RtpPacketReceived received_packet;
ASSERT_TRUE(received_packet.Parse(reference_packet.Buffer()));
receive_channel_->OnPacketReceived(received_packet);
rtc::Thread::Current()->ProcessMessages(0);
EXPECT_EQ(fake_call_->last_received_rtp_packet()
.GetExtension<webrtc::VideoOrientation>(),
webrtc::VideoRotation::kVideoRotation_270);
}
TEST_F(WebRtcVideoChannelTest, AddRecvStreamOnlyUsesOneReceiveStream) { TEST_F(WebRtcVideoChannelTest, AddRecvStreamOnlyUsesOneReceiveStream) {
EXPECT_TRUE( EXPECT_TRUE(
receive_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); receive_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
@ -6999,7 +7021,7 @@ TEST_F(WebRtcVideoChannelTest, UnsignalledSsrcHasACooldown) {
// Receive a packet for kSsrc1. // Receive a packet for kSsrc1.
RtpPacketReceived packet; RtpPacketReceived packet;
packet.SetSsrc(kSsrc1); packet.SetSsrc(kSsrc1);
receive_channel_->OnPacketReceived(packet.Buffer(), /*packet_time_us=*/-1); receive_channel_->OnPacketReceived(packet);
} }
rtc::Thread::Current()->ProcessMessages(0); rtc::Thread::Current()->ProcessMessages(0);
time_controller_.AdvanceTime( time_controller_.AdvanceTime(
@ -7014,7 +7036,7 @@ TEST_F(WebRtcVideoChannelTest, UnsignalledSsrcHasACooldown) {
// Receive a packet for kSsrc2. // Receive a packet for kSsrc2.
RtpPacketReceived packet; RtpPacketReceived packet;
packet.SetSsrc(kSsrc2); packet.SetSsrc(kSsrc2);
receive_channel_->OnPacketReceived(packet.Buffer(), /*packet_time_us=*/-1); receive_channel_->OnPacketReceived(packet);
} }
rtc::Thread::Current()->ProcessMessages(0); rtc::Thread::Current()->ProcessMessages(0);
@ -7031,7 +7053,7 @@ TEST_F(WebRtcVideoChannelTest, UnsignalledSsrcHasACooldown) {
// Receive a packet for kSsrc2. // Receive a packet for kSsrc2.
RtpPacketReceived packet; RtpPacketReceived packet;
packet.SetSsrc(kSsrc2); packet.SetSsrc(kSsrc2);
receive_channel_->OnPacketReceived(packet.Buffer(), /*packet_time_us=*/-1); receive_channel_->OnPacketReceived(packet);
} }
rtc::Thread::Current()->ProcessMessages(0); rtc::Thread::Current()->ProcessMessages(0);

View File

@ -19,6 +19,7 @@
#include <vector> #include <vector>
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "absl/functional/bind_front.h"
#include "absl/strings/match.h" #include "absl/strings/match.h"
#include "api/audio/audio_frame_processor.h" #include "api/audio/audio_frame_processor.h"
#include "api/audio_codecs/audio_codec_pair_id.h" #include "api/audio_codecs/audio_codec_pair_id.h"
@ -36,6 +37,8 @@
#include "modules/audio_mixer/audio_mixer_impl.h" #include "modules/audio_mixer/audio_mixer_impl.h"
#include "modules/audio_processing/aec_dump/aec_dump_factory.h" #include "modules/audio_processing/aec_dump/aec_dump_factory.h"
#include "modules/audio_processing/include/audio_processing.h" #include "modules/audio_processing/include/audio_processing.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/rtp_rtcp/source/rtp_util.h" #include "modules/rtp_rtcp/source/rtp_util.h"
#include "rtc_base/arraysize.h" #include "rtc_base/arraysize.h"
#include "rtc_base/byte_order.h" #include "rtc_base/byte_order.h"
@ -1353,6 +1356,8 @@ bool WebRtcVoiceMediaChannel::SetRecvParameters(
call_->trials()); call_->trials());
if (recv_rtp_extensions_ != filtered_extensions) { if (recv_rtp_extensions_ != filtered_extensions) {
recv_rtp_extensions_.swap(filtered_extensions); recv_rtp_extensions_.swap(filtered_extensions);
recv_rtp_extension_map_ =
webrtc::RtpHeaderExtensionMap(recv_rtp_extensions_);
for (auto& it : recv_streams_) { for (auto& it : recv_streams_) {
it.second->SetRtpExtensions(recv_rtp_extensions_); it.second->SetRtpExtensions(recv_rtp_extensions_);
} }
@ -2129,74 +2134,84 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
event, duration); event, duration);
} }
void WebRtcVoiceMediaChannel::OnPacketReceived(rtc::CopyOnWriteBuffer packet, void WebRtcVoiceMediaChannel::OnPacketReceived(
int64_t packet_time_us) { const webrtc::RtpPacketReceived& packet) {
RTC_DCHECK_RUN_ON(&network_thread_checker_); RTC_DCHECK_RUN_ON(&network_thread_checker_);
// TODO(bugs.webrtc.org/11993): This code is very similar to what // TODO(bugs.webrtc.org/11993): This code is very similar to what
// WebRtcVideoChannel::OnPacketReceived does. For maintainability and // WebRtcVideoChannel::OnPacketReceived does. For maintainability and
// consistency it would be good to move the interaction with call_->Receiver() // consistency it would be good to move the interaction with
// to a common implementation and provide a callback on the worker thread // call_->Receiver() to a common implementation and provide a callback on
// for the exception case (DELIVERY_UNKNOWN_SSRC) and how retry is attempted. // the worker thread for the exception case (DELIVERY_UNKNOWN_SSRC) and
worker_thread_->PostTask(SafeTask(task_safety_.flag(), [this, packet, // how retry is attempted.
packet_time_us] { worker_thread_->PostTask(
RTC_DCHECK_RUN_ON(worker_thread_); SafeTask(task_safety_.flag(), [this, packet = packet]() mutable {
RTC_DCHECK_RUN_ON(worker_thread_);
webrtc::PacketReceiver::DeliveryStatus delivery_result = // TODO(bugs.webrtc.org/7135): extensions in `packet` is currently set
call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, packet, // in RtpTransport and does not neccessarily include extensions specific
packet_time_us); // to this channel/MID. Also see comment in
// BaseChannel::MaybeUpdateDemuxerAndRtpExtensions_w.
// It would likely be good if extensions where merged per BUNDLE and
// applied directly in RtpTransport::DemuxPacket;
packet.IdentifyExtensions(recv_rtp_extension_map_);
if (!packet.arrival_time().IsFinite()) {
packet.set_arrival_time(webrtc::Timestamp::Micros(rtc::TimeMicros()));
}
if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) { call_->Receiver()->DeliverRtpPacket(
return; webrtc::MediaType::AUDIO, std::move(packet),
absl::bind_front(
&WebRtcVoiceMediaChannel::MaybeCreateDefaultReceiveStream,
this));
}));
}
bool WebRtcVoiceMediaChannel::MaybeCreateDefaultReceiveStream(
const webrtc::RtpPacketReceived& packet) {
// Create an unsignaled receive stream for this previously not received
// ssrc. If there already is N unsignaled receive streams, delete the
// oldest. See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
uint32_t ssrc = packet.Ssrc();
RTC_DCHECK(!absl::c_linear_search(unsignaled_recv_ssrcs_, ssrc));
// Add new stream.
StreamParams sp = unsignaled_stream_params_;
sp.ssrcs.push_back(ssrc);
RTC_LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
if (!AddRecvStream(sp)) {
RTC_LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
return false;
}
unsignaled_recv_ssrcs_.push_back(ssrc);
RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.NumOfUnsignaledStreams",
unsignaled_recv_ssrcs_.size(), 1, 100, 101);
// Remove oldest unsignaled stream, if we have too many.
if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
RTC_DLOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
<< remove_ssrc;
RemoveRecvStream(remove_ssrc);
}
RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
SetOutputVolume(ssrc, default_recv_volume_);
SetBaseMinimumPlayoutDelayMs(ssrc, default_recv_base_minimum_delay_ms_);
// The default sink can only be attached to one stream at a time, so we hook
// it up to the *latest* unsignaled stream we've seen, in order to support
// the case where the SSRC of one unsignaled stream changes.
if (default_sink_) {
for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
auto it = recv_streams_.find(drop_ssrc);
it->second->SetRawAudioSink(nullptr);
} }
std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
// Create an unsignaled receive stream for this previously not received new ProxySink(default_sink_.get()));
// ssrc. If there already is N unsignaled receive streams, delete the SetRawAudioSink(ssrc, std::move(proxy_sink));
// oldest. See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208 }
uint32_t ssrc = ParseRtpSsrc(packet); return true;
RTC_DCHECK(!absl::c_linear_search(unsignaled_recv_ssrcs_, ssrc));
// Add new stream.
StreamParams sp = unsignaled_stream_params_;
sp.ssrcs.push_back(ssrc);
RTC_LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
if (!AddRecvStream(sp)) {
RTC_LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
return;
}
unsignaled_recv_ssrcs_.push_back(ssrc);
RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.NumOfUnsignaledStreams",
unsignaled_recv_ssrcs_.size(), 1, 100, 101);
// Remove oldest unsignaled stream, if we have too many.
if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
RTC_DLOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
<< remove_ssrc;
RemoveRecvStream(remove_ssrc);
}
RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
SetOutputVolume(ssrc, default_recv_volume_);
SetBaseMinimumPlayoutDelayMs(ssrc, default_recv_base_minimum_delay_ms_);
// The default sink can only be attached to one stream at a time, so we hook
// it up to the *latest* unsignaled stream we've seen, in order to support
// the case where the SSRC of one unsignaled stream changes.
if (default_sink_) {
for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
auto it = recv_streams_.find(drop_ssrc);
it->second->SetRawAudioSink(nullptr);
}
std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
new ProxySink(default_sink_.get()));
SetRawAudioSink(ssrc, std::move(proxy_sink));
}
delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
packet, packet_time_us);
RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC,
delivery_result);
}));
} }
void WebRtcVoiceMediaChannel::OnPacketSent(const rtc::SentPacket& sent_packet) { void WebRtcVoiceMediaChannel::OnPacketSent(const rtc::SentPacket& sent_packet) {

View File

@ -202,8 +202,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
bool CanInsertDtmf() override; bool CanInsertDtmf() override;
bool InsertDtmf(uint32_t ssrc, int event, int duration) override; bool InsertDtmf(uint32_t ssrc, int event, int duration) override;
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override;
int64_t packet_time_us) override;
void OnPacketSent(const rtc::SentPacket& sent_packet) override; void OnPacketSent(const rtc::SentPacket& sent_packet) override;
void OnNetworkRouteChanged(absl::string_view transport_name, void OnNetworkRouteChanged(absl::string_view transport_name,
const rtc::NetworkRoute& network_route) override; const rtc::NetworkRoute& network_route) override;
@ -253,6 +252,11 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
bool DeleteVoEChannel(int channel); bool DeleteVoEChannel(int channel);
bool SetMaxSendBitrate(int bps); bool SetMaxSendBitrate(int bps);
void SetupRecording(); void SetupRecording();
// Expected to be invoked once per packet that belongs to this channel that
// can not be demuxed. Returns true if a default receive stream has been
// created.
bool MaybeCreateDefaultReceiveStream(const webrtc::RtpPacketReceived& packet);
// Check if 'ssrc' is an unsignaled stream, and if so mark it as not being // Check if 'ssrc' is an unsignaled stream, and if so mark it as not being
// unsignaled anymore (i.e. it is now removed, or signaled), and return true. // unsignaled anymore (i.e. it is now removed, or signaled), and return true.
bool MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc); bool MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc);
@ -311,6 +315,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
class WebRtcAudioReceiveStream; class WebRtcAudioReceiveStream;
std::map<uint32_t, WebRtcAudioReceiveStream*> recv_streams_; std::map<uint32_t, WebRtcAudioReceiveStream*> recv_streams_;
std::vector<webrtc::RtpExtension> recv_rtp_extensions_; std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
webrtc::RtpHeaderExtensionMap recv_rtp_extension_map_;
absl::optional<webrtc::AudioSendStream::Config::SendCodecSpec> absl::optional<webrtc::AudioSendStream::Config::SendCodecSpec>
send_codec_spec_; send_codec_spec_;

View File

@ -31,6 +31,8 @@
#include "modules/audio_device/include/mock_audio_device.h" #include "modules/audio_device/include/mock_audio_device.h"
#include "modules/audio_mixer/audio_mixer_impl.h" #include "modules/audio_mixer/audio_mixer_impl.h"
#include "modules/audio_processing/include/mock_audio_processing.h" #include "modules/audio_processing/include/mock_audio_processing.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/arraysize.h" #include "rtc_base/arraysize.h"
#include "rtc_base/byte_order.h" #include "rtc_base/byte_order.h"
#include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/numerics/safe_conversions.h"
@ -275,9 +277,9 @@ class WebRtcVoiceEngineTestFake : public ::testing::TestWithParam<bool> {
} }
void DeliverPacket(const void* data, int len) { void DeliverPacket(const void* data, int len) {
rtc::CopyOnWriteBuffer packet(reinterpret_cast<const uint8_t*>(data), len); webrtc::RtpPacketReceived packet;
receive_channel_->OnPacketReceived(packet, packet.Parse(reinterpret_cast<const uint8_t*>(data), len);
/* packet_time_us */ -1); receive_channel_->OnPacketReceived(packet);
rtc::Thread::Current()->ProcessMessages(0); rtc::Thread::Current()->ProcessMessages(0);
} }
@ -1474,6 +1476,31 @@ TEST_P(WebRtcVoiceEngineTestFake, GetRtpReceiveParametersWithUnsignaledSsrc) {
EXPECT_FALSE(rtp_parameters.encodings[0].ssrc); EXPECT_FALSE(rtp_parameters.encodings[0].ssrc);
} }
TEST_P(WebRtcVoiceEngineTestFake, OnPacketReceivedIdentifiesExtensions) {
ASSERT_TRUE(SetupChannel());
cricket::AudioRecvParameters parameters = recv_parameters_;
parameters.extensions.push_back(
RtpExtension(RtpExtension::kAudioLevelUri, /*id=*/1));
ASSERT_TRUE(channel_->SetRecvParameters(parameters));
webrtc::RtpHeaderExtensionMap extension_map(parameters.extensions);
webrtc::RtpPacketReceived reference_packet(&extension_map);
constexpr uint8_t kAudioLevel = 123;
reference_packet.SetExtension<webrtc::AudioLevel>(/*voice_activity=*/true,
kAudioLevel);
// Create a packet without the extension map but with the same content.
webrtc::RtpPacketReceived received_packet;
ASSERT_TRUE(received_packet.Parse(reference_packet.Buffer()));
receive_channel_->OnPacketReceived(received_packet);
rtc::Thread::Current()->ProcessMessages(0);
bool voice_activity;
uint8_t audio_level;
EXPECT_TRUE(call_.last_received_rtp_packet().GetExtension<webrtc::AudioLevel>(
&voice_activity, &audio_level));
EXPECT_EQ(audio_level, kAudioLevel);
}
// Test that we apply codecs properly. // Test that we apply codecs properly.
TEST_P(WebRtcVoiceEngineTestFake, SetSendCodecs) { TEST_P(WebRtcVoiceEngineTestFake, SetSendCodecs) {
EXPECT_TRUE(SetupSendStream()); EXPECT_TRUE(SetupSendStream());
@ -3419,8 +3446,9 @@ TEST_P(WebRtcVoiceEngineTestFake, DeliverAudioPacket_Call) {
const cricket::FakeAudioReceiveStream* s = const cricket::FakeAudioReceiveStream* s =
call_.GetAudioReceiveStream(kAudioSsrc); call_.GetAudioReceiveStream(kAudioSsrc);
EXPECT_EQ(0, s->received_packets()); EXPECT_EQ(0, s->received_packets());
receive_channel_->OnPacketReceived(kPcmuPacket, webrtc::RtpPacketReceived parsed_packet;
/* packet_time_us */ -1); RTC_CHECK(parsed_packet.Parse(kPcmuPacket));
receive_channel_->OnPacketReceived(parsed_packet);
rtc::Thread::Current()->ProcessMessages(0); rtc::Thread::Current()->ProcessMessages(0);
EXPECT_EQ(1, s->received_packets()); EXPECT_EQ(1, s->received_packets());

View File

@ -2803,6 +2803,7 @@ if (rtc_include_tests && !build_with_chromium) {
"../modules/audio_device", "../modules/audio_device",
"../modules/audio_processing", "../modules/audio_processing",
"../modules/audio_processing:api", "../modules/audio_processing:api",
"../modules/rtp_rtcp:rtp_rtcp_format",
"../p2p:fake_port_allocator", "../p2p:fake_port_allocator",
"../p2p:p2p_test_utils", "../p2p:p2p_test_utils",
"../p2p:rtc_p2p", "../p2p:rtc_p2p",

View File

@ -433,11 +433,7 @@ void BaseChannel::OnRtpPacket(const webrtc::RtpPacketReceived& parsed_packet) {
<< ToString(); << ToString();
return; return;
} }
media_channel_->OnPacketReceived(parsed_packet);
webrtc::Timestamp packet_time = parsed_packet.arrival_time();
media_channel_->OnPacketReceived(
parsed_packet.Buffer(),
packet_time.IsMinusInfinity() ? -1 : packet_time.us());
} }
bool BaseChannel::MaybeUpdateDemuxerAndRtpExtensions_w( bool BaseChannel::MaybeUpdateDemuxerAndRtpExtensions_w(

View File

@ -17,6 +17,7 @@
#include "api/call/audio_sink.h" #include "api/call/audio_sink.h"
#include "media/base/media_channel.h" #include "media/base/media_channel.h"
#include "media/base/media_channel_impl.h" #include "media/base/media_channel_impl.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
@ -36,7 +37,7 @@ class MockVoiceMediaChannel : public VoiceMediaChannel {
(override)); (override));
MOCK_METHOD(void, MOCK_METHOD(void,
OnPacketReceived, OnPacketReceived,
(rtc::CopyOnWriteBuffer packet, int64_t packet_time_us), (const webrtc::RtpPacketReceived& packet),
(override)); (override));
MOCK_METHOD(void, MOCK_METHOD(void,
OnPacketSent, OnPacketSent,