icecat: add release icecat-140.10.1-1gnu1 for ecne

This commit is contained in:
Ark74 2026-05-04 16:58:41 -06:00
parent a5f93cb214
commit ff85d7c623
1256 changed files with 63469 additions and 24141 deletions

View file

@ -590,6 +590,7 @@ if (rtc_include_tests) {
"../api/video:video_codec_constants",
"../api/video:video_frame",
"../api/video:video_frame_type",
"../api/video:video_layers_allocation",
"../api/video:video_rtp_headers",
"../api/video_codecs:video_codecs_api",
"../audio",

View file

@ -699,6 +699,11 @@ void RtpVideoSender::OnVideoLayersAllocationUpdated(
transport_queue_.PostTask(
SafeTask(safety_.flag(), [this, sending = std::move(sending)] {
RTC_DCHECK_RUN_ON(&transport_checker_);
// It's possible for another task to be scheduled on the transport
// checker ahead of this call that makes the sender not active.
if (!IsActive()) {
return;
}
RTC_CHECK_EQ(sending.size(), rtp_streams_.size());
for (size_t i = 0; i < sending.size(); ++i) {
SetModuleIsActive(sending[i], *rtp_streams_[i].rtp_rtcp);

View file

@ -38,6 +38,7 @@
#include "api/video/encoded_image.h"
#include "api/video/video_codec_type.h"
#include "api/video/video_frame_type.h"
#include "api/video/video_layers_allocation.h"
#include "api/video_codecs/video_encoder.h"
#include "call/rtp_config.h"
#include "call/rtp_transport_config.h"
@ -1670,4 +1671,73 @@ TEST(RtpVideoSenderTest, RetransmitsBaseLayerOnly) {
EXPECT_EQ(retransmitted_rtp_sequence_numbers, base_rtp_sequence_numbers);
}
TEST(RtpVideoSenderTest, PostTaskRaceDoesNotLeadToDanglingPointer) {
NiceMock<MockTransport> transport;
NiceMock<MockRtcpIntraFrameObserver> encoder_feedback;
GlobalSimulatedTimeController time_controller(Timestamp::Millis(1000000));
Environment env = CreateEnvironment(time_controller.GetClock(),
time_controller.CreateTaskQueueFactory());
VideoSendStream::Config config(&transport);
config.rtp.ssrcs = {kSsrc1};
SendStatisticsProxy stats_proxy(
time_controller.GetClock(), config,
VideoEncoderConfig::ContentType::kRealtimeVideo, env.field_trials());
BitrateConstraints bitrate_config = GetBitrateConfig();
RtpTransportConfig transport_config{.env = env,
.bitrate_config = bitrate_config};
RtpTransportControllerSend transport_controller(transport_config);
transport_controller.EnsureStarted();
RateLimiter retransmission_rate_limiter(time_controller.GetClock(),
kRetransmitWindowSizeMs);
std::map<uint32_t, RtpState> suspended_ssrcs;
std::map<uint32_t, RtpPayloadState> suspended_payload_states;
auto router = std::make_unique<RtpVideoSender>(
env, time_controller.GetMainThread(), suspended_ssrcs,
suspended_payload_states, config.rtp, config.rtcp_report_interval_ms,
&transport,
CreateObservers(&encoder_feedback, &stats_proxy, &stats_proxy,
&stats_proxy, nullptr, &stats_proxy),
&transport_controller, &retransmission_rate_limiter,
std::make_unique<FecControllerDefault>(env), nullptr, CryptoOptions{},
nullptr);
router->SetSending(true);
// Verify it's registered
EXPECT_TRUE(
transport_controller.packet_router()->SsrcOfFirstSender().has_value());
// Trigger race:
// 1. OnVideoLayersAllocationUpdated posts a task to re-register modules
// because it sees active_ is true.
VideoLayersAllocation allocation;
allocation.active_spatial_layers.push_back({.rtp_stream_index = 0});
router->OnVideoLayersAllocationUpdated(allocation);
// 2. Immediately set active_ to false. This happens BEFORE the posted task
// runs.
router->SetSending(false);
// 3. Let the posted task run. With the fix, it should return early and not
// re-register the module because active_ is now false.
time_controller.AdvanceTime(TimeDelta::Zero());
// 4. Verify that PacketRouter does NOT have a sender.
EXPECT_FALSE(
transport_controller.packet_router()->SsrcOfFirstSender().has_value());
// 5. Destroy the router.
router.reset();
// 6. Verify that PacketRouter still does not have a sender.
EXPECT_FALSE(
transport_controller.packet_router()->SsrcOfFirstSender().has_value());
}
} // namespace webrtc

View file

@ -230,14 +230,21 @@ void RtpPacket::SetCsrcs(rtc::ArrayView<const uint32_t> csrcs) {
RTC_DCHECK_EQ(padding_size_, 0);
RTC_DCHECK_LE(csrcs.size(), 0x0fu);
RTC_DCHECK_LE(kFixedHeaderSize + 4 * csrcs.size(), capacity());
if (csrcs.size() > kMaxCsrcs) {
RTC_LOG(LS_WARNING) << "Truncating CSRC list to spec length " << kMaxCsrcs
<< " from " << csrcs.size();
csrcs = csrcs.subview(0, kMaxCsrcs);
}
payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();
buffer_.SetSize(payload_offset_);
WriteAt(0, (data()[0] & 0xF0) | dchecked_cast<uint8_t>(csrcs.size()));
size_t offset = kFixedHeaderSize;
for (uint32_t csrc : csrcs) {
ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc);
offset += 4;
}
buffer_.SetSize(payload_offset_);
}
rtc::ArrayView<uint8_t> RtpPacket::AllocateRawExtension(int id, size_t length) {

View file

@ -27,6 +27,12 @@ class RtpPacket {
using ExtensionType = RTPExtensionType;
using ExtensionManager = RtpHeaderExtensionMap;
// Maximum number of CSRCs in an RTP packet as specified in section
// "5.1 RTP Fixed Header Fields" of RFC 3550.
// Note: This is a different limit than the one that applies to RTCP packets
// (which is specified in section 6.1).
static constexpr size_t kMaxCsrcs = 15;
// `extensions` required for SetExtension/ReserveExtension functions during
// packet creating and used if available in Parse function.
// Adding and getting extensions will fail until `extensions` is

View file

@ -71,9 +71,6 @@ class ScopedDav1dPicture
constexpr char kDav1dName[] = "dav1d";
// Calling `dav1d_data_wrap` requires a `free_callback` to be registered.
void NullFreeCallback(const uint8_t* /* buffer */, void* /* opaque */) {}
Dav1dDecoder::Dav1dDecoder() = default;
Dav1dDecoder::~Dav1dDecoder() {
@ -127,9 +124,25 @@ int32_t Dav1dDecoder::Decode(const EncodedImage& encoded_image,
ScopedDav1dData scoped_dav1d_data;
Dav1dData& dav1d_data = scoped_dav1d_data.Data();
dav1d_data_wrap(&dav1d_data, encoded_image.data(), encoded_image.size(),
/*free_callback=*/&NullFreeCallback,
/*user_data=*/nullptr);
// Calling GetEncodedData will create a new `scoped_refptr` and increment the
// ref count. By simply releasing we are now responsible for decrementing
// the ref count when appropriate, which is when dav1d calls the
// `free_callback` to indicate that the buffer is no longer needed.
EncodedImageBufferInterface* bitstream_buffer =
encoded_image.GetEncodedData().release();
// Note that the `bitstream_buffer` can have a higher capacity than what is
// actually being used, so `encoded_image.size()` should be used to get the
// actual size of the bitstream.
dav1d_data_wrap(
&dav1d_data, encoded_image.data(), encoded_image.size(),
/*free_callback=*/
[](const uint8_t* /* buffer */, void* user_data) {
auto* bb = static_cast<EncodedImageBufferInterface*>(user_data);
bb->Release();
},
/*user_data=*/bitstream_buffer);
if (int decode_res = dav1d_send_data(context_, &dav1d_data)) {
RTC_LOG(LS_WARNING)

View file

@ -0,0 +1 @@
We cherry-picked this in bug 2029776

View file

@ -133,6 +133,9 @@ OutstandingData::AckInfo OutstandingData::HandleSack(
UnwrappedTSN cumulative_tsn_ack,
rtc::ArrayView<const SackChunk::GapAckBlock> gap_ack_blocks,
bool is_in_fast_recovery) {
bool cumulative_tsn_ack_advanced =
cumulative_tsn_ack > last_cumulative_tsn_ack_;
OutstandingData::AckInfo ack_info(cumulative_tsn_ack);
// Erase all items up to cumulative_tsn_ack.
RemoveAcked(cumulative_tsn_ack, ack_info);
@ -142,7 +145,7 @@ OutstandingData::AckInfo OutstandingData::HandleSack(
// NACK and possibly mark for retransmit chunks that weren't acked.
NackBetweenAckBlocks(cumulative_tsn_ack, gap_ack_blocks, is_in_fast_recovery,
ack_info);
cumulative_tsn_ack_advanced, ack_info);
RTC_DCHECK(IsConsistent());
return ack_info;
@ -215,6 +218,7 @@ void OutstandingData::NackBetweenAckBlocks(
UnwrappedTSN cumulative_tsn_ack,
rtc::ArrayView<const SackChunk::GapAckBlock> gap_ack_blocks,
bool is_in_fast_recovery,
bool cumulative_tsn_acked_advanced,
OutstandingData::AckInfo& ack_info) {
// Mark everything between the blocks as NACKED/TO_BE_RETRANSMITTED.
// https://tools.ietf.org/html/rfc4960#section-7.2.4
@ -227,7 +231,7 @@ void OutstandingData::NackBetweenAckBlocks(
// in-flight and between gaps should be nacked. This means that SCTP relies on
// the T3-RTX-timer to re-send packets otherwise.
UnwrappedTSN max_tsn_to_nack = ack_info.highest_tsn_acked;
if (is_in_fast_recovery && cumulative_tsn_ack > last_cumulative_tsn_ack_) {
if (is_in_fast_recovery && cumulative_tsn_acked_advanced) {
// https://tools.ietf.org/html/rfc4960#section-7.2.4
// "If an endpoint is in Fast Recovery and a SACK arrives that advances
// the Cumulative TSN Ack Point, the miss indications are incremented for
@ -242,7 +246,8 @@ void OutstandingData::NackBetweenAckBlocks(
UnwrappedTSN cur_block_first_acked =
UnwrappedTSN::AddTo(cumulative_tsn_ack, block.start);
for (UnwrappedTSN tsn = prev_block_last_acked.next_value();
tsn < cur_block_first_acked && tsn <= max_tsn_to_nack;
tsn < cur_block_first_acked && tsn <= max_tsn_to_nack &&
tsn < next_tsn();
tsn = tsn.next_value()) {
ack_info.has_packet_loss |=
NackItem(tsn, /*retransmit_now=*/false,

View file

@ -320,6 +320,7 @@ class OutstandingData {
UnwrappedTSN cumulative_tsn_ack,
rtc::ArrayView<const SackChunk::GapAckBlock> gap_ack_blocks,
bool is_in_fast_recovery,
bool cumulative_tsn_acked_advanced,
OutstandingData::AckInfo& ack_info);
// Process the acknowledgement of the chunk referenced by `iter` and updates

View file

@ -252,6 +252,14 @@ bool RetransmissionQueue::IsSackValid(const SackChunk& sack) const {
} else if (cumulative_tsn_ack > outstanding_data_.highest_outstanding_tsn()) {
return false;
}
for (const auto& block : sack.gap_ack_blocks()) {
if (UnwrappedTSN::AddTo(cumulative_tsn_ack, block.end) >
outstanding_data_.highest_outstanding_tsn()) {
return false;
}
}
return true;
}

View file

@ -1 +1 @@
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"cf6ebe6d41b022897360866b526d19ba8843aa82ae99a1d28393985576b6a782",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"63b221c28d209afb8dfc53191b61f7ba9d3faa1591fddb5547e4c400301a8138","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"967448b6cd46a8e60d465d56be0b1e6794a18110592a30939d2cb0650c4e5bc6","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"bae82f66dd47a060b6fdcc238520084aec1079d5b1b1d66d103baa1ffaa8773d","src/backend/aggregate_device.rs":"f408ea934a20f5a24372fdcaa3bbc113713239fdb32323de0fd6334034c25e46","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"30ceeceee4fc1f6f872c6c61765e41d582ccd91d2d1ac3ca9b1e5ac18dd11a71","src/backend/mixer.rs":"c4d09291598cbffb2217b551770ec590f34b6dd6b461dd99b019d5bb70f0eef3","src/backend/mod.rs":"6f38a9e3d5b8864e9f921a47fa7655d9322ecf8789a63560fb2f5fcc63076d33","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"afbdf1da1fcaddcad2986bd3146bf93ca75c24b3362f5f23a09517a926290ca2","src/backend/tests/api.rs":"3b0936810b3afa84cb80428c471e1097701fd790460d00c0a5715fd8026d0a4d","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"bb4f7df992d915723222f62a4f995896cce861821c73351d831cb01a34cef0c4","src/backend/tests/device_property.rs":"4ef3ab625809fe95e944c19cc5dc1cc79f473520a4314d123b1f80c6b7e11411","src/backend/tests/interfaces.rs":"a96d1432afd381bf74dcbe73e892dfc4ddc68721a956606c94fd4128c6589adc","src/backend/tests/manual.rs":"f72625c05110534775c4608ccc45472ea108286657ffc1f029844a13d0b883bf","src/backend/tests/mod.rs":"e388a37edd5f53cda04fe1ac8bf033e423c6604014792177c623c8456fe5d257","src/backend/tests/parallel.rs":"a7ebd579339c40ca64c0757cc9da6baec641e670f226e1b2ec5049894700bd7a","src/backend/tests/sync_callback.rs":"20e7ba57714c0d2bff3bc8d3a912f17fdab293737bc729eae1684070b90b72c4","src/backend/tests/tone.rs":"b028c67777b6453a26190b6a49785dfe28556adcbe179cb10862ce0d47ee8509","src/backend/tests/utils.rs":"9f4f486b3d59081747785dae4828ec22a4ecbab755ac4c09ff2c0c065865a358","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"be88c967e470bf6c120f3e42f7155fe89a4718f56a35524ea4c17181856757d5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"cf6ebe6d41b022897360866b526d19ba8843aa82ae99a1d28393985576b6a782",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"63b221c28d209afb8dfc53191b61f7ba9d3faa1591fddb5547e4c400301a8138","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"967448b6cd46a8e60d465d56be0b1e6794a18110592a30939d2cb0650c4e5bc6","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"bae82f66dd47a060b6fdcc238520084aec1079d5b1b1d66d103baa1ffaa8773d","src/backend/aggregate_device.rs":"3e2b5d1fa24130a9b14d6761b443fc7d1ed2f7884c545013ed2d048a1de2c3e6","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"30ceeceee4fc1f6f872c6c61765e41d582ccd91d2d1ac3ca9b1e5ac18dd11a71","src/backend/mixer.rs":"c4d09291598cbffb2217b551770ec590f34b6dd6b461dd99b019d5bb70f0eef3","src/backend/mod.rs":"6f38a9e3d5b8864e9f921a47fa7655d9322ecf8789a63560fb2f5fcc63076d33","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"afbdf1da1fcaddcad2986bd3146bf93ca75c24b3362f5f23a09517a926290ca2","src/backend/tests/api.rs":"3b0936810b3afa84cb80428c471e1097701fd790460d00c0a5715fd8026d0a4d","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"bb4f7df992d915723222f62a4f995896cce861821c73351d831cb01a34cef0c4","src/backend/tests/device_property.rs":"4ef3ab625809fe95e944c19cc5dc1cc79f473520a4314d123b1f80c6b7e11411","src/backend/tests/interfaces.rs":"a96d1432afd381bf74dcbe73e892dfc4ddc68721a956606c94fd4128c6589adc","src/backend/tests/manual.rs":"f72625c05110534775c4608ccc45472ea108286657ffc1f029844a13d0b883bf","src/backend/tests/mod.rs":"e388a37edd5f53cda04fe1ac8bf033e423c6604014792177c623c8456fe5d257","src/backend/tests/parallel.rs":"a7ebd579339c40ca64c0757cc9da6baec641e670f226e1b2ec5049894700bd7a","src/backend/tests/sync_callback.rs":"20e7ba57714c0d2bff3bc8d3a912f17fdab293737bc729eae1684070b90b72c4","src/backend/tests/tone.rs":"b028c67777b6453a26190b6a49785dfe28556adcbe179cb10862ce0d47ee8509","src/backend/tests/utils.rs":"9f4f486b3d59081747785dae4828ec22a4ecbab755ac4c09ff2c0c065865a358","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"be88c967e470bf6c120f3e42f7155fe89a4718f56a35524ea4c17181856757d5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}

View file

@ -334,17 +334,19 @@ impl AggregateDevice {
return Err(Error::from(status));
}
let cleanup = || {
let _teardown = finally(|| {
let status = audio_object_remove_property_listener(
device_id,
&address,
devices_changed_callback,
data_ptr as *mut c_void,
);
// kAudioHardwareBadObjectError implies device_id is somehow dead,
// so its listener should receive nothing.
assert!(status == NO_ERR || status == (kAudioHardwareBadObjectError as OSStatus));
sync_callback_registry_unregister(data_ptr as usize);
unsafe { drop(Box::from_raw(data_ptr)) };
status
};
});
Self::set_sub_devices(device_id, input_id, output_id)?;
@ -362,10 +364,6 @@ impl AggregateDevice {
);
}
if *dev != device_id {
let status = cleanup();
// If the error is kAudioHardwareBadObjectError, it implies `device_id` is somehow
// dead, so its listener should receive nothing. It's ok to leave here.
assert!(status == NO_ERR || status == (kAudioHardwareBadObjectError as OSStatus));
return Err(Error::from(waiting_time));
}
}
@ -386,8 +384,6 @@ impl AggregateDevice {
NO_ERR
}
let status = cleanup();
assert_eq!(status, NO_ERR);
Ok(())
}