summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-01-05 20:42:51 -0500
committerAndrew Opalach <andrew@akon.city> 2025-01-05 20:42:51 -0500
commit240ee00a9177d6ff80ef48ce577b06d93cb554c2 (patch)
tree0f759e7a9fe28ae0d21a54917ca893131aef9dda
parent9362f2223038b59954c8402963932b4eb77030be (diff)
downloadcamu-240ee00a9177d6ff80ef48ce577b06d93cb554c2.tar.gz
camu-240ee00a9177d6ff80ef48ce577b06d93cb554c2.tar.bz2
camu-240ee00a9177d6ff80ef48ce577b06d93cb554c2.zip
Temp fix for stream selection, compile fixes
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--src/codec/codec.h19
-rw-r--r--src/codec/ffmpeg/common.c10
-rw-r--r--src/liana/client.c48
-rw-r--r--src/liana/handlers/codec_client.c2
-rw-r--r--src/libsink/sink.c31
-rw-r--r--src/screen/screen.c1
6 files changed, 65 insertions, 46 deletions
diff --git a/src/codec/codec.h b/src/codec/codec.h
index 6ddcff9..fac3be8 100644
--- a/src/codec/codec.h
+++ b/src/codec/codec.h
@@ -255,20 +255,23 @@ static inline s32 camu_audio_format_bytes_per_sample(struct camu_audio_format *f
#else
switch (fmt->format) {
case CAMU_SAMPLE_FORMAT_U8:
- case CAMU_SAMPLE_FORMAT_U8P: return 1;
+ case CAMU_SAMPLE_FORMAT_U8P:
+ return 1;
case CAMU_SAMPLE_FORMAT_S16:
- case CAMU_SAMPLE_FORMAT_S16P: return 2;
+ case CAMU_SAMPLE_FORMAT_S16P:
+ return 2;
case CAMU_SAMPLE_FORMAT_S32:
case CAMU_SAMPLE_FORMAT_S32P:
case CAMU_SAMPLE_FORMAT_FLT:
- case CAMU_SAMPLE_FORMAT_FLTP: return 4;
+ case CAMU_SAMPLE_FORMAT_FLTP:
+ return 4;
case CAMU_SAMPLE_FORMAT_S64:
case CAMU_SAMPLE_FORMAT_S64P:
case CAMU_SAMPLE_FORMAT_DBL:
- case CAMU_SAMPLE_FORMAT_DBLP: return 8;
+ case CAMU_SAMPLE_FORMAT_DBLP:
+ return 8;
default:
- al_assert(false);
- return -1;
+ al_assert_and_return(-1);
}
#endif
}
@@ -323,8 +326,8 @@ static const char *camu_pixel_format_name(s32 format)
case CAMU_PIXEL_FORMAT_RGB: return "rgb";
case CAMU_PIXEL_FORMAT_GREYA: return "grey + alpha";
case CAMU_PIXEL_FORMAT_GREY: return "grey";
+ default: return "(unknown)";
}
- return "(unknown)";
}
static inline s32 camu_pixel_format_from_channels(s32 channels)
@@ -334,7 +337,7 @@ static inline s32 camu_pixel_format_from_channels(s32 channels)
case 3: return CAMU_PIXEL_FORMAT_RGB;
case 2: return CAMU_PIXEL_FORMAT_GREYA;
case 1: return CAMU_PIXEL_FORMAT_GREY;
- default: al_assert(false); return CAMU_PIXEL_FORMAT_GREY;
+ default: al_assert_and_return(CAMU_PIXEL_FORMAT_GREY);
}
}
diff --git a/src/codec/ffmpeg/common.c b/src/codec/ffmpeg/common.c
index b2e727d..95bf247 100644
--- a/src/codec/ffmpeg/common.c
+++ b/src/codec/ffmpeg/common.c
@@ -10,18 +10,20 @@ void camu_ff_set_log_callback(void (*callback)(void *, s32, const char *, va_lis
}
static char *buf = NULL;
-static s32 pos = 0;
+static size_t pos = 0;
// If a line takes more than 2 steps to print, make sure we stay within AL_LOG_MESSAGE_SIZE.
-#define CHUNK_SIZE (AL_LOG_MESSAGE_SIZE / 2)
+#define CHUNK_SIZE (AL_LOG_MESSAGE_SIZE / 2u)
static void av_log_callback(void *userdata, s32 level, const char *fmt, va_list args)
{
(void)userdata;
al_assert(buf);
if (level < AV_LOG_DEBUG) {
- pos += al_vsnprintf(&buf[pos], CHUNK_SIZE, fmt, args);
- if (buf[pos - 1] == '\n' || pos >= CHUNK_SIZE) {
+ s32 ret = al_vsnprintf(&buf[pos], CHUNK_SIZE, fmt, args);
+ al_assert(ret > 0);
+ pos += ret;
+ if ((pos > 0 && buf[pos - 1] == '\n') || pos >= CHUNK_SIZE) {
if (level <= AV_LOG_INFO) {
al_log_info("ff", buf);
} else {
diff --git a/src/liana/client.c b/src/liana/client.c
index daf32b0..b6635af 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -22,6 +22,12 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe
str liana;
nn_packet_read_str(packet, &liana);
client->duration = nn_packet_read_u64(packet);
+ // TODO: This should be made into 2 steps.
+ // 1. Collect all streams into an array
+ // 2. Perform selection based on prefrences.
+ bool have_audio = false;
+ bool have_video = false;
+ bool have_subs = false;
u32 count = nn_packet_read_u32(packet);
for (u32 i = 0; i < count; i++) {
u8 mode = nn_packet_read_u8(packet);
@@ -52,37 +58,42 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe
}
#ifdef CAMU_HAVE_FFMPEG
case CAMU_FFMPEG_COMPAT: {
+ enum AVCodecID codec_id = nn_packet_read_av_codec_id(packet);
+ const AVCodec *codec = avcodec_find_decoder(codec_id);
+ AVFormatContext *format_context = avformat_alloc_context();
+ AVStream *stream = nn_packet_read_av_stream(format_context, codec, packet);
switch (type) {
case CAMU_STREAM_AUDIO:
+ if (have_audio) {
+ goto skip;
+ }
client->mask |= 1 << index;
+ have_audio = true;
break;
case CAMU_STREAM_VIDEO:
+ if (have_video) {
+ goto skip;
+ }
client->mask |= 1 << index;
+ have_video = true;
break;
case CAMU_STREAM_SUBTITLE:
+ if (have_subs || codec_id != AV_CODEC_ID_ASS) {
+ goto skip;
+ }
client->mask |= 1 << index;
+ have_subs = true;
break;
- case CAMU_STREAM_ATTACHMENT:
- // Assume all the data we need is in the AVStream object.
- break;
- default:
- continue;
- }
- enum AVCodecID codec_id = nn_packet_read_av_codec_id(packet);
- const AVCodec *codec = avcodec_find_decoder(codec_id);
- AVFormatContext *format_context = avformat_alloc_context();
- AVStream *stream = nn_packet_read_av_stream(format_context, codec, packet);
- if (type == CAMU_STREAM_SUBTITLE && codec_id != AV_CODEC_ID_ASS) {
- client->mask &= ~(1 << index);
- continue;
- }
- if (type == CAMU_STREAM_ATTACHMENT) {
+ case CAMU_STREAM_ATTACHMENT: {
struct camu_codec_stream attachment;
attachment.type = CAMU_STREAM_ATTACHMENT;
attachment.av.stream = stream;
client->callback(client->userdata, LIANA_CLIENT_CONFIGURE, &attachment, track);
- avformat_free_context(format_context);
- continue;
+ // Assume all the data we need is in the AVStream object.
+ // fallthrough
+ }
+ default:
+ goto skip;
}
track = al_alloc_object(struct lia_vcr_track);
track->stream.av.format_context = format_context;
@@ -95,6 +106,9 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe
fmt->channel_count = stream->codecpar->ch_layout.nb_channels;
}
break;
+skip:
+ avformat_free_context(format_context);
+ continue;
}
#endif
}
diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c
index 2492533..0aef69f 100644
--- a/src/liana/handlers/codec_client.c
+++ b/src/liana/handlers/codec_client.c
@@ -65,9 +65,11 @@ static bool codec_client_handle_packet(struct lia_client_handler *handler, struc
case CAMU_NORMAL:
codec->dec->push(codec->dec, NULL);
break;
+#ifdef CAMU_HAVE_FFMPEG
case CAMU_FFMPEG_COMPAT:
codec->dec->push_av_packet(codec->dec, NULL);
break;
+#endif
}
// process() could still error.
s32 ret = codec->dec->process(codec->dec);
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 97f1d66..03f76b7 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -65,11 +65,6 @@ enum {
#define VIDEO_EMPTY(entry) BUFFER_EMPTY(&(entry)->video)
#endif
-#define AUDIO_NOT_EMPTY(entry) BUFFER_NOT_EMPTY(&(entry)->audio)
-#ifndef CAMU_SINK_NO_VIDEO
-#define VIDEO_NOT_EMPTY(entry) BUFFER_NOT_EMPTY(&(entry)->video)
-#endif
-
#define AUDIO_ADDED_OR_EMPTY(entry) ((entry)->audio.state == BUFFER_ADDED || BUFFER_EMPTY(&(entry)->audio))
#ifndef CAMU_SINK_NO_VIDEO
#define VIDEO_ADDED_OR_EMPTY(entry) ((entry)->video.state == BUFFER_ADDED || BUFFER_EMPTY(&(entry)->video))
@@ -237,7 +232,7 @@ static void sink_local_pause(struct camu_sink *sink, struct camu_sink_entry *ent
if (camu_clock_is_paused(&entry->clock)) {
entry->audio.buffer_paused = false;
camu_clock_resume(&entry->clock, 0);
- if (AUDIO_NOT_EMPTY(entry) && sink->audio.state == SINK_PAUSED) {
+ if (!AUDIO_EMPTY(entry) && sink->audio.state == SINK_PAUSED) {
sink->callback(sink->userdata, CAMU_SINK_START, CAMU_SINK_AUDIO, NULL);
sink->audio.state = SINK_PLAYING;
}
@@ -790,6 +785,7 @@ static void audio_buffer_callback(void *userdata, u8 op)
break;
}
case CAMU_BUFFER_ERRORED:
+ al_log_error("sink", "Audio buffer errored.");
break;
}
}
@@ -817,7 +813,7 @@ static void video_buffer_callback(void *userdata, u8 op)
bool swapped = false;
nn_mutex_lock(&sink->mutex);
al_log_info("sink", "Video EOF.");
- if (AUDIO_NOT_EMPTY(entry)) {
+ if (!AUDIO_EMPTY(entry)) {
camu_audio_buffer_set_no_video(&entry->audio.buf, true);
}
if (!VIDEO_IS_SINGLE_FRAME(entry)) {
@@ -840,6 +836,7 @@ static void video_buffer_callback(void *userdata, u8 op)
break;
}
case CAMU_BUFFER_ERRORED:
+ al_log_error("sink", "Video buffer errored.");
break;
}
}
@@ -874,7 +871,7 @@ static void evaluate_latency(struct camu_sink *sink, struct camu_sink_entry *ent
{
#ifdef CAMU_SINK_LOCAL
#ifndef CAMU_SINK_NO_VIDEO
- if (AUDIO_NOT_EMPTY(entry) && VIDEO_NOT_EMPTY(entry)) {
+ if (!AUDIO_EMPTY(entry) && !VIDEO_EMPTY(entry)) {
f64 audio = camu_mixer_get_latency(sink->audio.mixer);
s32 frames = audio / entry->video.buf.avg_frame_duration;
frames -= sink->video.renderer->get_latency(sink->video.renderer);
@@ -889,7 +886,7 @@ static void evaluate_latency(struct camu_sink *sink, struct camu_sink_entry *ent
// latency directly into the audio buffer.
f64 audio = camu_mixer_get_latency(sink->audio.mixer);
#ifndef CAMU_SINK_NO_VIDEO
- if (VIDEO_NOT_EMPTY(entry)) {
+ if (!VIDEO_EMPTY(entry)) {
s32 frames = audio / entry->video.buf.avg_frame_duration;
frames += sink->video.renderer->get_latency(sink->video.renderer);
camu_video_buffer_set_latency(&entry->video.buf, frames);
@@ -933,7 +930,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
} else if (entry->audio.state == BUFFER_INIT) {
entry->audio.state = BUFFER_CONFIGURED;
} else {
- assert(false);
+ al_assert(false);
}
if (VIDEO_ADDED_OR_EMPTY(entry)) {
evaluate_latency(sink, entry);
@@ -954,7 +951,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
} else if (entry->video.state == BUFFER_INIT) {
entry->video.state = BUFFER_CONFIGURED;
} else {
- assert(false);
+ al_assert(false);
}
if (AUDIO_ADDED_OR_EMPTY(entry)) {
evaluate_latency(sink, entry);
@@ -985,14 +982,14 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
struct camu_codec_frame *frame = (struct camu_codec_frame *)opaque;
switch (stream->type) {
case CAMU_STREAM_AUDIO:
- if (AUDIO_NOT_EMPTY(entry)) {
+ if (!AUDIO_EMPTY(entry)) {
camu_audio_buffer_push(&entry->audio.buf, frame);
return;
}
break;
#ifndef CAMU_SINK_NO_VIDEO
case CAMU_STREAM_VIDEO:
- if (VIDEO_NOT_EMPTY(entry)) {
+ if (!VIDEO_EMPTY(entry)) {
camu_video_buffer_push(&entry->video.buf, frame);
return;
}
@@ -1074,11 +1071,11 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
) { BLOCKING_SLEEP(NNWT_TS_FROM_USEC(2000)); }
if (reconnect) {
- if (AUDIO_NOT_EMPTY(entry)) {
+ if (!AUDIO_EMPTY(entry)) {
camu_audio_buffer_reset(&entry->audio.buf);
}
#ifndef CAMU_SINK_NO_VIDEO
- if (VIDEO_NOT_EMPTY(entry) && !ignore_video) {
+ if (!VIDEO_EMPTY(entry) && !ignore_video) {
camu_video_buffer_reset(&entry->video.buf);
}
#endif
@@ -1122,7 +1119,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
case LIANA_CLIENT_EOF: {
switch (stream->type) {
case CAMU_STREAM_AUDIO: {
- if (AUDIO_NOT_EMPTY(entry)) {
+ if (!AUDIO_EMPTY(entry)) {
camu_audio_buffer_flush(&entry->audio.buf);
}
break;
@@ -1130,7 +1127,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str
#ifndef CAMU_SINK_NO_VIDEO
case CAMU_STREAM_VIDEO: {
// Single frames are immediately flushed inside the buffer.
- if (VIDEO_NOT_EMPTY(entry) && !VIDEO_IS_SINGLE_FRAME(entry)) {
+ if (!VIDEO_EMPTY(entry) && !VIDEO_IS_SINGLE_FRAME(entry)) {
camu_video_buffer_flush(&entry->video.buf);
}
break;
diff --git a/src/screen/screen.c b/src/screen/screen.c
index de7c8a7..e76650f 100644
--- a/src/screen/screen.c
+++ b/src/screen/screen.c
@@ -1,5 +1,6 @@
#include <al/log.h>
#include <nnwt/thread.h>
+#include <math.h>
#include "view.h"
#include "screen.h"