summaryrefslogtreecommitdiff
path: root/src/bimu
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-04-09 11:24:01 -0400
committerAndrew Opalach <andrew@akon.city> 2024-04-09 11:24:01 -0400
commit02f3d3565602146bbbfce85b2719246f24036cb9 (patch)
treec6588ffe297b777e36260effa4fa42b958ca6ba3 /src/bimu
parentbbf3314165182e402ff25acccddc004a87f81ef0 (diff)
downloadcamu-02f3d3565602146bbbfce85b2719246f24036cb9.tar.gz
camu-02f3d3565602146bbbfce85b2719246f24036cb9.tar.bz2
camu-02f3d3565602146bbbfce85b2719246f24036cb9.zip
Massive restructure and many changes
- The server-side list concept is still a wip Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/bimu')
-rw-r--r--src/bimu/client.c246
-rw-r--r--src/bimu/client.h31
-rw-r--r--src/bimu/common.h23
-rw-r--r--src/bimu/handler.h52
-rw-r--r--src/bimu/handlers/cdio.h17
-rw-r--r--src/bimu/handlers/cdio_server.c21
-rw-r--r--src/bimu/handlers/codec.h20
-rw-r--r--src/bimu/handlers/codec_client.c104
-rw-r--r--src/bimu/handlers/codec_server.c140
-rw-r--r--src/bimu/handlers/dvd.h14
-rw-r--r--src/bimu/handlers/dvd_server.c21
-rw-r--r--src/bimu/local.c281
-rw-r--r--src/bimu/local.h52
-rw-r--r--src/bimu/meson.build29
-rw-r--r--src/bimu/server.c356
-rw-r--r--src/bimu/server.h59
-rw-r--r--src/bimu/vcr.c173
-rw-r--r--src/bimu/vcr.h45
18 files changed, 0 insertions, 1684 deletions
diff --git a/src/bimu/client.c b/src/bimu/client.c
deleted file mode 100644
index 03910ee..0000000
--- a/src/bimu/client.c
+++ /dev/null
@@ -1,246 +0,0 @@
-#include <al/log.h>
-
-#include "../codec/libav/packet_ext.h"
-
-#include "handlers/codec.h"
-
-#include "client.h"
-#include "common.h"
-
-static void data_connection_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_client *client = (struct bmu_client *)userdata;
- (void)stream;
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONNECTION_DATA);
- aki_packet_write_u16(packet, client->connection_id);
- aki_packet_write_u16(packet, client->node_id);
- aki_packet_write_u64(packet, client->seek_pos);
- aki_packet_stream_send_packet(&client->data, packet);
-}
-
-static void send_reconnect_packet(struct bmu_client *client)
-{
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_RECONNECT);
- aki_packet_write_u32(packet, client->level);
- aki_packet_stream_send_packet(&client->control, packet);
-}
-
-static void cleanup_connection_internal(struct bmu_client *client)
-{
- client->callback(client->userdata, BIMU_CLIENT_CLOSED, NULL, NULL);
-}
-
-static void data_connection_closed_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_client *client = (struct bmu_client *)userdata;
- (void)stream;
- if (client->closed) {
- if (!client->control.connected) cleanup_connection_internal(client);
- return;
- }
- aki_packet_stream_free(&client->data);
- client->callback(client->userdata, BIMU_CLIENT_REMOVE_BUFFERS, NULL, NULL);
- bmu_vcr_flush(&client->vcr);
- send_reconnect_packet(client);
-}
-
-static void data_packet_callback(void *userdata, struct aki_packet_stream *stream,
- struct aki_packet *packet)
-{
- struct bmu_client *client = (struct bmu_client *)userdata;
- (void)stream;
- bmu_vcr_push_packet(&client->vcr, packet);
-}
-
-static void packet_sent_callback(void *userdata, struct aki_packet *packet)
-{
- (void)userdata;
- aki_packet_free(packet);
-}
-
-void connect_data(struct bmu_client *client)
-{
- aki_packet_stream_init(&client->data, AKI_SOCKET_TCP, data_connection_callback,
- data_connection_closed_callback, data_packet_callback, packet_sent_callback, client);
- aki_packet_stream_connect(&client->data, client->loop, &client->addr, client->port);
-}
-
-static void control_connection_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_client *client = (struct bmu_client *)userdata;
- (void)stream;
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONNECTION_CONTROL);
- aki_packet_write_u16(packet, 0);
- aki_packet_write_u16(packet, client->node_id);
- aki_packet_stream_send_packet(&client->control, packet);
-}
-
-static void control_connection_closed_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_client *client = (struct bmu_client *)userdata;
- (void)stream;
- if (client->closed) {
- if (!client->data.connected) cleanup_connection_internal(client);
- return;
- }
- aki_packet_stream_free(&client->control);
- // TODO: Reconnect.
-}
-
-static void parse_info_packet(struct bmu_client *client, struct aki_packet *packet)
-{
- client->duration = aki_packet_read_u64(packet);
- u32 count = aki_packet_read_u32(packet);
- for (u32 i = 0; i < count; i++) {
- struct bmu_vcr_stream *stream = al_alloc_object(struct bmu_vcr_stream);
- stream->client = bmu_codec_client_create();
- stream->client->callback = client->callback;
- stream->client->userdata = client->userdata;
- stream->stream.type = aki_packet_read_u8(packet);
- switch (stream->stream.type) {
- case CAMU_NORMAL:
- stream->type = BIMU_STREAM_VIDEO;
- stream->index = 0;
- stream->stream.video.width = aki_packet_read_s32(packet);
- stream->stream.video.height = aki_packet_read_s32(packet);
- break;
-#ifdef HAVE_FFMPEG
- case CAMU_FFMPEG_COMPAT: {
- stream->stream.type = CAMU_FFMPEG_COMPAT;
- stream->stream.av.format_context = avformat_alloc_context();
- const AVCodec *codec = avcodec_find_decoder(aki_packet_read_av_codec_id(packet));
- stream->stream.av.stream = aki_packet_read_av_stream(stream->stream.av.format_context, codec, packet);
- stream->index = stream->stream.av.stream->index;
- switch (stream->stream.av.stream->codecpar->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- stream->type = BIMU_STREAM_AUDIO;
- al_array_push(client->subscribed, stream->index);
- break;
- case AVMEDIA_TYPE_VIDEO:
- stream->type = BIMU_STREAM_VIDEO;
- al_array_push(client->subscribed, stream->index);
- break;
- case AVMEDIA_TYPE_SUBTITLE:
- default:
- stream->type = BIMU_STREAM_UNKNOWN;
- break;
- }
- break;
- }
-#endif
- }
- if (!stream->client->init(stream->client, NULL, stream)) {
- }
- bmu_vcr_add_stream(&client->vcr, stream);
- }
-}
-
-static void send_subscribe_packet(struct bmu_client *client)
-{
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_SUBSCRIBE);
- aki_packet_write_u32(packet, client->subscribed.size);
- s32 index;
- al_array_foreach(client->subscribed, i, index) {
- aki_packet_write_s32(packet, index);
- }
- aki_packet_stream_send_packet(&client->control, packet);
-}
-
-static void parse_start_packet(struct bmu_client *client, struct aki_packet *packet)
-{
- u64 ts = aki_packet_read_u64(packet);
- u64 delay = aki_packet_read_u64(packet);
- u64 seek_pos = aki_packet_read_u64(packet);
- struct bmu_seek_req req = { .base = seek_pos, .ts = ts, .delay = delay };
- client->callback(client->userdata, BIMU_CLIENT_SET, NULL, &req);
- client->seek_pos = req.base;
-}
-
-static void control_packet_callback(void *userdata, struct aki_packet_stream *stream,
- struct aki_packet *packet)
-{
- struct bmu_client *client = (struct bmu_client *)userdata;
- (void)stream;
-
- switch (aki_packet_read_u8(packet)) {
- case BIMU_CONTROL_INFO:
- client->connection_id = aki_packet_read_u16(packet);
- parse_info_packet(client, packet);
- send_subscribe_packet(client);
- break;
- case BIMU_CONTROL_START:
- parse_start_packet(client, packet);
- connect_data(client);
- break;
- case BIMU_CONTROL_PAUSE:
- break;
- case BIMU_CONTROL_RESUME:
- break;
- case BIMU_CONTROL_SEEK:
- client->level = 0;
- client->corked = false;
- aki_packet_stream_disconnect(&client->data);
- break;
- default:
- break;
- }
-
- aki_packet_free(packet);
-}
-
-void bmu_client_connect(struct bmu_client *client, struct aki_event_loop *loop, str *addr, s32 port, u16 node_id)
-{
- client->loop = loop;
- client->node_id = node_id;
- al_str_clone(&client->addr, addr);
- client->port = port;
- client->level = 0;
- client->corked = false;
- al_array_init(client->subscribed);
- bmu_vcr_init(&client->vcr, client->loop, &client->data);
- aki_packet_stream_init(&client->control, AKI_SOCKET_TCP, control_connection_callback,
- control_connection_closed_callback, control_packet_callback, packet_sent_callback, client);
- aki_packet_stream_set_no_delay(&client->control, 1);
- aki_packet_stream_connect(&client->control, client->loop, &client->addr, client->port);
-}
-
-void bmu_client_reseek(struct bmu_client *client)
-{
- client->level++;
- al_log_debug("bimu", "Attempting re-seek at level %i.", client->level);
- client->corked = false;
- aki_packet_stream_disconnect(&client->data);
-}
-
-void bmu_client_seek(struct bmu_client *client, f64 percent)
-{
- u64 pos = client->duration * percent;
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_SEEK);
- aki_packet_write_u64(packet, pos);
- aki_packet_stream_send_packet(&client->control, packet);
-}
-
-void bmu_client_close(struct bmu_client *client)
-{
- struct bmu_vcr_stream *stream;
- al_array_foreach(client->vcr.streams, i, stream) {
- bmu_vcr_stream_close(stream);
- }
- client->closed = true;
- aki_packet_stream_disconnect(&client->control);
- aki_packet_stream_disconnect(&client->data);
-}
-
-void bmu_client_free(struct bmu_client *client)
-{
- aki_packet_stream_free(&client->control);
- aki_packet_stream_free(&client->data);
- al_str_free(&client->addr);
- al_array_free(client->subscribed);
- bmu_vcr_free(&client->vcr);
-}
diff --git a/src/bimu/client.h b/src/bimu/client.h
deleted file mode 100644
index db1f9e5..0000000
--- a/src/bimu/client.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include <al/types.h>
-#include <aki/packet_stream.h>
-
-#include "vcr.h"
-
-struct bmu_client {
- struct aki_event_loop *loop;
- u16 node_id;
- u16 connection_id;
- str addr;
- s32 port;
- struct aki_packet_stream control;
- struct aki_packet_stream data;
- bool closed;
- u32 level;
- bool corked;
- u64 duration;
- u64 seek_pos;
- array(s32) subscribed;
- struct bmu_vcr vcr;
- void (*callback)(void *, u8, struct bmu_vcr_stream *stream, void *);
- void *userdata;
-};
-
-void bmu_client_connect(struct bmu_client *client, struct aki_event_loop *loop, str *addr, s32 port, u16 node_id);
-void bmu_client_reseek(struct bmu_client *client);
-void bmu_client_seek(struct bmu_client *client, f64 percent);
-void bmu_client_close(struct bmu_client *client);
-void bmu_client_free(struct bmu_client *client);
diff --git a/src/bimu/common.h b/src/bimu/common.h
deleted file mode 100644
index 485d454..0000000
--- a/src/bimu/common.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-enum {
- BIMU_STREAM_AUDIO = 0,
- BIMU_STREAM_VIDEO,
- BIMU_STREAM_UNKNOWN,
-};
-
-enum {
- BIMU_CONNECTION_CONTROL = 0,
- BIMU_CONNECTION_DATA
-};
-
-enum {
- BIMU_CONTROL_INFO = 0,
- BIMU_CONTROL_SUBSCRIBE,
- BIMU_CONTROL_RECONNECT,
- BIMU_CONTROL_START,
- BIMU_CONTROL_TOGGLE_PAUSE,
- BIMU_CONTROL_PAUSE,
- BIMU_CONTROL_RESUME,
- BIMU_CONTROL_SEEK
-};
diff --git a/src/bimu/handler.h b/src/bimu/handler.h
deleted file mode 100644
index c6b482d..0000000
--- a/src/bimu/handler.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <aki/packet_pool.h>
-
-#include "../codec/codec.h"
-#include "../cache/handle.h"
-
-#include "vcr.h"
-
-struct bmu_server_handler {
- bool (*init)(struct bmu_server_handler *, struct cch_handle *, struct aki_packet_pool *);
- void (*write_info)(struct bmu_server_handler *, struct aki_packet *);
- void (*subscribe)(struct bmu_server_handler *, s32, bool);
- u64 (*get_duration)(struct bmu_server_handler *);
- bool (*seek)(struct bmu_server_handler *, u64);
- bool (*step)(struct bmu_server_handler *);
- void (*free)(struct bmu_server_handler **);
- void *userdata;
-};
-
-enum {
- BIMU_PACKET_DATA = 0,
- BIMU_PACKET_EOF,
- BIMU_PACKET_ERROR
-};
-
-enum {
- BIMU_CLIENT_CONFIGURE = 0,
- BIMU_CLIENT_SET,
- BIMU_CLIENT_DATA,
- BIMU_CLIENT_REMOVE_BUFFERS,
- BIMU_CLIENT_EOF,
- BIMU_CLIENT_CLOSED
-};
-
-struct bmu_seek_req {
- u64 base;
- u64 ts;
- u64 delay;
-};
-
-struct bmu_client_stream;
-struct bmu_client_handler {
- bool (*init)(struct bmu_client_handler *, struct camu_renderer *, struct bmu_vcr_stream *);
- void (*handle_data_packet)(struct bmu_client_handler *, struct aki_packet *);
- void (*handle_eof)(struct bmu_client_handler *);
- void (*flush)(struct bmu_client_handler *);
- void (*free)(struct bmu_client_handler **);
- struct bmu_vcr_stream *stream;
- void (*callback)(void *, u8, struct bmu_vcr_stream *stream, void *);
- void *userdata;
-};
diff --git a/src/bimu/handlers/cdio.h b/src/bimu/handlers/cdio.h
deleted file mode 100644
index 0f614af..0000000
--- a/src/bimu/handlers/cdio.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#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/bimu/handlers/cdio_server.c b/src/bimu/handlers/cdio_server.c
deleted file mode 100644
index 151b94f..0000000
--- a/src/bimu/handlers/cdio_server.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#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/bimu/handlers/codec.h b/src/bimu/handlers/codec.h
deleted file mode 100644
index a8031b1..0000000
--- a/src/bimu/handlers/codec.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include "../handler.h"
-
-#include "../../codec/codec.h"
-
-struct bmu_codec_server {
- struct bmu_server_handler handler;
- struct camu_demuxer *demux;
- struct camu_packet packet;
- struct aki_packet_pool *pool;
-};
-
-struct bmu_codec_client {
- struct bmu_client_handler handler;
- struct camu_decoder *dec;
-};
-
-struct bmu_server_handler *bmu_codec_server_create(void);
-struct bmu_client_handler *bmu_codec_client_create(void);
diff --git a/src/bimu/handlers/codec_client.c b/src/bimu/handlers/codec_client.c
deleted file mode 100644
index 79ef27d..0000000
--- a/src/bimu/handlers/codec_client.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include "../../codec/codec.h"
-#include "../../codec/libav/decoder.h"
-#include "../../codec/libav/packet_ext.h"
-
-#include "../../bimu/vcr.h"
-
-#include "codec.h"
-
-static void data_callback(void *userdata, struct camu_frame *frame)
-{
- struct bmu_codec_client *codec = (struct bmu_codec_client *)userdata;
- codec->handler.callback(codec->handler.userdata, BIMU_CLIENT_DATA, codec->handler.stream, frame);
-}
-
-static bool codec_client_init(struct bmu_client_handler *handler, struct camu_renderer *renderer,
- struct bmu_vcr_stream *stream)
-{
- struct bmu_codec_client *codec = (struct bmu_codec_client *)handler;
- codec->dec = camu_lav_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, BIMU_CLIENT_CONFIGURE, codec->handler.stream, NULL);
- codec->dec->set_callback(codec->dec, data_callback, codec);
- return true;
-}
-
-#ifdef HAVE_FFMPEG
-static void push_av_packet(struct bmu_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 bmu_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_data_packet(struct bmu_client_handler *handler, struct aki_packet *packet)
-{
- struct bmu_codec_client *codec = (struct bmu_codec_client *)handler;
- 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 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_handle_eof(struct bmu_client_handler *handler)
-{
- struct bmu_codec_client *codec = (struct bmu_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, BIMU_CLIENT_EOF, codec->handler.stream, NULL);
-}
-
-static void codec_client_flush(struct bmu_client_handler *handler)
-{
- struct bmu_codec_client *codec = (struct bmu_codec_client *)handler;
- codec->dec->flush(codec->dec);
-}
-
-static void codec_client_free(struct bmu_client_handler **handler)
-{
- struct bmu_codec_client *codec = (struct bmu_codec_client *)*handler;
- codec->dec->free(&codec->dec);
- al_free(codec);
- *handler = NULL;
-}
-
-struct bmu_client_handler *bmu_codec_client_create(void)
-{
- struct bmu_codec_client *codec = al_alloc_object(struct bmu_codec_client);
- codec->handler.init = codec_client_init;
- codec->handler.handle_data_packet = codec_client_handle_data_packet;
- codec->handler.handle_eof = codec_client_handle_eof;
- codec->handler.flush = codec_client_flush;
- codec->handler.free = codec_client_free;
- return (struct bmu_client_handler *)codec;
-}
diff --git a/src/bimu/handlers/codec_server.c b/src/bimu/handlers/codec_server.c
deleted file mode 100644
index a30ce68..0000000
--- a/src/bimu/handlers/codec_server.c
+++ /dev/null
@@ -1,140 +0,0 @@
-#include "../../codec/codec.h"
-#include "../../codec/libav/demuxer.h"
-#include "../../codec/libav/packet_ext.h"
-
-#include "../handler.h"
-
-#include "codec.h"
-
-static bool codec_server_init(struct bmu_server_handler *handler, struct cch_handle *handle,
- struct aki_packet_pool *pool)
-{
- struct bmu_codec_server *codec = (struct bmu_codec_server *)handler;
- codec->demux = camu_lav_demuxer_create();
- if (!codec->demux->init(codec->demux, handle)) {
- return false;
- }
- switch (codec->demux->type) {
- case CAMU_NORMAL:
- break;
-#ifdef 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 bmu_server_handler *handler, struct aki_packet *packet)
-{
- struct bmu_codec_server *codec = (struct bmu_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 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 bmu_server_handler *handler, s32 index, bool subscribe)
-{
- struct bmu_codec_server *codec = (struct bmu_codec_server *)handler;
- if (subscribe) {
- al_array_push(codec->demux->subscribed, index);
- }
-}
-
-static u64 codec_server_get_duration(struct bmu_server_handler *handler)
-{
- struct bmu_codec_server *codec = (struct bmu_codec_server *)handler;
- return codec->demux->get_duration(codec->demux);
-}
-
-static bool codec_server_seek(struct bmu_server_handler *handler, u64 pos)
-{
- struct bmu_codec_server *codec = (struct bmu_codec_server *)handler;
- return codec->demux->seek(codec->demux, pos);
-}
-
-static bool codec_server_step(struct bmu_server_handler *handler)
-{
- struct bmu_codec_server *codec = (struct bmu_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, BIMU_PACKET_DATA);
- aki_packet_write_u8(packet, codec->packet.type);
- aki_packet_write_buffer(packet, codec->packet.buffer);
- break;
- }
-#ifdef 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, BIMU_PACKET_EOF);
- aki_packet_pool_submit(codec->pool, packet);
- return false;
- } else {
- aki_packet_write_u8(packet, BIMU_PACKET_ERROR);
- aki_packet_pool_submit(codec->pool, packet);
- return false;
- }
- return true;
-}
-
-static void codec_server_free(struct bmu_server_handler **handler)
-{
- struct bmu_codec_server *codec = (struct bmu_codec_server *)*handler;
- switch (codec->demux->type) {
- case CAMU_NORMAL:
- break;
-#ifdef 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 bmu_server_handler *bmu_codec_server_create(void)
-{
- struct bmu_codec_server *codec = al_alloc_object(struct bmu_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 bmu_server_handler *)codec;
-}
diff --git a/src/bimu/handlers/dvd.h b/src/bimu/handlers/dvd.h
deleted file mode 100644
index db9bfe9..0000000
--- a/src/bimu/handlers/dvd.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#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/bimu/handlers/dvd_server.c b/src/bimu/handlers/dvd_server.c
deleted file mode 100644
index ea3a9d9..0000000
--- a/src/bimu/handlers/dvd_server.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#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;
-}
diff --git a/src/bimu/local.c b/src/bimu/local.c
deleted file mode 100644
index 76824ed..0000000
--- a/src/bimu/local.c
+++ /dev/null
@@ -1,281 +0,0 @@
-#include "../codec/libav/packet_ext.h"
-
-#include "local.h"
-
-#define PACKETS 1400
-
-static struct bmu_local_stream *stream_at_index(struct bmu_local *runner, s32 index)
-{
- struct bmu_local_stream *stream = NULL;
- al_array_foreach(runner->streams, i, stream) {
- if (stream->s.index == index) {
- return stream;
- }
- }
- return NULL;
-}
-
-static aki_thread_result AKI_THREADCALL stream_thread(void *userdata)
-{
- struct bmu_local_stream *stream = (struct bmu_local_stream *)userdata;
- do {
- if (!aki_packet_cache_wait(&stream->cache)) break;
- struct aki_packet *packet = aki_packet_cache_pop(&stream->cache);
- if (!packet) break;
- aki_mutex_lock(&stream->mutex);
- if (al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED) == BIMU_LOCAL_STOPPED) {
- aki_cond_wait(&stream->cond, &stream->mutex);
- }
- s32 state = al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED);
- aki_mutex_unlock(&stream->mutex);
- if (state == BIMU_LOCAL_CLOSED) {
- aki_packet_pool_return(&stream->runner->pool, packet);
- break;
- }
- switch (aki_packet_read_u8(packet)) {
- case 0:
- stream->s.client->handle_data_packet(stream->s.client, packet);
- break;
- case 1:
- stream->s.client->handle_eof(stream->s.client);
- break;
- }
- aki_packet_pool_return(&stream->runner->pool, packet);
- } while (1);
- return 0;
-}
-
-static u8 packet_pool_callback(void *userdata, struct aki_packet *packet)
-{
- struct bmu_local *runner = (struct bmu_local *)userdata;
- if (!packet) {
- aki_event_loop_break(&runner->loop);
- return AKI_PACKET_POOL_CLOSED;
- }
- aki_packet_write_size(packet);
- u8 close = aki_packet_read_u8(packet);
- if (close) return AKI_PACKET_POOL_DISABLE;
- struct bmu_local_stream *stream = NULL;
- s32 index = aki_packet_read_s32(packet);
- if (index >= 0) {
- stream = stream_at_index(runner, index);
- if (!stream) return AKI_PACKET_POOL_RETURN;
- if (al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED) != BIMU_LOCAL_CLOSED) {
- if (aki_packet_cache_send_packet(&stream->cache, packet)) {
- return AKI_PACKET_POOL_KEEP;
- }
- }
- }
- return AKI_PACKET_POOL_RETURN;
-}
-
-bool bmu_local_init(struct bmu_local *runner, struct cch_entry *entry)
-{
- runner->entry = entry;
- runner->server = bmu_codec_server_create();
- cch_entry_get_handle(runner->entry, &runner->handle);
- aki_event_loop_init(&runner->loop);
- aki_packet_pool_init(&runner->pool, PACKETS, &runner->loop, packet_pool_callback, runner);
- if (!runner->server->init(runner->server, &runner->handle, &runner->pool, NULL)) {
- return false;
- }
- al_array_init(runner->streams);
- al_atomic_bool_store(&runner->closed, false, AL_ATOMIC_RELAXED);
- return true;
-}
-
-bool bmu_local_prepare_clients(struct bmu_local *runner, struct camu_renderer *renderer)
-{
- struct aki_packet *packet = aki_packet_create();
- runner->server->write_info(runner->server, packet);
- aki_packet_write_size(packet);
- u32 count = aki_packet_read_u32(packet);
- for (u32 i = 0; i < count; i++) {
- struct bmu_local_stream *local = al_alloc_object(struct bmu_local_stream);
- struct bmu_client_stream *stream = &local->s;
- local->runner = runner;
- local->s.client = bmu_codec_client_create();
- local->s.client->callback = runner->callback;
- local->s.client->userdata = runner->userdata;
- aki_cond_init(&local->cond);
- aki_mutex_init(&local->mutex);
- aki_packet_cache_init(&local->cache, PACKETS);
- al_atomic_s32_store(&local->state, BIMU_LOCAL_RUNNING, AL_ATOMIC_RELAXED);
- stream->stream.type = aki_packet_read_u8(packet);
- switch (stream->stream.type) {
- case CAMU_NORMAL:
- stream->index = 0;
- stream->type = BIMU_STREAM_VIDEO;
- stream->stream.video.width = aki_packet_read_s32(packet);
- stream->stream.video.height = aki_packet_read_s32(packet);
- break;
-#ifdef HAVE_FFMPEG
- case CAMU_FFMPEG_COMPAT: {
- stream->stream.type = CAMU_FFMPEG_COMPAT;
- stream->stream.av.format_context = avformat_alloc_context();
- const AVCodec *codec = avcodec_find_decoder(aki_packet_read_av_codec_id(packet));
- stream->stream.av.stream = aki_packet_read_av_stream(stream->stream.av.format_context, codec, packet);
- stream->index = stream->stream.av.stream->index;
- switch (stream->stream.av.stream->codecpar->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- stream->type = BIMU_STREAM_AUDIO;
- break;
- case AVMEDIA_TYPE_VIDEO:
- stream->type = BIMU_STREAM_VIDEO;
- break;
- case AVMEDIA_TYPE_SUBTITLE:
- default:
- stream->type = BIMU_STREAM_UNKNOWN;
- break;
- }
- }
-#endif
- }
- if (!local->s.client->init(local->s.client, renderer, stream)) {
- aki_packet_free(packet);
- return false;
- }
- aki_thread_create(&local->thread, stream_thread, stream);
- al_array_push(runner->streams, local);
- }
- aki_packet_free(packet);
- return true;
-}
-
-void bmu_local_stream_stop(struct bmu_local_stream *stream)
-{
- aki_mutex_lock(&stream->mutex);
- if (al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED) == BIMU_LOCAL_RUNNING) {
- al_atomic_s32_store(&stream->state, BIMU_LOCAL_STOPPED, AL_ATOMIC_RELAXED);
- }
- aki_mutex_unlock(&stream->mutex);
-}
-
-void bmu_local_stream_continue(struct bmu_local_stream *stream)
-{
- aki_mutex_lock(&stream->mutex);
- al_atomic_s32_store(&stream->state, BIMU_LOCAL_RUNNING, AL_ATOMIC_RELAXED);
- if (aki_cond_is_waiting(&stream->cond)) {
- aki_cond_signal(&stream->cond);
- }
- aki_mutex_unlock(&stream->mutex);
-}
-
-void bmu_local_stream_close(struct bmu_local_stream *stream)
-{
- aki_mutex_lock(&stream->mutex);
- u8 state = al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED);
- if (state == BIMU_LOCAL_CLOSED) {
- aki_mutex_unlock(&stream->mutex);
- return;
- }
- al_atomic_s32_store(&stream->state, BIMU_LOCAL_CLOSED, AL_ATOMIC_RELAXED);
- aki_packet_cache_disable(&stream->cache);
- if (aki_cond_is_waiting(&stream->cond)) {
- aki_cond_signal(&stream->cond);
- }
- aki_mutex_unlock(&stream->mutex);
- aki_thread_join(&stream->thread);
-}
-
-static aki_thread_result AKI_THREADCALL decode_thread(void *userdata)
-{
- struct bmu_local *runner = (struct bmu_local *)userdata;
- while (!al_atomic_bool_load(&runner->closed, AL_ATOMIC_RELAXED)
- && runner->server->step(runner->server)) {}
- return 0;
-}
-
-static aki_thread_result AKI_THREADCALL event_loop_thread(void *userdata)
-{
- struct bmu_local *runner = (struct bmu_local *)userdata;
- aki_event_loop_run(&runner->loop);
- return 0;
-}
-
-void bmu_local_run(struct bmu_local *runner)
-{
- aki_thread_create(&runner->decode_thread, decode_thread, runner);
- aki_thread_create(&runner->event_loop_thread, event_loop_thread, runner);
-}
-
-f64 bmu_local_get_duration(struct bmu_local *runner)
-{
- return runner->server->get_duration(runner->server) / 1000000.0;
-}
-
-void bmu_local_seek(struct bmu_local *runner, f64 percent)
-{
- s64 pos = runner->server->get_duration(runner->server) * percent;
- f64 fpos = pos / 1000000.0;
- al_atomic_bool_store(&runner->closed, true, AL_ATOMIC_RELAXED);
- aki_packet_pool_disable(&runner->pool);
- struct bmu_local_stream *stream = NULL;
- al_array_foreach(runner->streams, i, stream) {
- bmu_local_stream_close(stream);
- struct aki_packet *packet;
- while ((packet = aki_packet_cache_pop(&stream->cache))) {
- aki_packet_pool_return(&stream->runner->pool, packet);
- }
- }
- aki_thread_join(&runner->decode_thread);
- runner->callback(runner->userdata, BIMU_CLIENT_SEEK, NULL, &fpos);
- runner->server->seek(runner->server, pos);
- al_atomic_bool_store(&runner->closed, false, AL_ATOMIC_RELAXED);
- aki_packet_pool_enable(&runner->pool);
- al_array_foreach(runner->streams, i, stream) {
- stream->s.client->flush(stream->s.client);
- al_atomic_s32_store(&stream->state, BIMU_LOCAL_RUNNING, AL_ATOMIC_RELAXED);
- aki_packet_cache_enable(&stream->cache);
- aki_thread_create(&stream->thread, stream_thread, stream);
- }
- aki_thread_create(&runner->decode_thread, decode_thread, runner);
-}
-
-void bmu_local_stop(struct bmu_local *runner)
-{
- al_atomic_bool_store(&runner->closed, true, AL_ATOMIC_RELAXED);
- cch_handle_disable(&runner->handle);
- struct bmu_local_stream *stream = NULL;
- al_array_foreach(runner->streams, i, stream) {
- bmu_local_stream_close(stream);
- }
- aki_thread_join(&runner->decode_thread);
- cch_entry_return_handle(runner->entry, &runner->handle);
- struct aki_packet *packet = aki_packet_pool_get(&runner->pool);
- if (!packet) al_assert(false);
- aki_packet_write_u8(packet, 1);
- aki_packet_pool_submit(&runner->pool, packet);
- aki_thread_join(&runner->event_loop_thread);
- runner->callback(runner->userdata, BIMU_CLIENT_CLOSED, NULL, NULL);
-}
-
-void bmu_local_close(struct bmu_local *runner)
-{
- struct bmu_local_stream *stream = NULL;
- al_array_foreach(runner->streams, i, stream) {
- stream->s.client->free(&stream->s.client);
- switch (stream->s.stream.type) {
- case CAMU_NORMAL:
- break;
-#ifdef HAVE_FFMPEG
- case CAMU_FFMPEG_COMPAT:
- avformat_free_context(stream->s.stream.av.format_context);
- break;
-#endif
- }
- struct aki_packet *packet;
- while ((packet = aki_packet_cache_pop(&stream->cache))) {
- aki_packet_pool_return(&stream->runner->pool, packet);
- }
- aki_mutex_destroy(&stream->mutex);
- aki_cond_destroy(&stream->cond);
- aki_packet_cache_free(&stream->cache);
- al_free(stream);
- al_array_remove_at_iter(runner->streams, i);
- }
- al_array_free(runner->streams);
- runner->server->free(&runner->server);
- aki_packet_pool_free(&runner->pool);
- aki_event_loop_destroy(&runner->loop);
-}
diff --git a/src/bimu/local.h b/src/bimu/local.h
deleted file mode 100644
index 10c0cc8..0000000
--- a/src/bimu/local.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <al/atomic.h>
-#include <aki/packet_pool.h>
-#include <aki/packet_cache.h>
-#include <aki/signal.h>
-
-#include "../cache/entry.h"
-
-#include "client.h"
-#include "common.h"
-
-enum {
- BIMU_LOCAL_RUNNING = 0,
- BIMU_LOCAL_STOPPED,
- BIMU_LOCAL_CLOSED
-};
-
-struct bmu_local_stream {
- struct bmu_client_stream s;
- atomic_s32 state;
- struct aki_cond cond;
- struct aki_mutex mutex;
- struct aki_packet_cache cache;
- struct aki_thread thread;
- struct bmu_local *runner;
-};
-
-struct bmu_local {
- struct cch_entry *entry;
- struct cch_handle handle;
- struct bmu_server_handler *server;
- struct aki_thread decode_thread;
- struct aki_event_loop loop;
- struct aki_packet_pool pool;
- struct aki_thread event_loop_thread;
- atomic_bool closed;
- array(struct bmu_local_stream *) streams;
- void (*callback)(void *, u8, struct bmu_client_stream *stream, void *);
- void *userdata;
-};
-
-bool bmu_local_init(struct bmu_local *runner, struct cch_entry *entry);
-bool bmu_local_prepare_clients(struct bmu_local *runner, struct camu_renderer *renderer);
-void bmu_local_stream_stop(struct bmu_local_stream *stream);
-void bmu_local_stream_continue(struct bmu_local_stream *stream);
-void bmu_local_stream_close(struct bmu_local_stream *stream);
-void bmu_local_run(struct bmu_local *runner);
-f64 bmu_local_get_duration(struct bmu_local *runner);
-void bmu_local_seek(struct bmu_local *runner, f64 percent);
-void bmu_local_stop(struct bmu_local *runner);
-void bmu_local_close(struct bmu_local *runner);
diff --git a/src/bimu/meson.build b/src/bimu/meson.build
deleted file mode 100644
index cc1ff43..0000000
--- a/src/bimu/meson.build
+++ /dev/null
@@ -1,29 +0,0 @@
-bimu_server_src = [
- 'server.c',
- 'handlers/codec_server.c'
-]
-bimu_client_src = [
- 'client.c',
- 'vcr.c',
- 'handlers/codec_client.c'
-]
-bimu_server_deps = [av_server]
-bimu_client_deps = [av_client]
-
-#libcdio_paranoia = dependency('libcdio_paranoia', required: false, allow_fallback: true)
-#libcdio_cdda = dependency('libcdio_cdda', required: false, allow_fallback: true)
-#if libcdio_paranoia.found() and libcdio_cdda.found()
-# bimu_server_src += ['handlers/cdio_server.c']
-# bimu_server_deps += [libcdio_paranoia, libcdio_cdda]
-#endif
-#
-#libdvdcss = dependency('libdvdcss', required: false, allow_fallback: true)
-#libdvdread = dependency('libdvdread', required: false, allow_fallback: true)
-#libdvdnav = dependency('libdvdnav', required: false, allow_fallback: true)
-#if libdvdcss.found() and libdvdread.found() and libdvdnav.found()
-# bimu_server_src += ['handlers/dvd_server.c']
-# bimu_server_deps += [libdvdcss]
-#endif
-
-bimu_server = declare_dependency(sources: bimu_server_src, dependencies: bimu_server_deps)
-bimu_client = declare_dependency(sources: bimu_client_src, dependencies: bimu_client_deps)
diff --git a/src/bimu/server.c b/src/bimu/server.c
deleted file mode 100644
index 6db0dd2..0000000
--- a/src/bimu/server.c
+++ /dev/null
@@ -1,356 +0,0 @@
-#include <al/random.h>
-#include <aki/common.h>
-
-#include "handlers/codec.h"
-
-#include "server.h"
-#include "common.h"
-
-static void control_connection_closed_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_node_connection *connection = (struct bmu_node_connection *)userdata;
- (void)stream;
- struct bmu_node_connection *rconnection;
- al_array_foreach(connection->node->connections, i, rconnection) {
- if (rconnection == connection) {
- al_array_remove_at_iter(connection->node->connections, i);
- break;
- }
- }
- aki_packet_stream_free(connection->control);
- connection->control = NULL;
- //cch_entry_return_handle(connection->node->entry, &connection->handle);
- //connection->handler->free(&connection->handler);
- //aki_packet_pool_free(&connection->pool);
-}
-
-static void data_connection_closed_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_node_connection *connection = (struct bmu_node_connection *)userdata;
- (void)stream;
- connection->running = 0;
- aki_packet_pool_disable(&connection->pool);
- aki_thread_join(&connection->thread);
- aki_packet_pool_enable(&connection->pool);
- aki_packet_stream_free(connection->data);
- connection->data = NULL;
-}
-
-static void default_packet_sent_callback(void *userdata, struct aki_packet *packet)
-{
- (void)userdata;
- aki_packet_free(packet);
-}
-
-static void packet_sent_callback(void *userdata, struct aki_packet *packet)
-{
- struct bmu_node_connection *connection = (struct bmu_node_connection *)userdata;
- aki_packet_pool_return(&connection->pool, packet);
-}
-
-static void data_packet_callback(void *userdata, struct aki_packet_stream *stream, struct aki_packet *packet)
-{
- (void)userdata;
- (void)stream;
- aki_packet_free(packet);
-}
-
-static u8 packet_pool_callback(void *userdata, struct aki_packet *packet)
-{
- struct bmu_node_connection *connection = (struct bmu_node_connection *)userdata;
- if (connection->data->connected) {
- aki_packet_stream_send_packet(connection->data, packet);
- return AKI_PACKET_POOL_KEEP;
- }
- return AKI_PACKET_POOL_RETURN;
-}
-
-static void send_resume_packet(struct bmu_node_connection *connection, u64 seek_pos, u64 ts)
-{
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_RESUME);
- aki_packet_write_u64(packet, seek_pos);
- aki_packet_write_u64(packet, ts);
- aki_packet_stream_send_packet(connection->control, packet);
-}
-
-static void send_pause_packet(struct bmu_node_connection *connection, u64 seek_pos)
-{
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_PAUSE);
- aki_packet_write_u64(packet, seek_pos);
- aki_packet_stream_send_packet(connection->control, packet);
-}
-
-#define DELAY 275000Lu // 275ms
-#define DELAY_GIVE 30000Lu // 30ms
-
-static void send_start_packet(struct bmu_node_connection *connection, u32 level)
-{
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_START);
- u64 ts = aki_get_timestamp();
- u64 delay = DELAY * powl(3, level);
- u64 seek_pos = connection->node->seek_pos;
- if (!(connection->node->flags & BIMU_NODE_PAUSED)) {
- if (connection->node->flags & BIMU_NODE_STARTED) {
- if ((ts - DELAY_GIVE) < (u64)connection->node->start) {
- // Current time is close enough to node start.
- ts = connection->node->start;
- } else {
- seek_pos += (ts - connection->node->start) + (delay - DELAY);
- }
- } else {
- // Must be set at level 0, this applies for seeks too.
- connection->node->start = ts;
- connection->node->flags |= BIMU_NODE_STARTED;
- }
- }
- aki_packet_write_u64(packet, ts);
- aki_packet_write_u64(packet, delay);
- aki_packet_write_u64(packet, seek_pos);
- aki_packet_stream_send_packet(connection->control, packet);
-}
-
-static void send_seek_packet(struct bmu_node *node)
-{
- struct aki_packet *packet;
- struct bmu_node_connection *connection;
- al_array_foreach(node->connections, i, connection) {
- packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_SEEK);
- aki_packet_stream_send_packet(connection->control, packet);
- }
-}
-
-static void control_packet_callback(void *userdata, struct aki_packet_stream *stream, struct aki_packet *packet)
-{
- struct bmu_node_connection *connection = (struct bmu_node_connection *)userdata;
- (void)stream;
-
- switch (aki_packet_read_u8(packet)) {
- case BIMU_CONTROL_SUBSCRIBE: {
- u32 count = aki_packet_read_u32(packet);
- for (u32 i = 0; i < count; i++) {
- connection->handler->subscribe(connection->handler, aki_packet_read_s32(packet), true);
- }
- send_start_packet(connection, 0);
- break;
- }
- case BIMU_CONTROL_RECONNECT: {
- send_start_packet(connection, aki_packet_read_u32(packet));
- break;
- }
- case BIMU_CONTROL_TOGGLE_PAUSE: {
- struct bmu_node *node = connection->node;
- u64 pos = aki_packet_read_u64(packet);
- u8 paused = connection->paused;
- if (paused == BIMU_PLAYING) {
- node->seek_pos = pos;
- node->flags |= BIMU_NODE_PAUSED;
- // Update node start?
- } else if (paused == BIMU_PAUSED_AND_RUNNING) {
- node->flags &= ~BIMU_NODE_PAUSED;
- }
- struct bmu_node_connection *rconnection;
- al_array_foreach(node->connections, i, rconnection) {
- switch (rconnection->paused) {
- case BIMU_PLAYING:
- al_assert(paused == BIMU_PLAYING || paused == BIMU_NOT_PAUSED);
- rconnection->paused = BIMU_PAUSED;
- send_pause_packet(rconnection, node->seek_pos);
- break;
- case BIMU_NOT_PAUSED:
- al_assert(paused != BIMU_PAUSED);
- rconnection->paused = BIMU_PAUSED;
- break;
- case BIMU_PAUSED:
- al_assert(paused != BIMU_NOT_PAUSED);
- rconnection->paused = BIMU_NOT_PAUSED;
- break;
- case BIMU_PAUSED_AND_RUNNING:
- al_assert(paused != BIMU_NOT_PAUSED);
- send_resume_packet(rconnection, node->seek_pos, node->start);
- rconnection->paused = BIMU_PLAYING;
- break;
- }
- }
- break;
- }
- case BIMU_CONTROL_SEEK: {
- u64 pos = aki_packet_read_u64(packet);
- connection->node->seek_pos = pos;
- connection->node->flags |= BIMU_NODE_SEEKED;
- connection->node->flags &= ~BIMU_NODE_STARTED;
- send_seek_packet(connection->node);
- break;
- }
- }
- aki_packet_free(packet);
-}
-
-static struct bmu_node *get_node_by_id(struct bmu_server *server, u16 id)
-{
- struct bmu_node *node;
- al_array_foreach(server->nodes, i, node) {
- if (node->id == id) return node;
- }
- return NULL;
-}
-
-static struct bmu_node_connection *get_connection_by_id(struct bmu_node *node, u16 id)
-{
- struct bmu_node_connection *connection;
- al_array_foreach(node->connections, i, connection) {
- if (connection->id == id) return connection;
- }
- return NULL;
-}
-
-static void send_control_info_packet(struct bmu_node_connection *connection)
-{
- struct aki_packet *packet = aki_packet_create();
- aki_packet_write_u8(packet, BIMU_CONTROL_INFO);
- aki_packet_write_u16(packet, connection->id);
- connection->handler = bmu_codec_server_create();
- connection->handler->init(connection->handler, &connection->handle, &connection->pool);
- connection->handler->write_info(connection->handler, packet);
- aki_packet_stream_send_packet(connection->control, packet);
-}
-
-static aki_thread_result AKI_THREADCALL handler_thread(void *userdata)
-{
- struct bmu_node_connection *connection = (struct bmu_node_connection *)userdata;
- while (connection->running && connection->handler->step(connection->handler)) {}
- return 0;
-}
-
-static void maybe_start_handler(struct bmu_node_connection *connection)
-{
- al_assert(!connection->running);
- // Don't seek to 0 unless NODE_SEEKED is set.
- if (connection->seek_pos > 0 || (connection->node->flags & BIMU_NODE_SEEKED)) {
- connection->handler->seek(connection->handler, connection->seek_pos);
- }
- connection->running = 1;
- aki_thread_create(&connection->thread, handler_thread, connection);
- struct bmu_node *node = connection->node;
- if (connection->paused == BIMU_NOT_PAUSED) {
- send_resume_packet(connection, connection->seek_pos, node->start);
- connection->paused = BIMU_PLAYING;
- } else if (connection->paused == BIMU_PAUSED) {
- connection->paused = BIMU_PAUSED_AND_RUNNING;
- }
-}
-
-static void identify_packet_callback(void *userdata, struct aki_packet_stream *stream, struct aki_packet *packet)
-{
- struct bmu_server *server = (struct bmu_server *)userdata;
-
- u8 type = aki_packet_read_u8(packet);
-
- u16 connection_id = aki_packet_read_u16(packet);
- u16 node_id = aki_packet_read_u16(packet);
-
- // Disconnecting a stream at any point before setting the new callbacks should
- // be valid and handled properly by the client.
- // Generalize erronious connection checking/handling.
- // - Node with id doesn't exist.
- // - Control connected more than once and/or after info is sent.
- // - Data connected before control.
- // - Data connected more than once.
-
- struct bmu_node *node = get_node_by_id(server, node_id);
- al_assert(node);
-
- struct bmu_node_connection *connection = get_connection_by_id(node, connection_id);
- if (!connection) {
- al_assert(type == BIMU_CONNECTION_CONTROL);
- connection = al_alloc_object(struct bmu_node_connection);
- al_array_push(node->connections, connection);
- connection->id = node->connection_id++;
- connection->node = node;
- connection->control = NULL;
- connection->data = NULL;
- aki_packet_pool_init(&connection->pool, 16, server->loop, packet_pool_callback, connection);
- cch_entry_get_handle(connection->node->entry, &connection->handle);
- connection->paused = BIMU_NOT_PAUSED;
- connection->running = 0;
- }
-
- switch (type) {
- case BIMU_CONNECTION_CONTROL:
- aki_packet_stream_set_no_delay(stream, 1);
- connection->control = stream;
- stream->packet_callback = control_packet_callback;
- stream->packet_sent_callback = default_packet_sent_callback;
- stream->connection_closed_callback = control_connection_closed_callback;
- stream->userdata = connection;
- send_control_info_packet(connection);
- break;
- case BIMU_CONNECTION_DATA:
- // TODO: Account for control connection being in a reconnect state.
- // TODO: is it possible for data->data to be non-NULL during normal operation
- // (disconnect and reconnect very fast?).
- // - Call maybe_cleanup_data in this function?
- al_assert(!connection->data);
- connection->seek_pos = aki_packet_read_u64(packet);
- connection->data = stream;
- stream->packet_callback = data_packet_callback;
- stream->packet_sent_callback = packet_sent_callback;
- stream->connection_closed_callback = data_connection_closed_callback;
- stream->userdata = connection;
- maybe_start_handler(connection);
- break;
- }
-
- aki_packet_free(packet);
-}
-
-static void connection_closed_callback(void *userdata, struct aki_packet_stream *stream)
-{
- (void)userdata;
- (void)stream;
-}
-
-static void connection_callback(void *userdata, struct aki_packet_stream *stream)
-{
- struct bmu_server *server = (struct bmu_server *)userdata;
- stream->connection_closed_callback = connection_closed_callback;
- stream->packet_callback = identify_packet_callback;
- stream->packet_sent_callback = default_packet_sent_callback;
- stream->flushed_callback = NULL;
- stream->userdata = server;
-}
-
-bool bmu_server_init(struct bmu_server *server)
-{
- al_array_init(server->nodes);
- return aki_packet_stream_init(&server->server, AKI_SOCKET_TCP, connection_callback, NULL, NULL, NULL, server);
-}
-
-void bmu_server_listen(struct bmu_server *server, struct aki_event_loop *loop, str *addr, s32 port)
-{
- server->loop = loop;
- aki_packet_stream_listen(&server->server, loop, addr, port);
-}
-
-u16 bmu_server_create_node(struct bmu_server *server, struct cch_entry *entry)
-{
- struct bmu_node *node = al_alloc_object(struct bmu_node);
- al_array_push(server->nodes, node);
- node->id = al_rand_u16();
- node->entry = entry;
- node->flags = 0;
- node->start = 0;
- node->seek_pos = 0;
- node->connection_id = 1;
- al_array_init(node->connections);
- node->server = server;
- return node->id;
-}
-
-void bmu_server_close(struct bmu_server *server)
-{
- (void)server;
-}
diff --git a/src/bimu/server.h b/src/bimu/server.h
deleted file mode 100644
index 20f73c6..0000000
--- a/src/bimu/server.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma once
-
-#include <al/array.h>
-#include <aki/packet_stream.h>
-#include <aki/packet_pool.h>
-
-#include "../cache/entry.h"
-#include "../cache/handle.h"
-
-#include "handler.h"
-
-enum {
- BIMU_PLAYING = 0,
- BIMU_NOT_PAUSED,
- BIMU_PAUSED,
- BIMU_PAUSED_AND_RUNNING
-};
-
-struct bmu_node_connection {
- u16 id;
- struct bmu_node *node;
- struct aki_packet_stream *control;
- struct aki_packet_stream *data;
- struct aki_packet_pool pool;
- s32 running;
- u8 paused;
- u64 seek_pos;
- struct cch_handle handle;
- struct bmu_server_handler *handler;
- struct aki_thread thread;
-};
-
-enum {
- BIMU_NODE_STARTED = 1,
- BIMU_NODE_SEEKED = 1 << 1,
- BIMU_NODE_PAUSED = 1 << 2
-};
-
-struct bmu_node {
- u16 id;
- struct cch_entry *entry;
- u8 flags;
- u64 start;
- u64 seek_pos;
- u16 connection_id;
- array(struct bmu_node_connection *) connections;
- struct bmu_server *server;
-};
-
-struct bmu_server {
- struct aki_event_loop *loop;
- struct aki_packet_stream server;
- array(struct bmu_node *) nodes;
-};
-
-bool bmu_server_init(struct bmu_server *server);
-void bmu_server_listen(struct bmu_server *server, struct aki_event_loop *loop, str *addr, s32 port);
-u16 bmu_server_create_node(struct bmu_server *server, struct cch_entry *entry);
-void bmu_server_close(struct bmu_server *server);
diff --git a/src/bimu/vcr.c b/src/bimu/vcr.c
deleted file mode 100644
index 109edd7..0000000
--- a/src/bimu/vcr.c
+++ /dev/null
@@ -1,173 +0,0 @@
-#include <al/log.h>
-
-#include "vcr.h"
-#include "handler.h"
-
-#define VCR_BUFFER_HIGH 1024
-#define VCR_BUFFER_BUFFERED (VCR_BUFFER_HIGH - 64)
-#define VCR_BUFFER_LOW (VCR_BUFFER_HIGH - 256)
-
-static void signal_callback(void *userdata)
-{
- struct bmu_vcr *vcr = (struct bmu_vcr *)userdata;
- aki_packet_stream_cork(vcr->data, false);
-}
-
-void bmu_vcr_init(struct bmu_vcr *vcr, struct aki_event_loop *loop, struct aki_packet_stream *data)
-{
- al_array_init(vcr->streams);
- al_atomic_u64_store(&vcr->count, 0, AL_ATOMIC_RELAXED);
- vcr->data = data;
- aki_signal_init(&vcr->signal, signal_callback, vcr);
- aki_signal_start(&vcr->signal, loop);
-}
-
-static aki_thread_result AKI_THREADCALL vcr_stream_thread(void *userdata)
-{
- struct bmu_vcr_stream *stream = (struct bmu_vcr_stream *)userdata;
- struct bmu_vcr *vcr = stream->vcr;
- while (aki_packet_cache_wait(&stream->cache)) {
- struct aki_packet *packet = aki_packet_cache_pop(&stream->cache);
- if (!packet) {
- stream->client->handle_eof(stream->client);
- break;
- }
- if (al_atomic_u64_sub(&vcr->count, 1, AL_ATOMIC_RELAXED) < VCR_BUFFER_LOW && stream->buffered) {
- aki_signal_send(&vcr->signal);
- }
- if (al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED) == BIMU_STREAM_STOPPED) {
- aki_mutex_lock(&stream->mutex);
- aki_cond_wait(&stream->cond, &stream->mutex);
- aki_mutex_unlock(&stream->mutex);
- }
- if (al_atomic_s32_load(&stream->state, AL_ATOMIC_RELAXED) == BIMU_STREAM_CLOSED) {
- aki_packet_free(packet);
- break;
- }
- stream->client->handle_data_packet(stream->client, packet);
- aki_packet_free(packet);
- }
- return 0;
-}
-
-void bmu_vcr_add_stream(struct bmu_vcr *vcr, struct bmu_vcr_stream *stream)
-{
- stream->vcr = vcr;
- aki_cond_init(&stream->cond);
- aki_mutex_init(&stream->mutex);
- aki_packet_cache_init(&stream->cache, VCR_BUFFER_HIGH);
- stream->buffered = 0;
- al_array_push(vcr->streams, stream);
- al_atomic_s32_store(&stream->state, BIMU_STREAM_RUNNING, AL_ATOMIC_RELAXED);
-}
-
-static struct bmu_vcr_stream *get_stream_from_index(struct bmu_vcr *vcr, s32 index)
-{
- struct bmu_vcr_stream *stream;
- al_array_foreach(vcr->streams, i, stream) {
- if (stream->index == index) return stream;
- }
- return NULL;
-}
-
-bool bmu_vcr_push_packet(struct bmu_vcr *vcr, struct aki_packet *packet)
-{
- struct bmu_vcr_stream *stream;
- switch (aki_packet_read_u8(packet)) {
- case BIMU_PACKET_DATA:
- stream = get_stream_from_index(vcr, aki_packet_read_s32(packet));
- al_assert(stream);
- if (!stream->running) {
- aki_thread_create(&stream->thread, vcr_stream_thread, stream);
- stream->running = true;
- }
- if (!aki_packet_cache_send_packet(&stream->cache, packet)) {
- aki_packet_free(packet);
- } else if (al_atomic_u64_add(&vcr->count, 1, AL_ATOMIC_RELAXED) >= VCR_BUFFER_BUFFERED) {
- aki_packet_stream_cork(vcr->data, true);
- al_array_foreach(vcr->streams, i, stream) {
- stream->buffered = 1;
- }
- }
- break;
- case BIMU_PACKET_EOF:
- al_array_foreach(vcr->streams, i, stream) {
- aki_packet_cache_send_packet(&stream->cache, NULL);
- }
- aki_packet_free(packet);
- break;
- case BIMU_PACKET_ERROR:
- aki_packet_free(packet);
- al_log_warn("bimu", "Unhandled error packet.");
- break;
- default:
- al_assert(false);
- }
- return true;
-}
-
-static void vcr_stream_close_internal(struct bmu_vcr_stream *stream)
-{
- al_atomic_s32_store(&stream->state, BIMU_STREAM_CLOSED, AL_ATOMIC_RELAXED);
- aki_packet_cache_disable(&stream->cache);
- aki_mutex_lock(&stream->mutex);
- if (aki_cond_is_waiting(&stream->cond)) {
- aki_cond_signal(&stream->cond);
- }
- aki_mutex_unlock(&stream->mutex);
- if (stream->running) {
- aki_thread_join(&stream->thread);
- }
- struct aki_packet *packet;
- while ((packet = aki_packet_cache_pop(&stream->cache))) {
- aki_packet_free(packet);
- }
-}
-
-void bmu_vcr_stream_close(struct bmu_vcr_stream *stream)
-{
- vcr_stream_close_internal(stream);
-}
-
-void bmu_vcr_flush(struct bmu_vcr *vcr)
-{
- struct bmu_vcr_stream *stream;
- al_array_foreach(vcr->streams, i, stream) {
- vcr_stream_close_internal(stream);
- stream->client->flush(stream->client);
- aki_packet_cache_enable(&stream->cache);
- stream->running = false;
- al_atomic_s32_store(&stream->state, BIMU_STREAM_RUNNING, AL_ATOMIC_RELAXED);
- }
- al_atomic_u64_store(&vcr->count, 0, AL_ATOMIC_RELAXED);
-}
-
-void bmu_vcr_stream_cork(struct bmu_vcr_stream *stream)
-{
- al_atomic_s32_store(&stream->state, BIMU_STREAM_STOPPED, AL_ATOMIC_RELAXED);
-}
-
-void bmu_vcr_stream_uncork(struct bmu_vcr_stream *stream)
-{
- al_atomic_s32_store(&stream->state, BIMU_STREAM_RUNNING, AL_ATOMIC_RELAXED);
- aki_mutex_lock(&stream->mutex);
- if (aki_cond_is_waiting(&stream->cond)) {
- aki_cond_signal(&stream->cond);
- }
- aki_mutex_unlock(&stream->mutex);
-}
-
-void bmu_vcr_free(struct bmu_vcr *vcr)
-{
- aki_signal_stop(&vcr->signal);
- struct bmu_vcr_stream *stream;
- al_array_foreach(vcr->streams, i, stream) {
- aki_packet_cache_free(&stream->cache);
- stream->client->free(&stream->client);
- if (stream->stream.type == CAMU_FFMPEG_COMPAT) {
- avformat_free_context(stream->stream.av.format_context);
- }
- al_free(stream);
- }
- al_array_free(vcr->streams);
-}
diff --git a/src/bimu/vcr.h b/src/bimu/vcr.h
deleted file mode 100644
index 0f81c12..0000000
--- a/src/bimu/vcr.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include <aki/packet_cache.h>
-#include <al/atomic.h>
-#include <aki/packet_stream.h>
-#include <aki/signal.h>
-
-#include "../codec/codec.h"
-
-enum {
- BIMU_STREAM_RUNNING = 0,
- BIMU_STREAM_STOPPED,
- BIMU_STREAM_CLOSED
-};
-
-struct bmu_vcr_stream {
- u8 type;
- s32 index;
- struct camu_stream stream;
- struct bmu_client_handler *client;
- atomic_s32 state;
- struct aki_packet_cache cache;
- s32 buffered;
- struct aki_cond cond;
- struct aki_mutex mutex;
- bool running;
- struct aki_thread thread;
- struct bmu_vcr *vcr;
-};
-
-struct bmu_vcr {
- array(struct bmu_vcr_stream *) streams;
- atomic_u64 count;
- struct aki_packet_stream *data;
- struct aki_signal signal;
-};
-
-void bmu_vcr_init(struct bmu_vcr *vcr, struct aki_event_loop *loop, struct aki_packet_stream *data);
-void bmu_vcr_add_stream(struct bmu_vcr *vcr, struct bmu_vcr_stream *stream);
-bool bmu_vcr_push_packet(struct bmu_vcr *vcr, struct aki_packet *packet);
-void bmu_vcr_stream_close(struct bmu_vcr_stream *stream);
-void bmu_vcr_flush(struct bmu_vcr *vcr);
-void bmu_vcr_stream_cork(struct bmu_vcr_stream *stream);
-void bmu_vcr_stream_uncork(struct bmu_vcr_stream *stream);
-void bmu_vcr_free(struct bmu_vcr *vcr);