Работающие звонки
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <android/log.h>
|
||||
@@ -125,6 +126,12 @@ struct AdditionalTsState {
|
||||
uint64_t base_timestamp = 0;
|
||||
};
|
||||
|
||||
struct SenderTsOffsetState {
|
||||
bool initialized = false;
|
||||
bool enabled = false;
|
||||
uint64_t offset = 0;
|
||||
};
|
||||
|
||||
static inline uint16_t load16_be(const uint8_t* p) {
|
||||
return (uint16_t)(((uint16_t)p[0] << 8) | (uint16_t)p[1]);
|
||||
}
|
||||
@@ -334,6 +341,25 @@ static inline void fill_nonce_from_ts32(uint32_t ts, uint8_t nonce[24]) {
|
||||
nonce[7] = (uint8_t)(ts);
|
||||
}
|
||||
|
||||
static inline void fill_nonce_from_ts64(uint64_t ts, uint8_t nonce[24]) {
|
||||
nonce[0] = (uint8_t)(ts >> 56);
|
||||
nonce[1] = (uint8_t)(ts >> 48);
|
||||
nonce[2] = (uint8_t)(ts >> 40);
|
||||
nonce[3] = (uint8_t)(ts >> 32);
|
||||
nonce[4] = (uint8_t)(ts >> 24);
|
||||
nonce[5] = (uint8_t)(ts >> 16);
|
||||
nonce[6] = (uint8_t)(ts >> 8);
|
||||
nonce[7] = (uint8_t)(ts);
|
||||
}
|
||||
|
||||
static inline uint64_t monotonic_48k_ticks() {
|
||||
struct timespec ts {};
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return 0;
|
||||
const uint64_t sec = (uint64_t)ts.tv_sec;
|
||||
const uint64_t nsec = (uint64_t)ts.tv_nsec;
|
||||
return sec * 48000ULL + (nsec * 48000ULL) / 1000000000ULL;
|
||||
}
|
||||
|
||||
static inline uint32_t opus_base_frame_samples(uint8_t config) {
|
||||
// RFC 6716 TOC config mapping at 48 kHz.
|
||||
if (config <= 11) {
|
||||
@@ -550,6 +576,7 @@ public:
|
||||
bool nonce_from_generated_ts = false;
|
||||
bool nonce_from_additional_data = false;
|
||||
bool additional_was_rtp_header = false;
|
||||
bool additional_used_mono_offset = false;
|
||||
uint32_t generated_ts_used = 0;
|
||||
|
||||
// Build nonce from RTP timestamp in additional_data (preferred).
|
||||
@@ -579,23 +606,36 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (nonce_from_rtp_header && header_size <= frame.size()) {
|
||||
// Keep RTP header clear, encrypt payload only.
|
||||
if (header_size > 0) {
|
||||
memcpy(encrypted_frame.data(), frame.data(), header_size);
|
||||
// Some Android sender pipelines expose stream-relative ad8 timestamps
|
||||
// (0, 960, 1920, ...), while desktop receiver expects an absolute base.
|
||||
// For interop, add a monotonic 48k offset once when first ad8 is tiny.
|
||||
if (nonce_from_additional_data &&
|
||||
additional_data.size() == 8 &&
|
||||
!additional_was_rtp_header &&
|
||||
additional_data.data() != nullptr) {
|
||||
const uint64_t ad_ts64 = load64_be(additional_data.data());
|
||||
if (!sender_ts_offset_.initialized) {
|
||||
sender_ts_offset_.initialized = true;
|
||||
// Keep pure raw-abs mode by default; desktop is the source of truth.
|
||||
sender_ts_offset_.enabled = false;
|
||||
sender_ts_offset_.offset = 0ULL;
|
||||
diag_event("ENC ad8-base init ssrc=%u ad_ts=%llu use_mono=%d mono_off=%llu\n",
|
||||
ssrc,
|
||||
(unsigned long long)ad_ts64,
|
||||
sender_ts_offset_.enabled ? 1 : 0,
|
||||
(unsigned long long)sender_ts_offset_.offset);
|
||||
}
|
||||
if (sender_ts_offset_.enabled) {
|
||||
const uint64_t ts_adj = ad_ts64 + sender_ts_offset_.offset;
|
||||
fill_nonce_from_ts64(ts_adj, nonce);
|
||||
additional_used_mono_offset = true;
|
||||
}
|
||||
const size_t payload_size = frame.size() - header_size;
|
||||
rosetta_xchacha20_xor(
|
||||
encrypted_frame.data() + header_size,
|
||||
frame.data() + header_size,
|
||||
payload_size,
|
||||
nonce,
|
||||
key_);
|
||||
} else {
|
||||
// Legacy path: frame is payload-only.
|
||||
rosetta_xchacha20_xor(encrypted_frame.data(),
|
||||
frame.data(), frame.size(), nonce, key_);
|
||||
}
|
||||
|
||||
// Desktop createEncodedStreams encrypts full encoded chunk.
|
||||
// To stay wire-compatible, do not preserve any leading RTP-like bytes.
|
||||
rosetta_xchacha20_xor(encrypted_frame.data(),
|
||||
frame.data(), frame.size(), nonce, key_);
|
||||
*bytes_written = frame.size();
|
||||
|
||||
if (nonce_from_generated_ts) {
|
||||
@@ -628,7 +668,9 @@ public:
|
||||
: (nonce_from_additional_data
|
||||
? (additional_was_rtp_header
|
||||
? "ad-rtp"
|
||||
: (additional_used_relative_ts ? "raw-rel" : "raw-abs"))
|
||||
: (additional_used_mono_offset
|
||||
? "raw-abs+mono"
|
||||
: (additional_used_relative_ts ? "raw-rel" : "raw-abs")))
|
||||
: "raw-abs"));
|
||||
LOGI("ENC frame#%d mt=%s ssrc=%u sz=%zu ad=%zu hdr=%zu mode=%s nonce_ts=%u gen_ts=%u next_step=%u rtp_ok=%d rtp_seq=%u rtp_ts=%u rtp_ssrc=%u opus_ok=%d key_fp=%08x in_h=%08x out_h=%08x ad8=%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
n, media_type_name(media_type), ssrc, frame.size(), additional_data.size(), header_size, mode,
|
||||
@@ -663,6 +705,7 @@ private:
|
||||
mutable std::atomic<int> diag_count_{0};
|
||||
mutable RtpProbeState rtp_probe_;
|
||||
mutable GeneratedTsState generated_ts_;
|
||||
mutable SenderTsOffsetState sender_ts_offset_;
|
||||
uint32_t key_fingerprint_ = 0;
|
||||
uint8_t key_[32];
|
||||
};
|
||||
@@ -746,20 +789,8 @@ public:
|
||||
|
||||
bool used_generated_resync = false;
|
||||
|
||||
if (nonce_from_rtp_header && header_size <= encrypted_frame.size()) {
|
||||
if (header_size > 0) {
|
||||
memcpy(frame.data(), encrypted_frame.data(), header_size);
|
||||
}
|
||||
const size_t payload_size = encrypted_frame.size() - header_size;
|
||||
rosetta_xchacha20_xor(
|
||||
frame.data() + header_size,
|
||||
encrypted_frame.data() + header_size,
|
||||
payload_size,
|
||||
nonce,
|
||||
key_);
|
||||
} else {
|
||||
rosetta_xchacha20_xor(frame.data(), encrypted_frame.data(), encrypted_frame.size(), nonce, key_);
|
||||
}
|
||||
// Desktop createEncodedStreams decrypts full encoded chunk.
|
||||
rosetta_xchacha20_xor(frame.data(), encrypted_frame.data(), encrypted_frame.size(), nonce, key_);
|
||||
|
||||
if (nonce_from_additional_data) {
|
||||
bool plausible = is_plausible_decrypted_audio_frame(frame.data(), encrypted_frame.size());
|
||||
|
||||
Reference in New Issue
Block a user