summaryrefslogtreecommitdiff
path: root/src/liana/handlers
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-10-21 19:22:50 -0400
committerAndrew Opalach <andrew@akon.city> 2024-10-21 19:22:50 -0400
commit60b4ebfbf3be78dba9dc7c65ab2bdaa0b218c0c2 (patch)
tree08ff2ce7975f523112e7ad2fe4f797b4fc7db5de /src/liana/handlers
parent2f9a0945bfeee3296cec3d38d094e4c49f9cb65f (diff)
downloadcamu-60b4ebfbf3be78dba9dc7c65ab2bdaa0b218c0c2.tar.gz
camu-60b4ebfbf3be78dba9dc7c65ab2bdaa0b218c0c2.tar.bz2
camu-60b4ebfbf3be78dba9dc7c65ab2bdaa0b218c0c2.zip
Everything before initial synced list
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/liana/handlers')
-rw-r--r--src/liana/handlers/cdio.h18
-rw-r--r--src/liana/handlers/cdio_client.c49
-rw-r--r--src/liana/handlers/cdio_server.c106
-rw-r--r--src/liana/handlers/codec.h19
-rw-r--r--src/liana/handlers/codec_client.c116
-rw-r--r--src/liana/handlers/codec_server.c143
-rw-r--r--src/liana/handlers/dvd.h14
-rw-r--r--src/liana/handlers/dvd_server.c21
8 files changed, 486 insertions, 0 deletions
diff --git a/src/liana/handlers/cdio.h b/src/liana/handlers/cdio.h
new file mode 100644
index 0000000..2727616
--- /dev/null
+++ b/src/liana/handlers/cdio.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "../handler.h"
+
+struct lia_cdio_server {
+ struct lia_server_handler handler;
+ struct cch_handle *handle;
+ struct camu_audio_format fmt;
+ f64 pts;
+ struct aki_buffer buffer;
+};
+
+struct lia_cdio_client {
+ struct lia_client_handler handler;
+};
+
+struct lia_server_handler *lia_cdio_server_create();
+struct lia_client_handler *lia_cdio_client_create(void);
diff --git a/src/liana/handlers/cdio_client.c b/src/liana/handlers/cdio_client.c
new file mode 100644
index 0000000..93b1a27
--- /dev/null
+++ b/src/liana/handlers/cdio_client.c
@@ -0,0 +1,49 @@
+#include "cdio.h"
+
+static bool cdio_client_init(struct lia_client_handler *handler, struct camu_renderer *renderer,
+ struct camu_codec_stream *stream)
+{
+ struct lia_cdio_client *cdio = (struct lia_cdio_client *)handler;
+ (void)renderer;
+ cdio->handler.stream = stream;
+ return true;
+}
+
+static bool cdio_client_handle_packet(struct lia_client_handler *handler, struct aki_packet *packet)
+{
+ struct lia_cdio_client *cdio = (struct lia_cdio_client *)handler;
+ if (!packet) {
+ cdio->handler.callback(cdio->handler.userdata, LIANA_CLIENT_EOF, cdio->handler.stream, NULL);
+ return true;
+ }
+ struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
+ frame->mode = CAMU_NORMAL;
+ frame->pts = aki_packet_read_f64(packet);
+ frame->audio.sample_count = aki_packet_read_s32(packet);
+ struct aki_buffer buffer;
+ aki_packet_read_buffer(packet, &buffer);
+ frame->data = al_malloc(buffer.size);
+ al_memcpy(frame->data, aki_buffer_get_ptr(&buffer, 0), buffer.size);
+ cdio->handler.callback(cdio->handler.userdata, LIANA_CLIENT_DATA, cdio->handler.stream, frame);
+ return true;
+}
+
+static void cdio_client_flush(struct lia_client_handler *handler)
+{
+ (void)handler;
+}
+
+static void cdio_client_free(struct lia_client_handler **handler)
+{
+ (void)handler;
+}
+
+struct lia_client_handler *lia_cdio_client_create(void)
+{
+ struct lia_cdio_client *cdio = al_alloc_object(struct lia_cdio_client);
+ cdio->handler.init = cdio_client_init;
+ cdio->handler.handle_packet = cdio_client_handle_packet;
+ cdio->handler.flush = cdio_client_flush;
+ cdio->handler.free = cdio_client_free;
+ return (struct lia_client_handler *)cdio;
+}
diff --git a/src/liana/handlers/cdio_server.c b/src/liana/handlers/cdio_server.c
new file mode 100644
index 0000000..1eaf6f3
--- /dev/null
+++ b/src/liana/handlers/cdio_server.c
@@ -0,0 +1,106 @@
+#include <al/log.h>
+#include <cdio/paranoia/cdda.h>
+
+#include "../../cache/entry.h"
+#include "../../cache/handlers/cdio.h"
+
+#include "cdio.h"
+
+#define SECTORS_PER_PACKET 8
+
+static bool cdio_server_init(struct lia_server_handler *handler, struct cch_handle *handle)
+{
+ struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
+ cdio->handle = handle;
+
+ cdio->fmt.format = CAMU_SAMPLE_FORMAT_S16;
+ cdio->fmt.sample_rate = 44100;
+ cdio->fmt.channel_count = 2;
+ cdio->pts = 0.0;
+ aki_buffer_init(&cdio->buffer);
+
+ if (handle->entry->chapter) {
+ cch_handle_seek(handle, handle->entry->chapter->start * CDIO_CD_FRAMESIZE_RAW, SEEK_SET);
+ }
+
+ return true;
+}
+
+static void cdio_server_write_info(struct lia_server_handler *handler, struct aki_packet *packet)
+{
+ struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
+ aki_packet_write_u64(packet, 0);
+ aki_packet_write_u32(packet, 1);
+ aki_packet_write_u8(packet, CAMU_NORMAL);
+ aki_packet_write_u8(packet, CAMU_STREAM_AUDIO);
+ aki_packet_write_s32(packet, cdio->fmt.format);
+ aki_packet_write_s32(packet, cdio->fmt.sample_rate);
+ aki_packet_write_s32(packet, cdio->fmt.channel_count);
+}
+
+static void cdio_server_subscribe(struct lia_server_handler *handler, s32 mask)
+{
+ (void)handler;
+ (void)mask;
+}
+
+static u64 cdio_server_get_duration(struct lia_server_handler *handler)
+{
+ (void)handler;
+ return 0;
+}
+
+static bool cdio_server_seek(struct lia_server_handler *handler, u64 pos)
+{
+ struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
+ return cch_handle_seek(cdio->handle, pos, SEEK_SET);
+}
+
+static void cdio_server_step(struct lia_server_handler *handler)
+{
+ struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
+ (void)cdio;
+}
+
+static void cdio_server_write_packet(struct lia_server_handler *handler, struct aki_packet *packet)
+{
+ struct lia_cdio_server *cdio = (struct lia_cdio_server *)handler;
+ off_t size = CDIO_CD_FRAMESIZE_RAW * SECTORS_PER_PACKET;
+ aki_buffer_ensure_space(&cdio->buffer, size);
+ s32 ret = cch_handle_read(cdio->handle, aki_buffer_get_ptr(&cdio->buffer, 0), size);
+ if (ret == CAMU_ERR_EOF) {
+ cdio->handler.status = CAMU_ERR_EOF;
+ aki_packet_write_u8(packet, LIANA_PACKET_EOF);
+ return;
+ }
+ cdio->handler.status = CAMU_OK;
+ aki_packet_write_u8(packet, LIANA_PACKET_DATA);
+ aki_packet_write_s32(packet, 0);
+ aki_packet_write_f64(packet, cdio->pts);
+ s32 sample_count = ret / (camu_audio_format_bytes_per_sample(&cdio->fmt) * cdio->fmt.channel_count);
+ cdio->pts += camu_audio_format_samples_to_sec(&cdio->fmt, sample_count);
+ aki_packet_write_s32(packet, sample_count);
+ aki_buffer_set_size(&cdio->buffer, ret);
+ aki_packet_write_buffer(packet, &cdio->buffer);
+}
+
+static void cdio_server_free(struct lia_server_handler **handler)
+{
+ struct lia_cdio_server *cdio = (struct lia_cdio_server *)*handler;
+ al_free(cdio);
+ *handler = NULL;
+}
+
+struct lia_server_handler *lia_cdio_server_create()
+{
+ struct lia_cdio_server *cdio = al_alloc_object(struct lia_cdio_server);
+ cdio->handler.init = cdio_server_init;
+ cdio->handler.write_info = cdio_server_write_info;
+ cdio->handler.subscribe = cdio_server_subscribe;
+ cdio->handler.get_duration = cdio_server_get_duration;
+ cdio->handler.seek = cdio_server_seek;
+ cdio->handler.step = cdio_server_step;
+ cdio->handler.write_packet = cdio_server_write_packet;
+ cdio->handler.free = cdio_server_free;
+ return (struct lia_server_handler *)cdio;
+}
diff --git a/src/liana/handlers/codec.h b/src/liana/handlers/codec.h
new file mode 100644
index 0000000..8c5528f
--- /dev/null
+++ b/src/liana/handlers/codec.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "../../codec/codec.h"
+
+#include "../handler.h"
+
+struct lia_codec_server {
+ struct lia_server_handler handler;
+ struct camu_demuxer *demux;
+ struct camu_codec_packet packet;
+};
+
+struct lia_codec_client {
+ struct lia_client_handler handler;
+ struct camu_decoder *dec;
+};
+
+struct lia_server_handler *lia_codec_server_create(void);
+struct lia_client_handler *lia_codec_client_create(void);
diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c
new file mode 100644
index 0000000..050cc6f
--- /dev/null
+++ b/src/liana/handlers/codec_client.c
@@ -0,0 +1,116 @@
+#include "../../codec/codec.h"
+#include "../../codec/ffmpeg/decoder.h"
+#include "../../codec/ffmpeg/packet_ext.h"
+#include "../../codec/stb_image/decoder.h"
+#include "../../codec/spng/decoder.h"
+#include "../../codec/wuffs/decoder.h"
+
+#include "../vcr.h"
+
+#include "codec.h"
+
+static void data_callback(void *userdata, struct camu_codec_frame *frame)
+{
+ struct lia_codec_client *codec = (struct lia_codec_client *)userdata;
+ codec->handler.callback(codec->handler.userdata, LIANA_CLIENT_DATA, codec->handler.stream, frame);
+}
+
+static bool codec_client_init(struct lia_client_handler *handler, struct camu_renderer *renderer,
+ struct camu_codec_stream *stream)
+{
+ struct lia_codec_client *codec = (struct lia_codec_client *)handler;
+ codec->dec = camu_ff_decoder_create();
+ //codec->dec = camu_stbi_decoder_create();
+ //codec->dec = camu_spng_decoder_create();
+ //codec->dec = camu_wuffs_decoder_create();
+ codec->handler.stream = stream;
+ if (!codec->dec->init(codec->dec, renderer, stream, data_callback, codec)) {
+ return false;
+ }
+ return true;
+}
+
+#ifdef CAMU_HAVE_FFMPEG
+static bool push_av_packet(struct lia_codec_client *codec, AVPacket *pkt)
+{
+ struct camu_codec_packet packet;
+ packet.av.pkt = pkt;
+ s32 ret = codec->dec->push(codec->dec, &packet);
+ av_packet_unref(pkt);
+ av_packet_free(&pkt);
+ return ret == CAMU_OK;
+}
+#endif
+
+static bool push_packet(struct lia_codec_client *codec, struct aki_buffer *buffer)
+{
+ struct camu_codec_packet packet;
+ packet.buffer = buffer;
+ s32 ret = codec->dec->push(codec->dec, &packet);
+ return ret == CAMU_OK;
+}
+
+static bool codec_client_handle_packet(struct lia_client_handler *handler, struct aki_packet *packet)
+{
+ struct lia_codec_client *codec = (struct lia_codec_client *)handler;
+ if (!packet) {
+ struct lia_codec_client *codec = (struct lia_codec_client *)handler;
+ s32 ret = codec->dec->push(codec->dec, NULL);
+ // Flush returns success.
+ ret = codec->dec->process(codec->dec);
+ // process() could still error.
+ codec->handler.callback(codec->handler.userdata, LIANA_CLIENT_EOF, codec->handler.stream, NULL);
+ return ret == CAMU_ERR_EOF;
+ }
+ bool success = false;
+ u8 type = aki_packet_read_u8(packet);
+ switch (type) {
+ case CAMU_NORMAL: {
+ struct aki_buffer buffer;
+ aki_packet_read_buffer(packet, &buffer);
+ success = push_packet(codec, &buffer);
+ break;
+ }
+#ifdef CAMU_HAVE_FFMPEG
+ case CAMU_FFMPEG_COMPAT: {
+ success = push_av_packet(codec, aki_packet_read_av_packet(packet));
+ break;
+ }
+#endif
+ }
+ // Forcing in EOF on errors is not necessary but should be a better experience client-side.
+ if (!success) {
+ codec->handler.callback(codec->handler.userdata, LIANA_CLIENT_EOF, codec->handler.stream, NULL);
+ return false;
+ }
+ s32 ret = codec->dec->process(codec->dec);
+ if (!(ret == CAMU_ERR_AGAIN || ret == CAMU_ERR_EOF)) {
+ codec->handler.callback(codec->handler.userdata, LIANA_CLIENT_EOF, codec->handler.stream, NULL);
+ return false;
+ }
+ return true;
+}
+
+static void codec_client_flush(struct lia_client_handler *handler)
+{
+ struct lia_codec_client *codec = (struct lia_codec_client *)handler;
+ codec->dec->flush(codec->dec);
+}
+
+static void codec_client_free(struct lia_client_handler **handler)
+{
+ struct lia_codec_client *codec = (struct lia_codec_client *)*handler;
+ codec->dec->free(&codec->dec);
+ al_free(codec);
+ *handler = NULL;
+}
+
+struct lia_client_handler *lia_codec_client_create(void)
+{
+ struct lia_codec_client *codec = al_alloc_object(struct lia_codec_client);
+ codec->handler.init = codec_client_init;
+ codec->handler.handle_packet = codec_client_handle_packet;
+ codec->handler.flush = codec_client_flush;
+ codec->handler.free = codec_client_free;
+ return (struct lia_client_handler *)codec;
+}
diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c
new file mode 100644
index 0000000..07fafdf
--- /dev/null
+++ b/src/liana/handlers/codec_server.c
@@ -0,0 +1,143 @@
+#include "../../codec/codec.h"
+#include "../../codec/ffmpeg/demuxer.h"
+#include "../../codec/ffmpeg/packet_ext.h"
+#include "../../codec/stb_image/demuxer.h"
+#include "../../codec/spng/demuxer.h"
+#include "../../codec/wuffs/demuxer.h"
+
+#include "../handler.h"
+
+#include "codec.h"
+
+static bool codec_server_init(struct lia_server_handler *handler, struct cch_handle *handle)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ codec->demux = camu_ff_demuxer_create();
+ //codec->demux = camu_stbi_demuxer_create();
+ //codec->demux = camu_spng_demuxer_create();
+ //codec->demux = camu_wuffs_demuxer_create();
+ if (!codec->demux->init(codec->demux, handle)) {
+ return false;
+ }
+ switch (codec->demux->mode) {
+ case CAMU_NORMAL:
+ break;
+#ifdef CAMU_HAVE_FFMPEG
+ case CAMU_FFMPEG_COMPAT:
+ codec->packet.av.pkt = av_packet_alloc();
+ break;
+#endif
+ }
+ return true;
+}
+
+static void codec_server_write_info(struct lia_server_handler *handler, struct aki_packet *packet)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ u64 duration = codec->demux->get_duration(codec->demux);
+ aki_packet_write_u64(packet, duration);
+ aki_packet_write_u32(packet, codec->demux->streams.size);
+ struct camu_codec_stream *stream;
+ al_array_foreach_ptr(codec->demux->streams, i, stream) {
+ aki_packet_write_u8(packet, stream->mode);
+ switch (stream->mode) {
+ case CAMU_NORMAL:
+ aki_packet_write_u8(packet, stream->type);
+ aki_packet_write_s32(packet, stream->video.width);
+ aki_packet_write_s32(packet, stream->video.height);
+ aki_packet_write_s32(packet, stream->video.format);
+ break;
+#ifdef CAMU_HAVE_FFMPEG
+ case CAMU_FFMPEG_COMPAT:
+ aki_packet_write_av_codec_id(packet, stream->av.stream->codecpar->codec_id);
+ aki_packet_write_av_stream(packet, stream->av.stream);
+ break;
+#endif
+ }
+ }
+}
+
+static void codec_server_subscribe(struct lia_server_handler *handler, s32 mask)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ codec->demux->subscribed = mask;
+}
+
+static u64 codec_server_get_duration(struct lia_server_handler *handler)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ return codec->demux->get_duration(codec->demux);
+}
+
+static bool codec_server_seek(struct lia_server_handler *handler, u64 pos)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ return codec->demux->seek(codec->demux, pos);
+}
+
+static void codec_server_step(struct lia_server_handler *handler)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ codec->handler.status = codec->demux->get_packet(codec->demux, &codec->packet);
+}
+
+static void codec_server_write_packet(struct lia_server_handler *handler, struct aki_packet *packet)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)handler;
+ if (codec->handler.status == CAMU_OK) {
+ aki_packet_write_u8(packet, LIANA_PACKET_DATA);
+ switch (codec->packet.mode) {
+ case CAMU_NORMAL: {
+ aki_packet_write_s32(packet, 0);
+ aki_packet_write_u8(packet, codec->packet.mode);
+ aki_packet_write_buffer(packet, codec->packet.buffer);
+ break;
+ }
+#ifdef CAMU_HAVE_FFMPEG
+ case CAMU_FFMPEG_COMPAT: {
+ AVPacket *pkt = codec->packet.av.pkt;
+ aki_packet_write_s32(packet, pkt->stream_index);
+ aki_packet_write_u8(packet, codec->packet.mode);
+ aki_packet_write_av_packet(packet, pkt);
+ av_packet_unref(pkt);
+ break;
+ }
+#endif
+ }
+ } else if (codec->handler.status == CAMU_ERR_EOF) {
+ aki_packet_write_u8(packet, LIANA_PACKET_EOF);
+ } else {
+ aki_packet_write_u8(packet, LIANA_PACKET_ERROR);
+ }
+}
+
+static void codec_server_free(struct lia_server_handler **handler)
+{
+ struct lia_codec_server *codec = (struct lia_codec_server *)*handler;
+ switch (codec->demux->mode) {
+ case CAMU_NORMAL:
+ break;
+#ifdef CAMU_HAVE_FFMPEG
+ case CAMU_FFMPEG_COMPAT:
+ av_packet_free(&codec->packet.av.pkt);
+ break;
+#endif
+ }
+ codec->demux->free(&codec->demux);
+ al_free(codec);
+ *handler = NULL;
+}
+
+struct lia_server_handler *lia_codec_server_create(void)
+{
+ struct lia_codec_server *codec = al_alloc_object(struct lia_codec_server);
+ codec->handler.init = codec_server_init;
+ codec->handler.write_info = codec_server_write_info;
+ codec->handler.subscribe = codec_server_subscribe;
+ codec->handler.get_duration = codec_server_get_duration;
+ codec->handler.seek = codec_server_seek;
+ codec->handler.step = codec_server_step;
+ codec->handler.write_packet = codec_server_write_packet;
+ codec->handler.free = codec_server_free;
+ return (struct lia_server_handler *)codec;
+}
diff --git a/src/liana/handlers/dvd.h b/src/liana/handlers/dvd.h
new file mode 100644
index 0000000..788c30e
--- /dev/null
+++ b/src/liana/handlers/dvd.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "../handler.h"
+
+struct lia_dvd_server {
+ struct lia_server_handler handler;
+};
+
+struct lia_dvd_client {
+ struct lia_client_handler handler;
+};
+
+struct lia_server_handler *lia_dvd_server_create(void);
+struct lia_client_handler *lia_dvd_client_create(void);
diff --git a/src/liana/handlers/dvd_server.c b/src/liana/handlers/dvd_server.c
new file mode 100644
index 0000000..a487de4
--- /dev/null
+++ b/src/liana/handlers/dvd_server.c
@@ -0,0 +1,21 @@
+#include "dvd.h"
+
+static bool dvd_server_init(struct lia_server_handler *handler, struct cch_handle *handle)
+{
+ struct lia_dvd_server *dvd = (struct lia_dvd_server *)handler;
+ return true;
+}
+
+struct lia_server_handler *lia_dvd_server_create(void)
+{
+ struct lia_dvd_server *dvd = al_alloc_object(struct lia_dvd_server);
+ dvd->handler.init = dvd_server_init;
+// dvd->handler.write_info = dvd_server_write_info;
+// dvd->handler.subscribe = dvd_server_subscribe;
+// dvd->handler.get_duration = dvd_server_get_duration;
+// dvd->handler.seek = dvd_server_seek;
+// dvd->handler.step = dvd_server_step;
+// dvd->handler.write_packet = dvd_server_write_packet;
+// dvd->handler.free = dvd_server_free;
+ return (struct lia_server_handler *)dvd;
+}