From 60b4ebfbf3be78dba9dc7c65ab2bdaa0b218c0c2 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Mon, 21 Oct 2024 19:22:50 -0400 Subject: Everything before initial synced list Signed-off-by: Andrew Opalach --- src/liana/handlers/cdio.h | 18 +++++ src/liana/handlers/cdio_client.c | 49 +++++++++++++ src/liana/handlers/cdio_server.c | 106 ++++++++++++++++++++++++++++ src/liana/handlers/codec.h | 19 +++++ src/liana/handlers/codec_client.c | 116 +++++++++++++++++++++++++++++++ src/liana/handlers/codec_server.c | 143 ++++++++++++++++++++++++++++++++++++++ src/liana/handlers/dvd.h | 14 ++++ src/liana/handlers/dvd_server.c | 21 ++++++ 8 files changed, 486 insertions(+) create mode 100644 src/liana/handlers/cdio.h create mode 100644 src/liana/handlers/cdio_client.c create mode 100644 src/liana/handlers/cdio_server.c create mode 100644 src/liana/handlers/codec.h create mode 100644 src/liana/handlers/codec_client.c create mode 100644 src/liana/handlers/codec_server.c create mode 100644 src/liana/handlers/dvd.h create mode 100644 src/liana/handlers/dvd_server.c (limited to 'src/liana/handlers') 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 +#include + +#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; +} -- cgit v1.2.3-101-g0448