diff options
Diffstat (limited to 'src/shrub/handlers')
| -rw-r--r-- | src/shrub/handlers/cdio.h | 17 | ||||
| -rw-r--r-- | src/shrub/handlers/cdio_server.c | 21 | ||||
| -rw-r--r-- | src/shrub/handlers/codec.h | 20 | ||||
| -rw-r--r-- | src/shrub/handlers/codec_client.c | 102 | ||||
| -rw-r--r-- | src/shrub/handlers/codec_server.c | 140 | ||||
| -rw-r--r-- | src/shrub/handlers/dvd.h | 14 | ||||
| -rw-r--r-- | src/shrub/handlers/dvd_server.c | 21 |
7 files changed, 335 insertions, 0 deletions
diff --git a/src/shrub/handlers/cdio.h b/src/shrub/handlers/cdio.h new file mode 100644 index 0000000..0f614af --- /dev/null +++ b/src/shrub/handlers/cdio.h @@ -0,0 +1,17 @@ +#pragma once + +#include <cdio/paranoia/cdda.h> +#include <cdio/cd_types.h> + +#include "../handler.h" + +struct bmu_cdio_server { + struct bmu_server_handler handler; +}; + +struct bmu_cdio_client { + struct bmu_client_handler handler; +}; + +struct bmu_server_handler *bmu_cdio_server_create(void); +struct bmu_client_handler *bmu_cdio_client_create(void); diff --git a/src/shrub/handlers/cdio_server.c b/src/shrub/handlers/cdio_server.c new file mode 100644 index 0000000..151b94f --- /dev/null +++ b/src/shrub/handlers/cdio_server.c @@ -0,0 +1,21 @@ +#include "cdio.h" + +static bool cdio_server_init(struct bmu_server_handler *handler, struct cch_handle *handle, + struct aki_packet_pool *pool) +{ + struct bmu_cdio_server *cdio = (struct bmu_cdio_server *)handler; + return true; +} + +struct bmu_server_handler *bmu_cdio_server_create(void) +{ + struct bmu_cdio_server *cdio = al_alloc_object(struct bmu_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.free = cdio_server_free; + return (struct bmu_server_handler *)cdio; +} diff --git a/src/shrub/handlers/codec.h b/src/shrub/handlers/codec.h new file mode 100644 index 0000000..f17b17d --- /dev/null +++ b/src/shrub/handlers/codec.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../handler.h" + +#include "../../codec/codec.h" + +struct shrb_codec_server { + struct shrb_server_handler handler; + struct camu_demuxer *demux; + struct camu_packet packet; + struct aki_packet_pool *pool; +}; + +struct shrb_codec_client { + struct shrb_client_handler handler; + struct camu_decoder *dec; +}; + +struct shrb_server_handler *shrb_codec_server_create(void); +struct shrb_client_handler *shrb_codec_client_create(void); diff --git a/src/shrub/handlers/codec_client.c b/src/shrub/handlers/codec_client.c new file mode 100644 index 0000000..f55a740 --- /dev/null +++ b/src/shrub/handlers/codec_client.c @@ -0,0 +1,102 @@ +#include "../../codec/codec.h" +#include "../../codec/ffmpeg/decoder.h" +#include "../../codec/ffmpeg/packet_ext.h" + +#include "../vcr.h" + +#include "codec.h" + +static void data_callback(void *userdata, struct camu_frame *frame) +{ + struct shrb_codec_client *codec = (struct shrb_codec_client *)userdata; + codec->handler.callback(codec->handler.userdata, SHRUB_CLIENT_DATA, codec->handler.stream, frame); +} + +static bool codec_client_init(struct shrb_client_handler *handler, struct camu_renderer *renderer, + struct shrb_vcr_stream *stream) +{ + struct shrb_codec_client *codec = (struct shrb_codec_client *)handler; + codec->dec = camu_ff_decoder_create(); + codec->handler.stream = stream; + if (!codec->dec->init(codec->dec, renderer, &stream->stream)) { + return false; + } + codec->dec->stream = &stream->stream; + codec->handler.callback(codec->handler.userdata, SHRUB_CLIENT_CONFIGURE, codec->handler.stream, NULL); + codec->dec->set_callback(codec->dec, data_callback, codec); + return true; +} + +#ifdef CAMU_HAVE_FFMPEG +static void push_av_packet(struct shrb_codec_client *codec, AVPacket *pkt) +{ + struct camu_packet packet; + packet.av.pkt = pkt; + s32 ret = codec->dec->push(codec->dec, &packet); + av_packet_unref(pkt); + av_packet_free(&pkt); + al_assert(ret == CAMU_OK); +} +#endif + +static void push_packet(struct shrb_codec_client *codec, struct aki_buffer *buffer) +{ + struct camu_packet packet; + packet.buffer = buffer; + s32 ret = codec->dec->push(codec->dec, &packet); + al_assert(ret == CAMU_OK); +} + +static void codec_client_handle_packet(struct shrb_client_handler *handler, struct aki_packet *packet) +{ + struct shrb_codec_client *codec = (struct shrb_codec_client *)handler; + if (!packet) { + struct shrb_codec_client *codec = (struct shrb_codec_client *)handler; + s32 ret = codec->dec->push(codec->dec, NULL); + // Flush returns success. + ret = codec->dec->process(codec->dec); + al_assert(ret == CAMU_ERR_EOF); + codec->handler.callback(codec->handler.userdata, SHRUB_CLIENT_EOF, codec->handler.stream, NULL); + return; + } + switch (aki_packet_read_u8(packet)) { + case CAMU_NORMAL: { + struct aki_buffer buffer; + aki_packet_read_buffer(packet, &buffer); + push_packet(codec, &buffer); + break; + } +#ifdef CAMU_HAVE_FFMPEG + case CAMU_FFMPEG_COMPAT: { + push_av_packet(codec, aki_packet_read_av_packet(packet)); + break; + } +#endif + } + s32 ret = codec->dec->process(codec->dec); + al_assert(ret == CAMU_ERR_AGAIN || ret == CAMU_ERR_EOF); +} + +static void codec_client_flush(struct shrb_client_handler *handler) +{ + struct shrb_codec_client *codec = (struct shrb_codec_client *)handler; + codec->dec->flush(codec->dec); +} + +static void codec_client_free(struct shrb_client_handler **handler) +{ + struct shrb_codec_client *codec = (struct shrb_codec_client *)*handler; + codec->dec->free(&codec->dec); + al_free(codec); + *handler = NULL; +} + +struct shrb_client_handler *shrb_codec_client_create(void) +{ + struct shrb_codec_client *codec = al_alloc_object(struct shrb_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 shrb_client_handler *)codec; +} diff --git a/src/shrub/handlers/codec_server.c b/src/shrub/handlers/codec_server.c new file mode 100644 index 0000000..cab615a --- /dev/null +++ b/src/shrub/handlers/codec_server.c @@ -0,0 +1,140 @@ +#include "../../codec/codec.h" +#include "../../codec/ffmpeg/demuxer.h" +#include "../../codec/ffmpeg/packet_ext.h" + +#include "../handler.h" + +#include "codec.h" + +static bool codec_server_init(struct shrb_server_handler *handler, struct cch_handle *handle, + struct aki_packet_pool *pool) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)handler; + codec->demux = camu_ff_demuxer_create(); + if (!codec->demux->init(codec->demux, handle)) { + return false; + } + switch (codec->demux->type) { + case CAMU_NORMAL: + break; +#ifdef CAMU_HAVE_FFMPEG + case CAMU_FFMPEG_COMPAT: + codec->packet.av.pkt = av_packet_alloc(); + break; +#endif + } + codec->pool = pool; + return true; +} + +static void codec_server_write_info(struct shrb_server_handler *handler, struct aki_packet *packet) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)handler; + aki_packet_write_u64(packet, codec->demux->get_duration(codec->demux)); + aki_packet_write_u32(packet, codec->demux->streams.size); + struct camu_stream *stream; + al_array_foreach_ptr(codec->demux->streams, i, stream) { + aki_packet_write_u8(packet, stream->type); + switch (stream->type) { + case CAMU_NORMAL: + aki_packet_write_s32(packet, stream->video.width); + aki_packet_write_s32(packet, stream->video.height); + 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 shrb_server_handler *handler, s32 index, bool subscribe) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)handler; + if (subscribe) { + al_array_push(codec->demux->subscribed, index); + } +} + +static u64 codec_server_get_duration(struct shrb_server_handler *handler) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)handler; + return codec->demux->get_duration(codec->demux); +} + +static bool codec_server_seek(struct shrb_server_handler *handler, u64 pos) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)handler; + return codec->demux->seek(codec->demux, pos); +} + +static bool codec_server_step(struct shrb_server_handler *handler) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)handler; + struct aki_packet *packet = aki_packet_pool_get(codec->pool); + if (!packet) return false; + s32 ret = codec->demux->get_packet(codec->demux, &codec->packet); + if (ret == CAMU_OK) { + aki_packet_write_u8(packet, 0); + switch (codec->packet.type) { + case CAMU_NORMAL: { + aki_packet_write_s32(packet, SHRUB_PACKET_DATA); + aki_packet_write_u8(packet, codec->packet.type); + 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.type); + aki_packet_write_av_packet(packet, pkt); + av_packet_unref(pkt); + break; + } +#endif + } + aki_packet_pool_submit(codec->pool, packet); + } else if (ret == CAMU_ERR_EOF) { + aki_packet_write_u8(packet, SHRUB_PACKET_EOF); + aki_packet_pool_submit(codec->pool, packet); + return false; + } else { + aki_packet_write_u8(packet, SHRUB_PACKET_ERROR); + aki_packet_pool_submit(codec->pool, packet); + return false; + } + return true; +} + +static void codec_server_free(struct shrb_server_handler **handler) +{ + struct shrb_codec_server *codec = (struct shrb_codec_server *)*handler; + switch (codec->demux->type) { + 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 shrb_server_handler *shrb_codec_server_create(void) +{ + struct shrb_codec_server *codec = al_alloc_object(struct shrb_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.free = codec_server_free; + return (struct shrb_server_handler *)codec; +} diff --git a/src/shrub/handlers/dvd.h b/src/shrub/handlers/dvd.h new file mode 100644 index 0000000..db9bfe9 --- /dev/null +++ b/src/shrub/handlers/dvd.h @@ -0,0 +1,14 @@ +#pragma once + +#include "../handler.h" + +struct bmu_dvd_server { + struct bmu_server_handler handler; +}; + +struct bmu_dvd_client { + struct bmu_client_handler handler; +}; + +struct bmu_server_handler *bmu_dvd_server_create(void); +struct bmu_client_handler *bmu_dvd_client_create(void); diff --git a/src/shrub/handlers/dvd_server.c b/src/shrub/handlers/dvd_server.c new file mode 100644 index 0000000..ea3a9d9 --- /dev/null +++ b/src/shrub/handlers/dvd_server.c @@ -0,0 +1,21 @@ +#include "dvd.h" + +static bool dvd_server_init(struct bmu_server_handler *handler, struct cch_handle *handle, + struct aki_packet_pool *pool) +{ + struct bmu_dvd_server *dvd = (struct bmu_dvd_server *)handler; + return true; +} + +struct bmu_server_handler *bmu_dvd_server_create(void) +{ + struct bmu_dvd_server *dvd = al_alloc_object(struct bmu_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.free = dvd_server_free; + return (struct bmu_server_handler *)dvd; +} |