Browse Source

Define bounded audio timeline and playback clock contracts

master
evgeny 6 days ago
parent
commit
b5bd45c4da
  1. 14
      src/call/call_clock.h
  2. 55
      src/call/call_timeline.h

14
src/call/call_clock.h

@ -0,0 +1,14 @@
/* Снимок часов входящего аудио. PTS принадлежит шкале захвата удалённой стороны.
* epoch — локальная эпоха устройства; source_epoch — поколение удалённого encoder.
* valid=0 запрещает продвижение видео по этому снимку. measured отличает аппаратную
* отметку от оценки backend. Тишина устройства/тоны удерживают PTS, remote mute — нет. */
#ifndef CALL_CLOCK_H
#define CALL_CLOCK_H
#include <stdint.h>
struct call_clock_snapshot {
uint64_t epoch, source_epoch, played_samples, written_samples;
int64_t pts_us;
uint32_t held_back_us;
int valid, measured;
};
#endif

55
src/call/call_timeline.h

@ -0,0 +1,55 @@
/* Карта SoundTouch → PTS → устройство. Встроенные кольца, без аллокаций в DSP callback.
* feed/source/read — один playback worker. read/silence/progress/clock синхронизирует
* владелец с читателями clock; source/feed общих выходных данных не касаются.
* reset — после остановки доступа. Source Reset обнуляет только локальную карту DSP.
* Ограничения не меняют PCM: ошибка карты делает clock недостоверным до reset. */
#ifndef CALL_TIMELINE_H
#define CALL_TIMELINE_H
#include "call_clock.h"
#include "soundtouch/SourceSpan.h"
#include <array>
#include <cstddef>
class CallTimeline {
public:
void reset(uint64_t epoch);
void feed(int64_t pts_us, unsigned samples, uint64_t source_epoch);
void source(const soundtouch::SourceSpan& span);
void read(unsigned samples);
void silence(unsigned samples);
void progress(uint64_t epoch, uint64_t position, int64_t at_us, int64_t received_us, bool measured);
call_clock_snapshot clock(int64_t now_us);
private:
struct Span {
uint64_t first = 0, epoch = 0;
unsigned count = 0;
double pts = 0, end = 0;
bool valid = false;
};
template<size_t N> struct Ring {
std::array<Span, N> data{};
size_t head = 0, count = 0;
Span& front() { return data[head]; }
const Span& back() const { return data[(head + count - 1) % N]; }
void pop() { head = (head + 1) % N; --count; }
void clear() { head = count = 0; }
bool push(const Span& s) {
if (count == N) return false;
data[(head + count++) % N] = s; return true;
}
};
Ring<256> input; // >5с входа; SoundTouch звонка держит лишь несколько блоков.
Ring<1024> ready;
Ring<2048> output;
uint64_t inputWritten = 0, generated = 0, consumed = 0, written = 0, epoch = 0;
uint64_t anchorPosition = 0, minimumPosition = 0, lastSourceEpoch = 0;
int64_t anchorTime = 0, anchorReceived = 0, lastPts = -1;
double endPts = 0;
uint64_t endEpoch = 0;
int sourceError = 0;
bool outputFailed = false, haveAnchor = false, measured = false, endValid = false;
static double at(const Span& s, double position);
const Span* findInput(uint64_t position) const;
void appendOutput(const Span& s);
};
#endif
Loading…
Cancel
Save