summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/audio.c40
-rw-r--r--src/buffer/audio.h2
-rw-r--r--src/buffer/frame_queue.h6
-rw-r--r--src/buffer/video.c23
-rw-r--r--src/buffer/video.h8
5 files changed, 40 insertions, 39 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index eaac16f..8e0d428 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -11,11 +11,11 @@
#define BUFFER_SIZE 8.0
#define BUFFER_MARK_MIN 3.25 // Must be a most half of the buffer size.
-#define BUFFER_MARK_BUFFERED 1.0
+#define BUFFER_MARK_BUFFERED 0.25
#ifdef CAMU_AUDIO_BUFFER_FADE
#define FADE_STEP(fmt) (2.50f / (fmt)->sample_rate)
-#define FADE_MIN(fmt) (8000.f / (fmt)->sample_rate)
+#define FADE_MIN 0.175f
#endif
enum {
@@ -32,6 +32,7 @@ static void reset_buffer_state(struct camu_audio_buffer *buf)
al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
buf->pause = PAUSE_PAUSED;
al_atomic_store(u32)(&buf->unpause, 0, AL_ATOMIC_RELAXED);
+ buf->logged_delay = false;
al_atomic_store(u32)(&buf->volume.set, 0, AL_ATOMIC_RELAXED);
buf->buffered = false;
al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
@@ -120,8 +121,7 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32
{
f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
- if (sample_count > 0) {
- al_assert(data);
+ if (data && sample_count > 0) {
f64 duration = camu_audio_format_samples_to_sec(&buf->fmt.in, sample_count);
if (frame_is_late(buf->clock, base_pts, pts, duration)) {
return true;
@@ -131,7 +131,6 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32
data = buf->resampler->get_data(buf->resampler);
}
} else {
- al_assert(!data);
if (buf->fmt.resampler_needed) {
sample_count = buf->resampler->flush(buf->resampler);
data = buf->resampler->get_data(buf->resampler);
@@ -148,10 +147,10 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32
return true;
}
+ // The maximum space is buf->size - 1.
ptrdiff_t space = al_ring_buffer_space(&buf->rb);
- if (!buf->buffered && buf->size - space > buf->mark.buffered) {
- al_log_debug("audio_buffer", "Buffered (mark: %.2fs).",
- camu_audio_format_bytes_to_sec(&buf->fmt.req, buf->size - space));
+ if (!buf->buffered && (buf->size - 1) - space >= buf->mark.buffered) {
+ al_log_debug("audio_buffer", "Buffered (mark: %.1fkb).", buf->mark.buffered / 1024.0);
buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED);
buf->buffered = true;
}
@@ -230,8 +229,7 @@ void camu_audio_buffer_flush(struct camu_audio_buffer *buf)
}
if (!buf->buffered) {
- al_log_debug("audio_buffer", "Buffered (mark: %.2fs).",
- camu_audio_format_bytes_to_sec(&buf->fmt.req, al_ring_buffer_occupied(&buf->rb)));
+ al_log_debug("audio_buffer", "Buffered (flush).");
buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED);
buf->buffered = true;
}
@@ -275,12 +273,16 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
(buf->fade.volume == 0.f)) {
al_memset(data, 0, req);
if (buf->pause == PAUSE_FADING_COMPLETE) {
- buf->callback(buf->userdata, CAMU_BUFFER_PAUSED);
- buf->pause = PAUSE_PAUSED;
+ if (!--buf->fade.tail) {
+ buf->callback(buf->userdata, CAMU_BUFFER_PAUSED);
+ buf->pause = PAUSE_PAUSED;
+ }
} else if (buf->pause != PAUSE_PAUSED) {
// Don't signal PAUSED until the next read to ensure at least 1 silent
// frame is included in the fade out.
buf->pause = PAUSE_FADING_COMPLETE;
+ // How many frames of silence to append after fading.
+ buf->fade.tail = 1;
}
return req;
}
@@ -314,7 +316,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
if (!buf->ignore_desync && al_atomic_load(u32)(&buf->unpause, AL_ATOMIC_ACQUIRE) > 0) {
// Queuing multiple resyncs before resuming the stream will cause pops!
- al_log_debug("audio_buffer", "Forcing resync.");
+ al_log_info("audio_buffer", "Forcing resync.");
buf->pause = PAUSE_PAUSED;
al_atomic_sub(u32)(&buf->unpause, 1, AL_ATOMIC_RELEASE);
}
@@ -342,13 +344,17 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
} else if (pts < 0.0) { // Delay.
pts = -pts;
ret = MIN((ptrdiff_t)camu_audio_format_sec_to_bytes(fmt, pts), req);
- al_log_info("audio_buffer", "Delaying audio by %fs.", pts);
+ if (!buf->logged_delay) {
+ al_log_info("audio_buffer", "Delaying audio by %fs.", pts);
+ buf->logged_delay = true;
+ }
al_memset(data, 0, ret);
data += ret;
req -= ret;
// We can continue to delay.
if (req == 0) goto out;
}
+ buf->logged_delay = false;
}
buf->pause = PAUSE_PLAYING;
}
@@ -420,7 +426,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
// fades if the volume is low.
step *= buf->volume.user;
}
- step *= MAX(buf->fade.volume, FADE_MIN(fmt));
+ step *= MAX(buf->fade.volume, FADE_MIN);
buf->fade.volume = apply_volume(data, req, fmt, buf->fade.volume, buf->volume.user, step);
}
#else
@@ -443,8 +449,8 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
}
out:
- // We are not safe to increment buf->pts from a different thread.
- // We would need to accumulate the difference and do an atomic add here.
+ // We aren't safe to increment buf->pts from a different thread.
+ // For that we could accumulate the difference and atomic_add here instead.
al_atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
// To signal EOF, return less then req.
diff --git a/src/buffer/audio.h b/src/buffer/audio.h
index ef907bd..5fa2473 100644
--- a/src/buffer/audio.h
+++ b/src/buffer/audio.h
@@ -21,6 +21,7 @@ struct camu_audio_buffer {
atomic(bool) no_video;
u8 pause;
+ bool logged_delay;
atomic(u32) unpause;
struct camu_resampler_format fmt;
@@ -47,6 +48,7 @@ struct camu_audio_buffer {
struct {
f32 volume;
ptrdiff_t offset;
+ u32 tail;
} fade;
#endif
diff --git a/src/buffer/frame_queue.h b/src/buffer/frame_queue.h
index fdb49b5..ca47457 100644
--- a/src/buffer/frame_queue.h
+++ b/src/buffer/frame_queue.h
@@ -16,14 +16,12 @@ enum {
struct camu_frame_queue {
struct camu_video_buffer *buf;
-#ifdef CAMU_HAVE_FFMPEG
- bool (*configure_subtitles)(struct camu_frame_queue *, u32, u32, AVCodecParameters *);
-#endif
+ bool (*configure_subtitles)(struct camu_frame_queue *, u32, u32, struct camu_codec_stream *);
void (*push)(struct camu_frame_queue *, struct camu_codec_frame *, f64);
#ifdef CAMU_HAVE_FFMPEG
void (*push_av_frame)(struct camu_frame_queue *, AVFrame *, f64);
- void (*push_subtitle)(struct camu_frame_queue *, AVPacket *);
#endif
+ void (*push_subtitle)(struct camu_frame_queue *, struct camu_codec_packet *);
void (*flush)(struct camu_frame_queue *);
s32 (*count)(struct camu_frame_queue *);
u8 (*read)(struct camu_frame_queue *, f64, void *);
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 2fc5773..34672fb 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -12,8 +12,8 @@
#include "../codec/ffmpeg/scaler.h"
#endif
-#define BUFFER_MARK_LOW ((1.0 / 30.0) * 6)
-#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 5) // Must be >1.
+#define BUFFER_MARK_LOW ((1.0 / 30.0) * 8)
+#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 4) // Must be >1.
#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 12)
#define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2.0)
@@ -117,13 +117,12 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code
return true;
}
-#ifdef CAMU_HAVE_FFMPEG
-bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, AVCodecParameters *codecpar)
+bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, struct camu_codec_stream *stream)
{
+ if (!buf->queue) return false;
struct camu_video_format *fmt = &buf->stream->video.fmt;
- return buf->queue->configure_subtitles(buf->queue, fmt->width, fmt->height, codecpar);
+ return buf->queue->configure_subtitles(buf->queue, fmt->width, fmt->height, stream);
}
-#endif
void camu_video_buffer_set_latency(struct camu_video_buffer *buf, s32 frames)
{
@@ -168,6 +167,7 @@ static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame
f64 duration = camu_ff_frame_duration(frame) * av_q2d(stream->time_base);
f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
if (!buf->single_frame && frame_is_late(buf->clock, base_pts, pts, duration)) {
+ al_log_info("video_buffer", "Discarding late frame.");
return false;
}
if (base_pts == -1.0) al_atomic_store(f64)(&buf->pts, pts, AL_ATOMIC_RELEASE);
@@ -215,12 +215,10 @@ void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_fra
after_push_internal(buf);
}
-#ifdef CAMU_HAVE_FFMPEG
-void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, AVPacket *pkt)
+void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, struct camu_codec_packet *packet)
{
- buf->queue->push_subtitle(buf->queue, pkt);
+ if (buf->queue) buf->queue->push_subtitle(buf->queue, packet);
}
-#endif
// flush() always comes from the same thread as push().
void camu_video_buffer_flush(struct camu_video_buffer *buf)
@@ -230,10 +228,9 @@ void camu_video_buffer_flush(struct camu_video_buffer *buf)
buf->queue->flush(buf->queue);
if (!buf->buffered) {
s32 count = buf->queue->count(buf->queue);
- f64 have = count * buf->avg_frame_duration;
buf->buffered = true;
buf->buffered_with_one_frame = count == 1;
- al_log_debug("video_buffer", "Buffered (mark: %.2fs).", have);
+ al_log_debug("video_buffer", "Buffered (flush).");
buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED);
}
}
@@ -286,6 +283,8 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig
if (ret == CAMU_QUEUE_OK) {
*weighted = buf->weighted_read;
buf->weighted_read = false;
+ } else if (ret == CAMU_QUEUE_MORE) {
+ al_log_warn("video_buffer", "Underrun.");
}
return ret == CAMU_QUEUE_OK || ret == CAMU_QUEUE_MORE;
diff --git a/src/buffer/video.h b/src/buffer/video.h
index 0814251..c587af1 100644
--- a/src/buffer/video.h
+++ b/src/buffer/video.h
@@ -49,15 +49,11 @@ struct camu_video_buffer {
bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock);
bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_codec_stream *stream,
struct camu_renderer *renderer);
-#ifdef CAMU_HAVE_FFMPEG
-bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, AVCodecParameters *codecpar);
-#endif
+bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, struct camu_codec_stream *stream);
void camu_video_buffer_set_latency(struct camu_video_buffer *buf, s32 frames);
bool camu_video_buffer_is_single_frame(struct camu_video_buffer *buf);
void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_frame *frame);
-#ifdef CAMU_HAVE_FFMPEG
-void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, AVPacket *pkt);
-#endif
+void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, struct camu_codec_packet *packet);
void camu_video_buffer_flush(struct camu_video_buffer *buf);
void camu_video_buffer_reset(struct camu_video_buffer *buf);
bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weighted);