summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer/audio.c6
-rw-r--r--src/buffer/video.c19
-rw-r--r--src/codec/ffmpeg/decoder.c3
-rw-r--r--src/codec/ffmpeg/demuxer.c4
-rw-r--r--src/liana/list.h2
-rw-r--r--src/liana/vcr.c11
-rw-r--r--src/libsink/sink.c29
-rw-r--r--src/mixer/audio_miniaudio.c12
-rw-r--r--src/mixer/mixer.c2
9 files changed, 49 insertions, 39 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 141c589..f3e0b74 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -14,7 +14,7 @@
#define BUFFER_MARK_BUFFERED (1.5 * 1000000L)
#ifdef CAMU_AUDIO_BUFFER_FADE
-#define FADE_STEP(fmt) (1.f / (fmt)->sample_rate)
+#define FADE_STEP(fmt) (1.1f / (fmt)->sample_rate)
#endif
enum {
@@ -280,7 +280,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
if (pts > 0.0) { // Skip.
ret = camu_audio_format_sec_to_bytes(&buf->fmt.req, pts);
ret = AL_MIN(ret, have);
- al_log_debug("audio_buffer", "Skipping %fs of audio (%zu bytes).", pts, ret);
+ al_log_info("audio_buffer", "Skipping %fs of audio (%zu bytes).", pts, ret);
ret = al_ring_buffer_discard(&buf->rb, ret);
have -= ret;
buf->pts += camu_audio_format_bytes_to_sec(&buf->fmt.req, ret);
@@ -289,7 +289,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
pts = -pts;
ret = camu_audio_format_sec_to_bytes(&buf->fmt.req, pts);
ret = AL_MIN(ret, req);
- al_log_debug("audio_buffer", "Delaying audio by %fs (%zu bytes).", pts, ret);
+ al_log_info("audio_buffer", "Delaying audio by %fs (%zu bytes).", pts, ret);
al_memset(data, 0, ret);
data += ret;
req -= ret;
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 00902f3..04a9dbf 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -4,10 +4,10 @@
#include "common.h"
#include "common_internal.h"
-#define BUFFER_WATERMARK_LOW 8 // frames.
-#define BUFFER_WATERMARK_BUFFERED 5
-#define BUFFER_WATERMARK_HIGH 12
-#define BUFFER_WATERMARK_RESET BUFFER_WATERMARK_HIGH + 10.
+#define BUFFER_WATERMARK_LOW 6 // frames.
+#define BUFFER_WATERMARK_BUFFERED 4
+#define BUFFER_WATERMARK_HIGH 10
+#define BUFFER_WATERMARK_RESET BUFFER_WATERMARK_HIGH + 10
bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock, struct camu_renderer *renderer)
{
@@ -99,7 +99,7 @@ static void after_push_internal(struct camu_video_buffer *buf)
}
#ifdef CAMU_HAVE_FFMPEG
-static void push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame)
+static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame)
{
f64 pts = 0.0;
if (!buf->single_frame) {
@@ -107,7 +107,7 @@ static void push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame
pts = frame->best_effort_timestamp * av_q2d(stream->time_base);
if (pts + buf->avg_frame_duration < camu_clock_get_base_pts(buf->clock)) {
av_frame_free(&frame);
- return;
+ return false;
}
}
if (buf->pts == -1.0) buf->pts = pts;
@@ -122,6 +122,7 @@ static void push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame
#endif
if (frame) frame->opaque = buf;
buf->queue->push_av_frame(buf->queue, frame, pts);
+ return true;
}
#endif
@@ -137,10 +138,12 @@ void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_fra
buf->queue->push(buf->queue, frame, 0.0);
break;
#ifdef CAMU_HAVE_FFMPEG
- case CAMU_FFMPEG_COMPAT:
- push_av_frame_internal(buf, frame->av.frame);
+ case CAMU_FFMPEG_COMPAT: {
+ bool pushed = push_av_frame_internal(buf, frame->av.frame);
al_free(frame);
+ if (!pushed) return;
break;
+ }
#endif
}
after_push_internal(buf);
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index 375bdfe..03940a0 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -43,7 +43,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
av->codec_context->thread_type = FF_THREAD_SLICE;
al_log_debug("ff_decoder", "Using %i threads for decoder.", cpus);
-#ifndef CAMU_SINK_NO_VIDEO
+//#ifndef CAMU_SINK_NO_VIDEO
+#if 0
if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO && renderer && renderer->get_buffer2) {
av->codec_context->get_buffer2 = renderer->get_buffer2;
av->codec_context->opaque = renderer->opaque;
diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c
index 7ff0dca..8ea645b 100644
--- a/src/codec/ffmpeg/demuxer.c
+++ b/src/codec/ffmpeg/demuxer.c
@@ -154,13 +154,13 @@ static u64 ff_demuxer_get_duration(struct camu_demuxer *demux)
static bool ff_demuxer_seek(struct camu_demuxer *demux, u64 pos)
{
struct camu_ff_demuxer *av = (struct camu_ff_demuxer *)demux;
- if (pos > av->duration) pos = av->duration;
al_assert(pos <= INT64_MAX);
- s64 ts = av_rescale_q((s64)pos, (AVRational){ 1, 1000000 }, AV_TIME_BASE_Q);
+ if (pos > av->duration) pos = av->duration;
if (av->eof) {
avformat_flush(av->format_context);
av->eof = false;
}
+ s64 ts = (s64)pos;
if (avformat_seek_file(av->format_context, -1, INT64_MIN, ts, ts, 0) < 0) {
return false;
}
diff --git a/src/liana/list.h b/src/liana/list.h
index bbb2ce4..5e3eaec 100644
--- a/src/liana/list.h
+++ b/src/liana/list.h
@@ -8,7 +8,7 @@
#define LIANA_TIMESTAMP_INVALID UINT64_MAX
#define LIANA_BASE_DELAY 475000Lu // 475ms
-#define LIANA_BASE_PING 200000Lu // 200ms
+#define LIANA_BASE_PING 150000Lu // 150ms
#define LIANA_PAUSE_DELAY LIANA_BASE_PING
#define LIANA_DELAY_IGNORE 0Lu
diff --git a/src/liana/vcr.c b/src/liana/vcr.c
index 192b4f1..40aa757 100644
--- a/src/liana/vcr.c
+++ b/src/liana/vcr.c
@@ -109,9 +109,9 @@ static void cork_if_buffered(struct lia_vcr *vcr)
{
u8 buffered = 1;
struct lia_vcr_track *track;
- al_array_foreach(vcr->tracks, i, track) {
- buffered &= al_atomic_load(u8)(&track->buffered, AL_ATOMIC_RELAXED);
- }
+ //al_array_foreach(vcr->tracks, i, track) {
+ // buffered &= al_atomic_load(u8)(&track->buffered, AL_ATOMIC_RELAXED);
+ //}
if (buffered) {
aki_packet_stream_cork(vcr->data, true);
al_array_foreach(vcr->tracks, i, track) {
@@ -136,9 +136,10 @@ bool lia_vcr_push_packet(struct lia_vcr *vcr, struct aki_packet *packet)
aki_thread_create(&track->thread, vcr_track_thread, track);
track->running = true;
}
+ s32 count;
if (!aki_packet_cache_send_packet(&track->cache, packet)) {
aki_packet_free(packet);
- } else if (al_atomic_add(s32)(&vcr->count, 1, AL_ATOMIC_RELAXED) > vcr->mark.buffered) {
+ } else if ((count = al_atomic_add(s32)(&vcr->count, 1, AL_ATOMIC_RELAXED)) > vcr->mark.buffered) {
cork_if_buffered(vcr);
}
break;
@@ -204,7 +205,7 @@ void lia_vcr_flush(struct lia_vcr *vcr)
vcr_track_close_internal(track);
track->client->flush(track->client);
aki_packet_cache_enable(&track->cache);
- track->running = false;
+ al_atomic_store(u8)(&track->buffered, 0, AL_ATOMIC_RELAXED);
al_atomic_store(s32)(&track->state, LIANA_STREAM_RUNNING, AL_ATOMIC_RELAXED);
}
aki_signal_send(&vcr->signal);
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index a2262bc..ff9f4f2 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -468,18 +468,17 @@ static void video_buffer_callback(void *userdata, u8 op)
static void evaluate_latency(struct camu_sink *sink, struct camu_sink_entry *entry)
{
- // Entry has both audio and video configured.
+#if CAMU_SINK_LOCAL
#ifndef CAMU_SINK_NO_VIDEO
+ // Entry has both audio and video configured.
if (!BUFFER_EMPTY(&entry->audio) && !BUFFER_EMPTY(&entry->video)) {
camu_video_buffer_set_latency(&entry->video.buf, -camu_mixer_get_latency(sink->audio.mixer));
- } else if (!BUFFER_EMPTY(&entry->audio)) {
-#if !CAMU_SINK_LOCAL
- camu_audio_buffer_set_latency(&entry->audio.buf, -camu_mixer_get_latency(sink->audio.mixer));
-#endif
}
+#endif
#else
- (void)sink;
- (void)entry;
+ // To sync clients with differing audio latencies our only option is to factor the mixer
+ // latency into the audio buffer.
+ camu_audio_buffer_set_latency(&entry->audio.buf, camu_mixer_get_latency(sink->audio.mixer));
#endif
}
@@ -867,8 +866,16 @@ static bool set_command_callback(void *userdata, struct aki_rpc_connection *conn
set_or_queue_entry(entry);
sink->current = entry;
break;
- case LIANA_PAUSE_PAUSE:
- if (sink->current) {
+ case LIANA_PAUSE_PAUSE: {
+ struct camu_sink_entry *prev_target = sink->target;
+ if (prev_target) {
+ if (prev_target == entry) {
+ sink->target = NULL;
+ } else {
+ sink->target = entry;
+ }
+ camu_clock_pause(&prev_target->clock, at);
+ } else if (sink->current) {
if (camu_clock_is_ended(&sink->current->clock)) {
// Server thought we weren't done, be we are.
switch_to(sink, entry);
@@ -878,6 +885,7 @@ static bool set_command_callback(void *userdata, struct aki_rpc_connection *conn
}
}
break;
+ }
case LIANA_PAUSE_BOTH: {
camu_clock_resume(&entry->clock, at);
struct camu_sink_entry *prev_target = sink->target;
@@ -928,6 +936,9 @@ static bool pause_command_callback(void *userdata, struct aki_rpc_connection *co
if (!current) goto out;
#if CAMU_SINK_LOCAL
+ (void)sequence;
+ (void)at;
+ (void)pause;
sink_local_pause(sink, current);
#else
if (current->sequence == sequence) {
diff --git a/src/mixer/audio_miniaudio.c b/src/mixer/audio_miniaudio.c
index fb4db23..4e29e0a 100644
--- a/src/mixer/audio_miniaudio.c
+++ b/src/mixer/audio_miniaudio.c
@@ -136,7 +136,7 @@ static void data_callback(ma_device *device, void *output, const void *input, u3
}
#define DEFAULT_PERIODS 3
-#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 75
+#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 64
static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opaque)
{
@@ -175,14 +175,8 @@ static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opa
static u64 audio_miniaudio_get_latency(struct camu_audio *audio)
{
struct camu_audio_miniaudio *ma = (struct camu_audio_miniaudio *)audio;
- // Latency is one period on PulseAudio even if periods is >1. On WASAPI, latency is periods
- // times period size.
-#ifdef _WIN32
- return ((ma->device.playback.internalPeriodSizeInFrames * ma->device.playback.internalPeriods) /
-#else
- return ((ma->device.playback.internalPeriodSizeInFrames) /
-#endif
- (ma->device.playback.internalSampleRate / 1000000.0));
+ return (ma->device.playback.internalPeriodSizeInFrames * ma->device.playback.internalPeriods) /
+ (ma->device.playback.internalSampleRate / 1000000.0);
}
static void audio_miniaudio_start(struct camu_audio *audio)
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
index e6fd178..5af63b7 100644
--- a/src/mixer/mixer.c
+++ b/src/mixer/mixer.c
@@ -7,7 +7,7 @@
#define MIXER_WANT_INITIAL_SILENCE 1
// Number of silent frames to append before signaling MIXER_EMPTY.
-#define MIXER_TRAILING_SILENCE 100
+#define MIXER_TRAILING_SILENCE 20
static s32 data_callback(void *userdata, u8 *data, s32 frame_count, bool *silence)
{