summaryrefslogtreecommitdiff
path: root/src/liana
diff options
context:
space:
mode:
Diffstat (limited to 'src/liana')
-rw-r--r--src/liana/handlers/codec_server.c4
-rw-r--r--src/liana/list.c8
-rw-r--r--src/liana/meson.build3
-rw-r--r--src/liana/process.c115
-rw-r--r--src/liana/process.h13
-rw-r--r--src/liana/server.c13
-rw-r--r--src/liana/server.h3
7 files changed, 150 insertions, 9 deletions
diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c
index 7868a42..99db398 100644
--- a/src/liana/handlers/codec_server.c
+++ b/src/liana/handlers/codec_server.c
@@ -59,7 +59,9 @@ static void codec_server_write_info(struct lia_server_handler *handler, struct n
nn_packet_write_u8(packet, stream->mode);
nn_packet_write_u8(packet, stream->type);
nn_packet_write_u64(packet, stream->duration);
- nn_packet_write_s32(packet, i);
+ // stream->index = i is currently expected but not necessary.
+ al_assert(stream->index == (s32)i);
+ nn_packet_write_s32(packet, stream->index);
switch (stream->mode) {
case CAMU_NORMAL: {
struct camu_video_format *fmt = &stream->video.fmt;
diff --git a/src/liana/list.c b/src/liana/list.c
index 1c7c6c9..0ceb591 100644
--- a/src/liana/list.c
+++ b/src/liana/list.c
@@ -148,7 +148,8 @@ static void pump_queue(struct lia_list *list);
static bool handle_add_sink(struct lia_list *list, struct lia_list_sink *sink)
{
- if (list->current >= 0 && !list->idle) {
+ // The list being idle is not equivalent to current being unset.
+ if (list->current >= 0) {
struct lia_list_entry *current = al_array_at(list->entries, list->current);
u64 now = nn_get_timestamp();
u8 pause;
@@ -243,9 +244,7 @@ static s32 get_sequence_from_entry_id(struct lia_list *list, u32 id)
// Not returning the entry pointer here is a meaningful simplification.
struct lia_list_entry *entry;
al_array_foreach(list->entries, i, entry) {
- if (entry->id == id) {
- return (s32)i;
- }
+ if (entry->id == id) return i;
}
return -1;
}
@@ -254,6 +253,7 @@ static bool handle_skipto(struct lia_list *list, s32 sequence, s32 index)
{
if (sequence == LIANA_SEQUENCE_ANY) sequence = list->current;
if (sequence < 0) return true; // list->current = -1
+ if (sequence == index) return true;
if (sequence != list->current) {
log_warn("Discarding out of date skip().");
return true;
diff --git a/src/liana/meson.build b/src/liana/meson.build
index 34abc66..12345c9 100644
--- a/src/liana/meson.build
+++ b/src/liana/meson.build
@@ -2,7 +2,8 @@ liana_server_src = [
'list.c',
'server.c',
'handlers/codec_server.c',
- 'handlers.c'
+ 'handlers.c',
+ 'process.c'
]
liana_client_src = [
'client.c',
diff --git a/src/liana/process.c b/src/liana/process.c
new file mode 100644
index 0000000..9a70210
--- /dev/null
+++ b/src/liana/process.c
@@ -0,0 +1,115 @@
+#ifdef CAMU_HAVE_FFMPEG
+#include "../codec/ffmpeg/demuxer.h"
+#include "../codec/ffmpeg/decoder.h"
+#include "../codec/ffmpeg/resampler.h"
+#endif
+
+#include "process.h"
+
+struct raw_samples_data {
+ struct camu_resampler *resampler;
+ u32 channels;
+ u32 bps;
+ struct nn_buffer buf;
+ u32 index;
+};
+
+static u32 append_samples(struct raw_samples_data *raw, u8 *data, u32 sample_count)
+{
+ u32 bytes = sample_count * raw->channels * raw->bps;
+ nn_buffer_write(&raw->buf, data, raw->index, bytes);
+ return bytes;
+}
+
+static void data_callback(void *userdata, struct camu_codec_frame *frame)
+{
+ struct raw_samples_data *raw = (struct raw_samples_data *)userdata;
+ u8 **data = frame->av.frame->data;
+ s32 sample_count = frame->av.frame->nb_samples;
+ sample_count = raw->resampler->convert(raw->resampler, (const u8 **)data, sample_count);
+ data = raw->resampler->get_data(raw->resampler);
+ raw->index += append_samples(raw, data[0], (u32)sample_count);
+}
+
+static void flush_resampler(struct camu_resampler *resampler, struct raw_samples_data *raw)
+{
+ s32 sample_count = resampler->flush(resampler);
+ u8 **data = resampler->get_data(resampler);
+ raw->index += append_samples(raw, data[0], (u32)sample_count);
+}
+
+bool lia_prepare_visual_data(struct cch_handle *handle, struct lia_visual_data *data)
+{
+ struct camu_demuxer *demux = camu_ff_demuxer_create();
+ struct camu_decoder *dec = camu_ff_decoder_create();
+ struct camu_resampler *resampler = camu_ff_resampler_create();
+ data->samples = NULL;
+
+ if (!demux->init(demux, handle)) {
+ goto out;
+ }
+
+ struct camu_codec_stream *stream;
+ struct camu_codec_stream *selected = NULL;
+ al_array_foreach_ptr(demux->streams, i, stream) {
+ if (stream->type == CAMU_STREAM_AUDIO) {
+ selected = stream;
+ break;
+ }
+ }
+ if (!selected) goto out;
+ demux->subscribed = 1 << selected->index;
+
+ struct camu_resampler_format fmt;
+ AVCodecParameters *codecpar = selected->av.stream->codecpar;
+ fmt.in.format = codecpar->format;
+ fmt.req.format = CAMU_SAMPLE_FORMAT_S16;
+ fmt.in.sample_rate = codecpar->sample_rate;
+ fmt.req.sample_rate = codecpar->sample_rate;
+ av_channel_layout_copy(&fmt.in.channel_layout, &codecpar->ch_layout);
+ av_channel_layout_copy(&fmt.req.channel_layout, &codecpar->ch_layout);
+ fmt.in.channel_count = codecpar->ch_layout.nb_channels;
+ fmt.req.channel_count = codecpar->ch_layout.nb_channels;
+
+ struct raw_samples_data raw;
+ raw.resampler = resampler;
+ raw.channels = fmt.req.channel_count;
+ raw.bps = camu_audio_format_bytes_per_sample(&fmt.req);
+ nn_buffer_init(&raw.buf);
+ raw.index = 0;
+
+ if (!dec->init(dec, NULL, selected, data_callback, &raw)) {
+ goto out;
+ }
+
+ fmt.resampler_needed = true;
+ if (!resampler->init(resampler, &fmt)) {
+ goto out;
+ }
+
+ AVPacket *pkt = av_packet_alloc();
+ struct camu_codec_packet packet = { .av.pkt = pkt };
+ s32 status;
+ do {
+ status = demux->get_packet(demux, &packet);
+ if (status == CAMU_OK) {
+ dec->push_av_packet(dec, pkt);
+ dec->process(dec);
+ av_packet_unref(pkt);
+ }
+ } while (status == CAMU_OK);
+ dec->flush(dec);
+ flush_resampler(resampler, &raw);
+
+ data->size = raw.index;
+ data->samples = raw.buf.data;
+ data->count = raw.index / raw.channels / raw.bps;
+ camu_audio_format_copy(&data->fmt, &fmt.req);
+
+out:
+ demux->free(&demux);
+ dec->free(&dec);
+ resampler->free(&resampler);
+
+ return data->samples != NULL;
+}
diff --git a/src/liana/process.h b/src/liana/process.h
new file mode 100644
index 0000000..a71728b
--- /dev/null
+++ b/src/liana/process.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "../codec/codec.h"
+#include "../cache/handle.h"
+
+struct lia_visual_data {
+ struct camu_audio_format fmt;
+ u32 size;
+ u8 *samples;
+ u32 count;
+};
+
+bool lia_prepare_visual_data(struct cch_handle *handle, struct lia_visual_data *data);
diff --git a/src/liana/server.c b/src/liana/server.c
index abf4154..9d1f42a 100644
--- a/src/liana/server.c
+++ b/src/liana/server.c
@@ -1,6 +1,7 @@
#include "server.h"
#include "handler.h"
#include "handlers.h"
+#include "process.h"
#include "list.h"
static inline u32 get_incremental_id(struct lia_server *server)
@@ -445,16 +446,24 @@ static void duration_signal_callback(void *userdata)
nn_signal_stop(&node->signal);
nn_thread_join(&node->thread);
node->handler->free(&node->handler);
+ bool got_visual_data = false;
+ struct lia_visual_data visual_data;
+ //cch_handle_seek(&node->handle, 0, SEEK_SET);
+ //got_visual_data = lia_prepare_visual_data(&node->handle, &visual_data);
cch_entry_return_handle(node->entry, &node->handle);
if (should_free_node(node)) {
free_node(node);
} else {
if (node->errored) {
- node->callback(node->userdata, LIANA_NODE_ERRORED, LIANA_TIMESTAMP_INVALID);
+ al_assert(node->duration == LIANA_TIMESTAMP_INVALID);
+ node->callback(node->userdata, LIANA_NODE_ERRORED, &node->duration);
} else {
- node->callback(node->userdata, LIANA_NODE_DURATION, node->duration);
+ node->callback(node->userdata, LIANA_NODE_DURATION, &node->duration);
}
}
+ if (got_visual_data) {
+ node->callback(node->userdata, LIANA_NODE_VISUAL_DATA, &visual_data);
+ }
}
void lia_node_get_duration(struct lia_node *node)
diff --git a/src/liana/server.h b/src/liana/server.h
index 679d607..13f4a6e 100644
--- a/src/liana/server.h
+++ b/src/liana/server.h
@@ -41,6 +41,7 @@ struct lia_node_connection {
enum {
LIANA_NODE_DURATION = 0,
+ LIANA_NODE_VISUAL_DATA,
LIANA_NODE_ERRORED
};
@@ -52,7 +53,7 @@ struct lia_node {
bool closed;
u64 duration;
struct lia_server *server;
- void (*callback)(void *, u8, u64);
+ void (*callback)(void *, u8, void *);
void *userdata;
// Temporary copy-paste from node_connection.
bool errored;