diff options
| author | 2024-04-09 11:24:01 -0400 | |
|---|---|---|
| committer | 2024-04-09 11:24:01 -0400 | |
| commit | 02f3d3565602146bbbfce85b2719246f24036cb9 (patch) | |
| tree | c6588ffe297b777e36260effa4fa42b958ca6ba3 /src/bimu | |
| parent | bbf3314165182e402ff25acccddc004a87f81ef0 (diff) | |
| download | camu-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.c | 246 | ||||
| -rw-r--r-- | src/bimu/client.h | 31 | ||||
| -rw-r--r-- | src/bimu/common.h | 23 | ||||
| -rw-r--r-- | src/bimu/handler.h | 52 | ||||
| -rw-r--r-- | src/bimu/handlers/cdio.h | 17 | ||||
| -rw-r--r-- | src/bimu/handlers/cdio_server.c | 21 | ||||
| -rw-r--r-- | src/bimu/handlers/codec.h | 20 | ||||
| -rw-r--r-- | src/bimu/handlers/codec_client.c | 104 | ||||
| -rw-r--r-- | src/bimu/handlers/codec_server.c | 140 | ||||
| -rw-r--r-- | src/bimu/handlers/dvd.h | 14 | ||||
| -rw-r--r-- | src/bimu/handlers/dvd_server.c | 21 | ||||
| -rw-r--r-- | src/bimu/local.c | 281 | ||||
| -rw-r--r-- | src/bimu/local.h | 52 | ||||
| -rw-r--r-- | src/bimu/meson.build | 29 | ||||
| -rw-r--r-- | src/bimu/server.c | 356 | ||||
| -rw-r--r-- | src/bimu/server.h | 59 | ||||
| -rw-r--r-- | src/bimu/vcr.c | 173 | ||||
| -rw-r--r-- | src/bimu/vcr.h | 45 |
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); |