Browse Source

Publish live audio toggles through the shared stream actor

master
evgeny 3 days ago
parent
commit
c9c1bb7cf1
  1. 22
      src/stream/stream_publisher.c
  2. 3
      src/stream/stream_publisher.h

22
src/stream/stream_publisher.c

@ -32,7 +32,7 @@ struct stream_publisher {
struct stream_publisher_status status;
struct publisher_queue video, audio;
uint64_t group, next_frame, last_pts[2], drain_until, report_us;
int seen[2], stopping;
int seen[2], stopping, audio_enabled, audio_dirty;
};
static void publisher_process(void *arg);
@ -180,6 +180,10 @@ static void publisher_process(void *arg) {
}
uint64_t now = get_time_us();
if (p->handle && !stream_handle_active(p->handle)) publisher_close(p, stream_handle_reason(p->handle));
if (p->handle && p->audio_dirty && p->status.state == STREAM_PUBLISHER_LIVE) {
if (stream_publish_set_audio_enabled(p->handle, p->audio_enabled) != STREAM_OK) publisher_close(p, STREAM_CLOSE_FAILED);
else { p->status.audio_enabled = p->audio_enabled; p->audio_dirty = 0; }
}
if (p->video.head && now - p->video.head->created > MEDIA_AGE_US) {
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "publisher video expired bytes=%zu records=%u; require KEY", p->video.bytes, p->video.count);
records_clear(&p->video); p->status.need_key = 1;
@ -246,11 +250,27 @@ int stream_publisher_open(struct stream_publisher *p, uint64_t id, uint64_t grou
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "publisher open busy id=%llu owner=%llu", (unsigned long long)id, (unsigned long long)p->status.id);
} else if (publisher_schedule(p) == 0) {
p->status = (struct stream_publisher_status){.id = id, .state = STREAM_PUBLISHER_OPENING, .need_key = 1};
p->audio_enabled = f->audio_codec != 0; p->audio_dirty = 1;
p->group = group; p->format = *f; p->next_frame = 0; p->stopping = 0; memset(p->seen, 0, sizeof(p->seen)); result = 0;
}
pthread_mutex_unlock(&p->lock); return result;
}
int stream_publisher_set_audio_enabled(struct stream_publisher *p, uint64_t id, int enabled) {
if (!p || !id || (enabled != 0 && enabled != 1)) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "publisher audio change invalid arguments"); return -1;
}
pthread_mutex_lock(&p->lock); int result = -1;
if (p->status.id != id || p->stopping || (enabled && !p->format.audio_codec)
|| (p->status.state != STREAM_PUBLISHER_OPENING && p->status.state != STREAM_PUBLISHER_LIVE)) {
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "publisher audio change refused id=%llu owner=%llu state=%d enabled=%d codec=%u",
(unsigned long long)id, (unsigned long long)p->status.id, p->status.state, enabled, p->format.audio_codec);
} else if (publisher_schedule(p) == 0) {
p->audio_enabled = enabled; p->audio_dirty = 1; result = 0;
}
pthread_mutex_unlock(&p->lock); return result;
}
/* Admission сохраняет PTS только принятого кадра; новая revision коммитится атомарно с KEY. */
int stream_publisher_feed(struct stream_publisher *p, uint64_t id, int video, uint64_t pts, int key,
const uint8_t *data, size_t length, const struct stream_media_format *f) {

3
src/stream/stream_publisher.h

@ -18,10 +18,13 @@ struct stream_publisher_status {
unsigned connections;
int state, reason, need_key;
int compressor_enabled, compressor_max_gain_db, compressor_rise_rate;
int audio_enabled;
};
int stream_publisher_create(struct stream_publisher **out, struct UTUN_INSTANCE *inst);
void stream_publisher_destroy(struct stream_publisher *publisher);
int stream_publisher_open(struct stream_publisher *publisher, uint64_t id, uint64_t group, const struct stream_media_format *format);
/* Producer заглушает свою копию PCM; actor публикует состояние без смены аудиотрека/эпохи. */
int stream_publisher_set_audio_enabled(struct stream_publisher *publisher, uint64_t id, int enabled);
/* 1 принято, 0 требуется KEY/перегрузка, -1 ошибка или старый/закрытый session ID. */
int stream_publisher_feed(struct stream_publisher *publisher, uint64_t id, int video, uint64_t pts, int key,
const uint8_t *data, size_t length, const struct stream_media_format *format);

Loading…
Cancel
Save