Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e8742e3
NCG-5940: added interface for call recording
Sep 10, 2024
dacfda4
NCG-5940: added callback about ready recored file
Sep 11, 2024
731c159
NCG-5940: added raw data and duration in callback
Sep 11, 2024
0928bbd
NCG-5940: added sound improvements
Sep 18, 2024
5a36422
NCG-5940: changed implementation to ogg
Sep 19, 2024
db3f940
NCG-5940: deleted redundant
Sep 24, 2024
c748174
NCG-5940: added synchronous flag
Oct 10, 2024
fdc3675
NCG-5940: changed call recored api
Oct 15, 2024
f5ca477
NCG-5940: changed call recored api
Oct 23, 2024
41a3014
NCG-5940: added error calback
Nov 5, 2024
cff7487
Telegram: hide h264 ffmpeg decoder behind WEBRTC_USE_H264_DECODER
Nov 15, 2024
77d3d1f
[Temp] Always pass frame decryptor if configured
Dec 13, 2024
bbcee9b
Merge commit 'cff7487b9c9a856678d645879d363e55812f3039' into NCG-5940…
denis15yo Dec 23, 2024
5d63b70
Merge remote-tracking branch 'telegram/telegram' into NCG-5940-implem…
denis15yo Jan 3, 2025
e8d2ef8
[Temp] Un-filter reflector ports
Feb 25, 2025
1d44f2a
Merge remote-tracking branch 'telegram/telegram' into NCG-5940-implem…
denis15yo Mar 17, 2025
dfd6b60
Fix RTCNetworkMonitor enumeration
Mar 20, 2025
3d6dcfb
Merge commit 'dfd6b604d7194a3d41614afa2c8abd8825a657aa' into NCG-5940…
denis15yo May 1, 2025
d5c77d3
Xcode 26.4
Mar 31, 2026
5b21d8b
perf: tune SCTP retransmission timers for lossy signaling
Apr 10, 2026
ea885e7
Revert "perf: tune SCTP retransmission timers for lossy signaling"
Apr 11, 2026
adb369c
fix: enable H264 decoder for FFmpeg 7+ and add diagnostics
Apr 14, 2026
7ce8c75
Merge commit 'd5c77d3588c9353dd48b80430d2ffb41dafef177' into NCG-5940…
denis15yo Apr 16, 2026
3817e90
Merge branch 'temp-merge' into telegram
Apr 30, 2026
aa9bf8f
Merge commit '3817e906cb6c22ec9cc62023b073e1a668d9cb33' into NCG-5940…
denis15yo Jun 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/candidate.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class RTC_EXPORT Candidate {
// cricket::LOCAL_PORT_TYPE). The type should really be an enum rather than a
// string, but until we make that change the lifetime attribute helps us lock
// things down. See also the `Port` class.
void set_type(absl::string_view type ABSL_ATTRIBUTE_LIFETIME_BOUND) {
void set_type(absl::string_view type) {
Assign(type_, type);
}

Expand Down
3 changes: 3 additions & 0 deletions common_video/h265/h265_pps_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#ifndef COMMON_VIDEO_H265_PPS_PARSER_H_
#define COMMON_VIDEO_H265_PPS_PARSER_H_

#include <cstddef>
#include <cstdint>

#include "absl/types/optional.h"

namespace rtc {
Expand Down
7 changes: 7 additions & 0 deletions media/engine/webrtc_video_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3571,6 +3571,13 @@ void WebRtcVideoReceiveChannel::WebRtcVideoReceiveStream::StopReceiveStream() {
void WebRtcVideoReceiveChannel::WebRtcVideoReceiveStream::OnFrame(
const webrtc::VideoFrame& frame) {
webrtc::MutexLock lock(&sink_lock_);
{
static int fc = 0;
if (++fc <= 3) {
RTC_LOG(LS_WARNING) << "WVRS::OnFrame #" << fc << " sink_=" << (sink_ ? "set" : "null")
<< " " << frame.width() << "x" << frame.height();
}
}

int64_t time_now_ms = rtc::TimeMillis();
if (first_frame_timestamp_ < 0)
Expand Down
11 changes: 11 additions & 0 deletions modules/audio_device/audio_device_generic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,15 @@ int AudioDeviceGeneric::GetRecordAudioParameters(
}
#endif // WEBRTC_IOS

// MARK: Nicegram NCG-5828 call recording

void AudioDeviceGeneric::StartNicegramRecording(const CompletionRecorderCallback& callback, const RecorderErrorCallback &errorCallback) {
RTC_LOG_F(LS_ERROR) << "Not supported on this platform";
}

void AudioDeviceGeneric::StopNicegramRecording(bool synchronous) {
RTC_LOG_F(LS_ERROR) << "Not supported on this platform";
}
//

} // namespace webrtc
12 changes: 12 additions & 0 deletions modules/audio_device/audio_device_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ namespace webrtc {

class AudioDeviceGeneric {
public:
// MARK: Nicegram NCG-5828 call recording
using CompletionRecorderCallback = std::function<void(const std::string& outputFilePath,
double durationInSeconds,
size_t rawDataSize)>;

using RecorderErrorCallback = std::function<void(const std::string& error)>;
//
// For use with UMA logging. Must be kept in sync with histograms.xml in
// Chrome, located at
// https://cs.chromium.org/chromium/src/tools/metrics/histograms/histograms.xml
Expand Down Expand Up @@ -135,6 +142,11 @@ class AudioDeviceGeneric {
virtual int GetRecordAudioParameters(AudioParameters* params) const;
#endif // WEBRTC_IOS

// MARK: Nicegram NCG-5828 call recording
virtual void StartNicegramRecording(const CompletionRecorderCallback& callback, const RecorderErrorCallback &errorCallback);
virtual void StopNicegramRecording(bool synchronous = false);
//

virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) = 0;

virtual ~AudioDeviceGeneric() {}
Expand Down
12 changes: 12 additions & 0 deletions modules/audio_device/include/audio_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ class AudioDeviceModuleForTest;

class AudioDeviceModule : public webrtc::RefCountInterface {
public:
// MARK: Nicegram NCG-5828 call recording
using CompletionRecorderCallback = std::function<void(const std::string& outputFilePath,
double durationInSeconds,
size_t rawDataSize)>;

using RecorderErrorCallback = std::function<void(const std::string& error)>;
//
enum AudioLayer {
kPlatformDefaultAudio = 0,
kWindowsCoreAudio,
Expand Down Expand Up @@ -171,6 +178,11 @@ class AudioDeviceModule : public webrtc::RefCountInterface {
virtual int GetRecordAudioParameters(AudioParameters* params) const = 0;
#endif // WEBRTC_IOS

// MARK: Nicegram NCG-5828 call recording
virtual void StartNicegramRecording(const CompletionRecorderCallback& callback, const RecorderErrorCallback &errorCallback) {}
virtual void StopNicegramRecording(bool synchronous = false) {}
//

protected:
~AudioDeviceModule() override {}
};
Expand Down
2 changes: 1 addition & 1 deletion modules/video_coding/codecs/h264/h264.cc
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ bool H264Encoder::SupportsScalabilityMode(ScalabilityMode scalability_mode) {

std::unique_ptr<H264Decoder> H264Decoder::Create() {
RTC_DCHECK(H264Decoder::IsSupported());
#if defined(WEBRTC_USE_H264)
#if defined(WEBRTC_USE_H264) && defined(WEBRTC_USE_H264_DECODER)
RTC_CHECK(g_rtc_use_h264);
RTC_LOG(LS_INFO) << "Creating H264DecoderImpl.";
return std::make_unique<H264DecoderImpl>();
Expand Down
9 changes: 6 additions & 3 deletions modules/video_coding/codecs/h264/h264_decoder_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// build with H264 support, please do not move anything out of the
// #ifdef unless needed and tested.
#ifdef WEBRTC_USE_H264
#ifdef WEBRTC_USE_H264_DECODER

#include "modules/video_coding/codecs/h264/h264_decoder_impl.h"

Expand Down Expand Up @@ -233,7 +234,7 @@ int H264DecoderImpl::AVGetBuffer2(AVCodecContext* context,
int total_size = y_size + 2 * uv_size;

av_frame->format = context->pix_fmt;
av_frame->reordered_opaque = context->reordered_opaque;
// Don't touch av_frame->opaque — context->opaque is the H264DecoderImpl* ptr.

// Create a VideoFrame object, to keep a reference to the buffer.
// TODO(nisse): The VideoFrame's timestamp and rotation info is not used.
Expand Down Expand Up @@ -382,7 +383,8 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,
}
packet->size = static_cast<int>(input_image.size());
int64_t frame_timestamp_us = input_image.ntp_time_ms_ * 1000; // ms -> μs
av_context_->reordered_opaque = frame_timestamp_us;
// Pass timestamp via AVPacket::pts (reordered_opaque removed in FFmpeg 7+).
packet->pts = frame_timestamp_us;

int result = avcodec_send_packet(av_context_.get(), packet.get());

Expand All @@ -401,7 +403,7 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,

// We don't expect reordering. Decoded frame timestamp should match
// the input one.
RTC_DCHECK_EQ(av_frame_->reordered_opaque, frame_timestamp_us);
RTC_DCHECK_EQ(av_frame_->pts, frame_timestamp_us);

// TODO(sakal): Maybe it is possible to get QP directly from FFmpeg.
h264_bitstream_parser_.ParseBitstream(input_image);
Expand Down Expand Up @@ -658,4 +660,5 @@ void H264DecoderImpl::ReportError() {

} // namespace webrtc

#endif // WEBRTC_USE_H264_DECODER
#endif // WEBRTC_USE_H264
2 changes: 2 additions & 0 deletions modules/video_coding/codecs/h264/h264_decoder_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// build with H264 support, please do not move anything out of the
// #ifdef unless needed and tested.
#ifdef WEBRTC_USE_H264
#ifdef WEBRTC_USE_H264_DECODER

#if defined(WEBRTC_WIN) && !defined(__clang__)
#error "See: bugs.webrtc.org/9213#c13."
Expand Down Expand Up @@ -104,6 +105,7 @@ class H264DecoderImpl : public H264Decoder {

} // namespace webrtc

#endif // WEBRTC_USE_H264_DECODER
#endif // WEBRTC_USE_H264

#endif // MODULES_VIDEO_CODING_CODECS_H264_H264_DECODER_IMPL_H_
8 changes: 8 additions & 0 deletions modules/video_coding/generic_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ VCMDecodedFrameCallback::FindFrameInfo(uint32_t rtp_timestamp) {
void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
absl::optional<int32_t> decode_time_ms,
absl::optional<uint8_t> qp) {
{
static int dfc = 0;
if (++dfc <= 5) {
RTC_LOG(LS_WARNING) << "VCMDecodedFrameCallback::Decoded #" << dfc
<< " " << decodedImage.width() << "x" << decodedImage.height()
<< " ts=" << decodedImage.timestamp();
}
}
RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point";
TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
"timestamp", decodedImage.timestamp());
Expand Down
9 changes: 6 additions & 3 deletions p2p/base/ice_transport_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ RTCError VerifyCandidate(const Candidate& cand) {
return RTCError::OK();
}
if (port < 1024) {
if ((port != 80) && (port != 443)) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
"candidate has port below 1024, but not 80 or 443");
if (absl::EndsWith(cand.address().hostname(), ".reflector")) {
} else {
if ((port != 80) && (port != 443)) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
"candidate has port below 1024, but not 80 or 443");
}
}

if (cand.address().IsPrivateIP()) {
Expand Down
50 changes: 21 additions & 29 deletions sdk/objc/components/network/RTCNetworkMonitor.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/

#import "RTCNetworkMonitor+Private.h"

#import <Network/Network.h>

#import "base/RTCLogging.h"
#import "helpers/RTCDispatcher+Private.h"

#include "rtc_base/string_utils.h"

namespace {

rtc::AdapterType AdapterTypeFromInterfaceType(nw_interface_type_t interfaceType) {
rtc::AdapterType AdapterTypeFromInterfaceType(
nw_interface_type_t interfaceType) {
rtc::AdapterType adapterType = rtc::ADAPTER_TYPE_UNKNOWN;
switch (interfaceType) {
case nw_interface_type_other:
Expand All @@ -43,18 +38,16 @@
}
return adapterType;
}

} // namespace

@implementation RTCNetworkMonitor {
webrtc::NetworkMonitorObserver *_observer;
nw_path_monitor_t _pathMonitor;
dispatch_queue_t _monitorQueue;
}

- (instancetype)initWithObserver:(webrtc::NetworkMonitorObserver *)observer {
RTC_DCHECK(observer);
if (self = [super init]) {
self = [super init];
if (self) {
_observer = observer;
if (@available(iOS 12, *)) {
_pathMonitor = nw_path_monitor_create();
Expand All @@ -65,10 +58,10 @@ - (instancetype)initWithObserver:(webrtc::NetworkMonitorObserver *)observer {
RTCLog(@"NW path monitor created.");
__weak RTCNetworkMonitor *weakSelf = self;
nw_path_monitor_set_update_handler(_pathMonitor, ^(nw_path_t path) {
if (weakSelf == nil) {
RTCNetworkMonitor *strongSelf = weakSelf;
if (strongSelf == nil) {
return;
}
RTCNetworkMonitor *strongSelf = weakSelf;
RTCLog(@"NW path monitor: updated.");
nw_path_status_t status = nw_path_get_status(path);
if (status == nw_path_status_invalid) {
Expand All @@ -80,33 +73,34 @@ - (instancetype)initWithObserver:(webrtc::NetworkMonitorObserver *)observer {
} else if (status == nw_path_status_satisfiable) {
RTCLog(@"NW path monitor status: satisfiable.");
}
std::map<std::string, rtc::AdapterType, rtc::AbslStringViewCmp> *map =
new std::map<std::string, rtc::AdapterType, rtc::AbslStringViewCmp>();
nw_path_enumerate_interfaces(
path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) {
const char *name = nw_interface_get_name(interface);
nw_interface_type_t interfaceType = nw_interface_get_type(interface);
RTCLog(@"NW path monitor available interface: %s", name);
rtc::AdapterType adapterType = AdapterTypeFromInterfaceType(interfaceType);
map->insert(std::pair<std::string, rtc::AdapterType>(name, adapterType));
});
std::map<std::string, rtc::AdapterType, rtc::AbslStringViewCmp>
owned_map;
auto map = &owned_map; // Capture raw pointer for Objective-C block
nw_path_enumerate_interfaces(path, ^(nw_interface_t interface) {
const char *name = nw_interface_get_name(interface);
nw_interface_type_t interfaceType = nw_interface_get_type(interface);
RTCLog(@"NW path monitor available interface: %s", name);
rtc::AdapterType adapterType =
AdapterTypeFromInterfaceType(interfaceType);
map->emplace(name, adapterType);
return true;
});
@synchronized(strongSelf) {
webrtc::NetworkMonitorObserver *observer = strongSelf->_observer;
if (observer) {
observer->OnPathUpdate(std::move(*map));
observer->OnPathUpdate(std::move(owned_map));
}
}
delete map;
});
nw_path_monitor_set_queue(
_pathMonitor,
[RTC_OBJC_TYPE(RTCDispatcher) dispatchQueueForType:RTCDispatcherTypeNetworkMonitor]);
[RTC_OBJC_TYPE(RTCDispatcher)
dispatchQueueForType:RTCDispatcherTypeNetworkMonitor]);
nw_path_monitor_start(_pathMonitor);
}
}
return self;
}

- (void)cancel {
if (@available(iOS 12, *)) {
nw_path_monitor_cancel(_pathMonitor);
Expand All @@ -118,9 +112,7 @@ - (void)stop {
_observer = nil;
}
}

- (void)dealloc {
[self cancel];
}

@end
2 changes: 1 addition & 1 deletion video/rtp_video_stream_receiver2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
}

// Only construct the encrypted receiver if frame encryption is enabled.
if (config_.crypto_options.sframe.require_frame_encryption) {
if (config_.crypto_options.sframe.require_frame_encryption || frame_decryptor) {
buffered_frame_decryptor_ =
std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_);
if (frame_decryptor != nullptr) {
Expand Down
2 changes: 1 addition & 1 deletion video/rtp_video_stream_receiver2.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender,
RTC_GUARDED_BY(packet_sequence_checker_);
video_coding::H264SpsPpsTracker tracker_
RTC_GUARDED_BY(packet_sequence_checker_);
video_coding::H265VpsSpsPpsTracker h265_tracker_;
video_coding::H265VpsSpsPpsTracker h265_tracker_
RTC_GUARDED_BY(packet_sequence_checker_);

// Maps payload id to the depacketizer.
Expand Down
27 changes: 27 additions & 0 deletions video/video_receive_stream2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ void VideoReceiveStream2::SetLocalSsrc(uint32_t local_ssrc) {

void VideoReceiveStream2::Start() {
RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
RTC_LOG(LS_WARNING) << "VRS2::Start() called, decoder_running_=" << decoder_running_;

if (decoder_running_) {
return;
Expand Down Expand Up @@ -675,6 +676,12 @@ void VideoReceiveStream2::SetDepacketizerToDecoderFrameTransformer(

void VideoReceiveStream2::RequestKeyFrame(Timestamp now) {
RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
{
static int count = 0;
if (++count <= 5) {
RTC_LOG(LS_WARNING) << "VRS2::RequestKeyFrame #" << count;
}
}
// Called from RtpVideoStreamReceiver (rtp_video_stream_receiver_ is
// ultimately responsible).
rtp_video_stream_receiver_.RequestKeyFrame();
Expand All @@ -683,6 +690,13 @@ void VideoReceiveStream2::RequestKeyFrame(Timestamp now) {

void VideoReceiveStream2::OnCompleteFrame(std::unique_ptr<EncodedFrame> frame) {
RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
{
static int count = 0;
if (++count <= 5) {
RTC_LOG(LS_WARNING) << "VRS2::OnCompleteFrame #" << count
<< " size=" << frame->size() << " type=" << static_cast<int>(frame->FrameType());
}
}

if (absl::optional<VideoPlayoutDelay> playout_delay =
frame->EncodedImage().PlayoutDelay()) {
Expand Down Expand Up @@ -747,6 +761,13 @@ bool VideoReceiveStream2::SetMinimumPlayoutDelay(int delay_ms) {

void VideoReceiveStream2::OnEncodedFrame(std::unique_ptr<EncodedFrame> frame) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
{
static int count = 0;
if (++count <= 5) {
RTC_LOG(LS_WARNING) << "VRS2::OnEncodedFrame #" << count
<< " size=" << frame->size() << " type=" << static_cast<int>(frame->FrameType());
}
}
Timestamp now = env_.clock().CurrentTime();
const bool keyframe_request_is_due =
!last_keyframe_request_ ||
Expand Down Expand Up @@ -848,6 +869,12 @@ VideoReceiveStream2::HandleEncodedFrameOnDecodeQueue(

int64_t frame_id = frame->Id();
int decode_result = DecodeAndMaybeDispatchEncodedFrame(std::move(frame));
{
static int dcount = 0;
if (++dcount <= 5) {
RTC_LOG(LS_WARNING) << "VRS2::decode_result=" << decode_result << " frame_id=" << frame_id;
}
}
if (decode_result == WEBRTC_VIDEO_CODEC_OK ||
decode_result == WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME) {
keyframe_required = false;
Expand Down