diff options
Diffstat (limited to 'src')
38 files changed, 504 insertions, 290 deletions
diff --git a/src/buffer/video.c b/src/buffer/video.c index ab61c2a..7874615 100644 --- a/src/buffer/video.c +++ b/src/buffer/video.c @@ -87,7 +87,7 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code #ifdef CAMU_HAVE_FFMPEG const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((enum AVPixelFormat)fmt->format); bool has_alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0; - req->format = has_alpha ? CAMU_PIXEL_FORMAT_RGB32 : CAMU_PIXEL_FORMAT_RGB24; + req->format = has_alpha ? CAMU_PIXEL_FORMAT_RGBA : CAMU_PIXEL_FORMAT_RGB24; buf->scaler = camu_ff_scaler_create(); if (!buf->scaler->init(buf->scaler, &buf->fmt)) { // Scaler will be freed in video_buffer_free(). diff --git a/src/cache/entry.c b/src/cache/entry.c index 183278a..0f50462 100644 --- a/src/cache/entry.c +++ b/src/cache/entry.c @@ -12,9 +12,14 @@ bool cch_entry_get_handle(struct cch_entry *entry, struct cch_handle *handle) return true; } -str *cch_entry_get_liana(struct cch_entry *entry) +str *cch_entry_get_handler(struct cch_entry *entry) { - return &entry->handler->liana; + return &entry->handler->handler; +} + +s32 cch_entry_guess_format(struct cch_entry *entry) +{ + return entry->handler->guess_format(entry->handler); } void cch_entry_return_handle(struct cch_entry *entry, struct cch_handle *handle) diff --git a/src/cache/entry.h b/src/cache/entry.h index d6eb86a..693e68b 100644 --- a/src/cache/entry.h +++ b/src/cache/entry.h @@ -80,7 +80,7 @@ [ ] On creation, the handler can create multiple backings and chapters. [ ] Chapters include index into array of backings. [ ] Method of requesting a unique file backing. - */ +*/ struct cch_chapter { off_t start; @@ -95,6 +95,7 @@ struct cch_entry { }; bool cch_entry_get_handle(struct cch_entry *entry, struct cch_handle *handle); -str *cch_entry_get_liana(struct cch_entry *entry); +str *cch_entry_get_handler(struct cch_entry *entry); +s32 cch_entry_guess_format(struct cch_entry *entry); void cch_entry_return_handle(struct cch_entry *entry, struct cch_handle *handle); void cch_entry_free(struct cch_entry **entry); diff --git a/src/cache/handler.h b/src/cache/handler.h index 4051449..fec7f0a 100644 --- a/src/cache/handler.h +++ b/src/cache/handler.h @@ -9,7 +9,8 @@ struct cch_handler { bool (*can_seek)(struct cch_handler *); void (*maybe_spawn_worker)(struct cch_handler *, size_t); bool (*wait_for_range)(struct cch_handler *, struct cch_wait *); + s32 (*guess_format)(struct cch_handler *); void (*free)(struct cch_handler **); struct cch_entry *entry; - str liana; + str handler; }; diff --git a/src/cache/handlers/cdio.c b/src/cache/handlers/cdio.c index 7c83523..abebeb0 100644 --- a/src/cache/handlers/cdio.c +++ b/src/cache/handlers/cdio.c @@ -119,7 +119,7 @@ static void handler_cdio_free(struct cch_handler **handler) cdio_cddap_close(cdio->drive); } cch_threaded_waits_close(&cdio->waits); - al_str_free(&cdio->handler.liana); + al_str_free(&cdio->handler.handler); al_free(cdio); *handler = NULL; } @@ -198,7 +198,7 @@ struct cch_entry *cch_handler_cdio_create(void) entry->handler->wait_for_range = handler_cdio_wait_for_range; entry->handler->free = handler_cdio_free; entry->handler->entry = entry; - al_str_from(&entry->handler->liana, "cdio"); + al_str_from(&entry->handler->handler, "cdio"); if (!open_cd_drive(cdio)) { return NULL; } diff --git a/src/cache/handlers/file.c b/src/cache/handlers/file.c index 345cdca..dba5649 100644 --- a/src/cache/handlers/file.c +++ b/src/cache/handlers/file.c @@ -1,3 +1,5 @@ +#include "../../codec/codec.h" + #include "../backings/file.h" #include "file.h" @@ -22,15 +24,28 @@ static bool handler_file_wait_for_range(struct cch_handler *handler, struct cch_ return true; } +static s32 handler_file_guess_format(struct cch_handler *handler) +{ + struct cch_handler_file *file = (struct cch_handler_file *)handler; + struct cch_backing_file *backing = (struct cch_backing_file *)file->backing; + str *path = &backing->file.path; + u32 dot = al_str_rfind(path, '.'); + if (dot != AL_STR_NPOS) { + str ext = al_str_substr(path, dot, path->length); + return camu_guess_format(NULL, &ext, NULL); + } + return -1; +} + static void handler_file_free(struct cch_handler **handler) { struct cch_handler_file *file = (struct cch_handler_file *)*handler; - al_str_free(&file->handler.liana); + al_str_free(&file->handler.handler); al_free(file); *handler = NULL; } -struct cch_entry *cch_handler_file_create(str *path, str *liana) +struct cch_entry *cch_handler_file_create(str *path, str *handler) { struct cch_backing *backing = cch_backing_file_create(path, 0); if (!backing) return NULL; @@ -42,8 +57,9 @@ struct cch_entry *cch_handler_file_create(str *path, str *liana) entry->handler->can_seek = handler_file_can_seek; entry->handler->maybe_spawn_worker = handler_file_maybe_spawn_worker; entry->handler->wait_for_range = handler_file_wait_for_range; + entry->handler->guess_format = handler_file_guess_format; entry->handler->free = handler_file_free; entry->handler->entry = entry; - al_str_clone(&entry->handler->liana, liana); + al_str_clone(&entry->handler->handler, handler); return entry; } diff --git a/src/cache/handlers/file.h b/src/cache/handlers/file.h index 4704387..f883498 100644 --- a/src/cache/handlers/file.h +++ b/src/cache/handlers/file.h @@ -10,4 +10,4 @@ struct cch_handler_file { struct cch_backing *backing; }; -struct cch_entry *cch_handler_file_create(str *path, str *liana); +struct cch_entry *cch_handler_file_create(str *path, str *handler); diff --git a/src/cache/handlers/http.c b/src/cache/handlers/http.c index e48490b..1691ea9 100644 --- a/src/cache/handlers/http.c +++ b/src/cache/handlers/http.c @@ -102,7 +102,7 @@ static void handler_http_free(struct cch_handler **handler) cch_threaded_waits_close(&http->waits); al_array_free(http->requests); al_str_free(&http->url); - al_str_free(&http->handler.liana); + al_str_free(&http->handler.handler); al_free(http); *handler = NULL; } @@ -121,7 +121,7 @@ struct cch_entry *cch_handler_http_create(str *url, struct nn_event_loop *loop) entry->handler->wait_for_range = handler_http_wait_for_range; entry->handler->free = handler_http_free; entry->handler->entry = entry; - al_str_from(&entry->handler->liana, "codec"); + al_str_from(&entry->handler->handler, "codec"); http->loop = loop; al_str_clone(&http->url, url); http->pointer = 0; diff --git a/src/codec/codec.h b/src/codec/codec.h index 25ec73e..701ef16 100644 --- a/src/codec/codec.h +++ b/src/codec/codec.h @@ -1,6 +1,7 @@ #pragma once #include <al/array.h> +#include <al/str.h> #include <nnwt/common.h> #ifdef CAMU_HAVE_FFMPEG #include <libavutil/pixdesc.h> @@ -9,6 +10,8 @@ #include "../cache/handle.h" +#include "codecs.h" + enum { CAMU_LANG_UNKNOWN = 0, CAMU_LANG_ENGLISH, @@ -59,7 +62,6 @@ enum { enum { CAMU_PIXEL_FORMAT_RGBA = AV_PIX_FMT_RGBA, - CAMU_PIXEL_FORMAT_RGB8 = AV_PIX_FMT_RGB8, CAMU_PIXEL_FORMAT_RGB24 = AV_PIX_FMT_RGB24, CAMU_PIXEL_FORMAT_RGB32 = AV_PIX_FMT_RGB32, CAMU_PIXEL_FORMAT_GREYA = AV_PIX_FMT_GRAY8A, @@ -67,6 +69,13 @@ enum { CAMU_PIXEL_FORMAT_PAL8 = AV_PIX_FMT_PAL8 }; +enum { + CAMU_CODEC_FALLBACK = -1, + CAMU_CODEC_NONE = AV_CODEC_ID_NONE, + CAMU_CODEC_PNG = AV_CODEC_ID_PNG, + CAMU_CODEC_JPEG = AV_CODEC_ID_MJPEG +}; + #define CAMU_PLANAR_DATA_POINTERS AV_NUM_DATA_POINTERS #else enum { @@ -107,9 +116,18 @@ enum { enum { CAMU_PIXEL_FORMAT_RGBA = 0, - CAMU_PIXEL_FORMAT_RGB, + CAMU_PIXEL_FORMAT_RGB24, + CAMU_PIXEL_FORMAT_RGB32, CAMU_PIXEL_FORMAT_GREYA, - CAMU_PIXEL_FORMAT_GREY + CAMU_PIXEL_FORMAT_GREY, + CAMU_PIXEL_FORMAT_PAL8 +}; + +enum { + CAMU_CODEC_FALLBACK = -1, + CAMU_CODEC_NONE, + CAMU_CODEC_PNG, + CAMU_CODEC_JPEG }; #define CAMU_PLANAR_DATA_POINTERS 8 @@ -150,6 +168,7 @@ struct camu_codec_stream { u8 type; s32 index; u64 duration; + struct camu_codec_info *codec_info; struct { struct camu_video_format fmt; } video; @@ -256,6 +275,7 @@ static inline bool camu_resampler_format_matches(struct camu_resampler_format *f && fmt->in.channel_count == fmt->req.channel_count; } +#ifdef CAMU_HAVE_FFMPEG #ifndef CAMU_OLD_FFMPEG #define AV_CODECPAR_CHANNEL_LAYOUT(codecpar) ((codecpar)->ch_layout) #define AV_CODECPAR_CHANNELS(codecpar) ((codecpar)->ch_layout.nb_channels) @@ -279,6 +299,7 @@ static inline void camu_copy_channel_layout(u64 *dest, u64 *src) *dest = *src; } #endif +#endif static inline void camu_audio_format_copy(struct camu_audio_format *dest, struct camu_audio_format *src) { @@ -408,3 +429,28 @@ static inline void camu_codec_frame_discard(struct camu_codec_frame *frame) if (frame->mode == CAMU_NORMAL && frame->data) al_free(frame->data); al_free(frame); } + +static inline s32 camu_guess_format(str *short_name, str *ext, str *mime_type) +{ + if (al_str_eq(ext, &al_str_c(".png"))) { + return CAMU_CODEC_PNG; + } else if (al_str_eq(ext, &al_str_c(".jpeg")) || al_str_eq(ext, &al_str_c(".jpg"))) { + return CAMU_CODEC_JPEG; + } +#ifdef CAMU_HAVE_FFMPEG + char *c_short_name = short_name ? al_str_to_c_str(short_name) : NULL; + char *c_ext = ext ? al_str_to_c_str(ext) : NULL; + char *c_mime_type = mime_type ? al_str_to_c_str(mime_type) : NULL; + // Empty short_name to attempt avoiding image2 probing. + const AVOutputFormat *fmt = av_guess_format(c_short_name ? c_short_name : "", c_ext, c_mime_type); + if (c_short_name) al_free(c_short_name); + if (c_ext) al_free(c_ext); + if (c_mime_type) al_free(c_mime_type); + // In FFmpeg AV_CODEC_ID_MJPEG also means "image2". + if (fmt) return (fmt->audio_codec != AV_CODEC_ID_NONE) ? fmt->audio_codec : fmt->video_codec; +#else + (void)short_name; + (void)mime_type; +#endif + return -1; +} diff --git a/src/codec/codecs.c b/src/codec/codecs.c new file mode 100644 index 0000000..7374517 --- /dev/null +++ b/src/codec/codecs.c @@ -0,0 +1,96 @@ +#include "codecs.h" +#include "codec.h" + +#ifdef LIANA_SERVER +#include "../../codec/wuffs/demuxer.h" +#include "../../codec/stb_image/demuxer.h" +#include "../../codec/spng/demuxer.h" +#ifdef CAMU_HAVE_FFMPEG +#include "../../codec/ffmpeg/demuxer.h" +#endif +#endif + +#ifdef LIANA_CLIENT +#include "../../codec/wuffs/decoder.h" +#include "../../codec/stb_image/decoder.h" +#include "../../codec/spng/decoder.h" +#ifdef CAMU_HAVE_FFMPEG +#include "../../codec/ffmpeg/decoder.h" +#endif +#endif + +struct camu_codec_info codec_information[] = { +#ifdef CAMU_HAVE_WUFFS + { + .name = al_str_c("wuffs"), + .supported = (s32[]){ CAMU_CODEC_PNG, CAMU_CODEC_NONE }, +#ifdef LIANA_SERVER + .create_demuxer = camu_wuffs_demuxer_create, +#endif +#ifdef LIANA_CLIENT + .create_decoder = camu_wuffs_decoder_create +#endif + }, +#endif +#ifdef CAMU_HAVE_STB_IMAGE + { + .name = al_str_c("stb_image"), + .supported = (s32[]){ CAMU_CODEC_PNG, CAMU_CODEC_JPEG, CAMU_CODEC_NONE }, +#ifdef LIANA_SERVER + .create_demuxer = camu_stbi_demuxer_create, +#endif +#ifdef LIANA_CLIENT + .create_decoder = camu_stbi_decoder_create +#endif + }, +#endif +#ifdef CAMU_HAVE_SPNG + { + .name = al_str_c("spng"), + .supported = (s32[]){ CAMU_CODEC_PNG, CAMU_CODEC_NONE }, +#ifdef LIANA_SERVER + .create_demuxer = camu_spng_demuxer_create, +#endif +#ifdef LIANA_CLIENT + .create_decoder = camu_spng_decoder_create +#endif + }, +#endif +#ifdef CAMU_HAVE_FFMPEG + { + .name = al_str_c("FFmpeg"), + .supported = (s32[]){ CAMU_CODEC_FALLBACK }, +#ifdef LIANA_SERVER + .create_demuxer = camu_ff_demuxer_create, +#endif +#ifdef LIANA_CLIENT + .create_decoder = camu_ff_decoder_create +#endif + }, +#endif +}; + +struct camu_codec_info *camu_codec_info_by_type(s32 type) +{ + for (u32 i = 0; i < ARRAY_SIZE(codec_information); i++) { + struct camu_codec_info *info = &codec_information[i]; + s32 *supported = info->supported; + while (*supported != CAMU_CODEC_NONE) { + if (type == (*supported) || (*supported) == CAMU_CODEC_FALLBACK) { + return info; + } + supported++; + } + } + return NULL; +} + +struct camu_codec_info *camu_codec_info_by_name(str *name) +{ + for (u32 i = 0; i < ARRAY_SIZE(codec_information); i++) { + if (al_str_eq(&codec_information[i].name, name)) { + return &codec_information[i]; + } + } + return NULL; +} diff --git a/src/codec/codecs.h b/src/codec/codecs.h new file mode 100644 index 0000000..d383eec --- /dev/null +++ b/src/codec/codecs.h @@ -0,0 +1,15 @@ +#pragma once + +#include <al/str.h> + +struct camu_codec_info { + str name; + s32 *supported; + struct camu_demuxer *(*create_demuxer)(void); + struct camu_decoder *(*create_decoder)(void); +}; + +extern struct camu_codec_info codec_information[]; + +struct camu_codec_info *camu_codec_info_by_type(s32 type); +struct camu_codec_info *camu_codec_info_by_name(str *name); diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c index cfa1dc2..7be21a2 100644 --- a/src/codec/ffmpeg/decoder.c +++ b/src/codec/ffmpeg/decoder.c @@ -151,11 +151,11 @@ static bool hw_device_supported_by_type(struct camu_ff_decoder *av, enum AVHWDev } */ -static enum AVHWDeviceType hw_device_supported_by_name(struct camu_ff_decoder *av, const char *name) +static enum AVHWDeviceType hw_device_supported_by_name(struct camu_ff_decoder *av, const char *name, size_t length) { enum AVHWDeviceType supported_type; al_array_foreach(av->supported_hw_devices, i, supported_type) { - if (strcmp(av_hwdevice_get_type_name(supported_type), name) == 0) { + if (al_strncmp(av_hwdevice_get_type_name(supported_type), name, length) == 0) { return supported_type; } } @@ -236,7 +236,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend av->hw_device_type = AV_HWDEVICE_TYPE_NONE; av->hw_pix_fmt = AV_PIX_FMT_NONE; for (u32 i = 0; i < ARRAY_SIZE(hwdevces); i++) { - av->hw_device_type = hw_device_supported_by_name(av, hwdevces[i]); + size_t length = sizeof(hwdevces[i]) - 1; + av->hw_device_type = hw_device_supported_by_name(av, hwdevces[i], length); if (!get_hwdevice_config(av, codec, av->hw_device_type)) { av->hw_device_type = AV_HWDEVICE_TYPE_NONE; } else { @@ -247,7 +248,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend const AVCodec *hw_codec; al_array_foreach(av->supported_hw_codecs, i, hw_codec) { if (hw_codec->id == codecpar->codec_id) { - av->hw_device_type = hw_device_supported_by_name(av, hw_codec->wrapper_name); + size_t length = al_strlen(hw_codec->wrapper_name); + av->hw_device_type = hw_device_supported_by_name(av, hw_codec->wrapper_name, length); if (get_hwdevice_config(av, hw_codec, av->hw_device_type)) { codec = hw_codec; break; diff --git a/src/codec/meson.build b/src/codec/meson.build index 9401b0b..851a72a 100644 --- a/src/codec/meson.build +++ b/src/codec/meson.build @@ -1,4 +1,4 @@ -codec_src = ['packet_ext.c'] +codec_src = ['packet_ext.c', 'codecs.c'] codec_server_deps = [] codec_client_deps = [] diff --git a/src/codec/spng/meson.build b/src/codec/spng/meson.build index d8af781..f99a885 100644 --- a/src/codec/spng/meson.build +++ b/src/codec/spng/meson.build @@ -1,3 +1,6 @@ spng = dependency('spng') -codec_server_deps += [declare_dependency(sources: ['server.c'], dependencies: spng)] -codec_client_deps += [declare_dependency(sources: ['client.c'], dependencies: spng)] +spng_args = ['-DCAMU_HAVE_SPNG'] +codec_server_deps += declare_dependency(sources: ['server.c'], + dependencies: spng, compile_args: spng_args) +codec_client_deps += declare_dependency(sources: ['client.c'], + dependencies: spng, compile_args: spng_args) diff --git a/src/codec/spng/server.c b/src/codec/spng/server.c index 8eb941b..1bb2ca8 100644 --- a/src/codec/spng/server.c +++ b/src/codec/spng/server.c @@ -13,7 +13,8 @@ static bool spng_demuxer_init(struct camu_demuxer *demux, struct cch_handle *han spng->eof = false; cch_handle_seek(spng->handle, 0, SEEK_SET); - off_t size = cch_entry_get_size(spng->handle->entry); + struct cch_backing *backing = spng->handle->entry->backing; + off_t size = backing->get_size_if_known(backing); nn_buffer_ensure_space(&spng->buffer, size); cch_handle_read(spng->handle, nn_buffer_get_ptr(&spng->buffer, 0), size); spng->buffer.size = size; @@ -59,10 +60,11 @@ static u64 spng_demuxer_get_duration(struct camu_demuxer *demux) return 0; } -static bool spng_demuxer_seek(struct camu_demuxer *demux, u64 pos) +static bool spng_demuxer_seek(struct camu_demuxer *demux, u64 pos, bool bytes) { (void)demux; (void)pos; + (void)bytes; return true; } @@ -75,7 +77,6 @@ static void spng_demuxer_free(struct camu_demuxer **demux) *demux = NULL; } - struct camu_demuxer *camu_spng_demuxer_create(void) { struct camu_spng_demuxer *spng = al_alloc_object(struct camu_spng_demuxer); diff --git a/src/codec/stb_image/meson.build b/src/codec/stb_image/meson.build index fea86ff..e6faa21 100644 --- a/src/codec/stb_image/meson.build +++ b/src/codec/stb_image/meson.build @@ -1,3 +1,6 @@ stb = subproject('stb').get_variable('stb') -codec_server_deps += declare_dependency(sources: ['server.c', 'impl.c'], dependencies: stb) -codec_client_deps += declare_dependency(sources: ['client.c', 'impl.c'], dependencies: stb) +stb_args = ['-DCAMU_HAVE_STB_IMAGE'] +codec_server_deps += declare_dependency(sources: ['server.c', 'impl.c'], + dependencies: stb, compile_args: stb_args) +codec_client_deps += declare_dependency(sources: ['client.c', 'impl.c'], + dependencies: stb, compile_args: stb_args) diff --git a/src/codec/wuffs/client.c b/src/codec/wuffs/client.c new file mode 100644 index 0000000..c57e506 --- /dev/null +++ b/src/codec/wuffs/client.c @@ -0,0 +1,100 @@ +#include "decoder.h" +#include "inc.h" + +static bool wuffs_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_codec_stream *stream, + void (*callback)(void *, struct camu_codec_frame *), void *userdata) +{ + struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; + (void)renderer; + wfs->stream = stream; + wfs->callback = callback; + wfs->userdata = userdata; + return true; +} + +static s32 wuffs_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet) +{ + struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; + if (!packet) return CAMU_OK; + + struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame); + frame->mode = CAMU_NORMAL; + frame->flags = 0; + frame->data = NULL; + struct camu_video_format *fmt = &wfs->stream->video.fmt; + frame->video.width = fmt->width; + frame->video.height = fmt->height; + frame->format = CAMU_PIXEL_FORMAT_RGBA; + + wuffs_png__decoder *wf_dec = wuffs_png__decoder__alloc(); + if (!wf_dec) goto err; + + wuffs_png__decoder__set_quirk(wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true); + + wuffs_base__io_buffer src = { 0 }; + src.data.ptr = nn_buffer_get_ptr(packet->buffer, 0); + src.data.len = packet->buffer->size; + src.meta.wi = packet->buffer->size; + src.meta.closed = true; + + wuffs_base__image_config ic = { 0 }; + wuffs_base__status status = wuffs_png__decoder__decode_image_config(wf_dec, &ic, &src); + if (!wuffs_base__status__is_ok(&status)) goto err; + if (!wuffs_base__image_config__is_valid(&ic)) goto err; + + u32 pixsub = WUFFS_BASE__PIXEL_SUBSAMPLING__NONE; + u32 pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL; + wuffs_base__pixel_config__set(&ic.pixcfg, pixfmt, pixsub, fmt->width, fmt->height); + + wuffs_base__pixel_buffer pb = { 0 }; + size_t dst_size = fmt->width * fmt->height * 4; + size_t wrk_size = wuffs_png__decoder__workbuf_len(wf_dec).max_incl; + frame->data = camu_page_alloc(dst_size + wrk_size); + status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, wuffs_base__make_slice_u8(frame->data, dst_size)); + if (!wuffs_base__status__is_ok(&status)) goto err; + wuffs_base__slice_u8 wrk = wuffs_base__make_slice_u8(frame->data + dst_size, wrk_size); + + status = wuffs_png__decoder__decode_frame(wf_dec, &pb, &src, 0, wrk, NULL); + if (!wuffs_base__status__is_ok(&status)) goto err; + + wfs->callback(wfs->userdata, frame); + + free(wf_dec); + + return CAMU_OK; +err: + if (wf_dec) free(wf_dec); + camu_codec_frame_discard(frame); + + return CAMU_ERR_ERROR; +} + +static void wuffs_decoder_flush(struct camu_decoder *dec) +{ + (void)dec; +} + +static s32 wuffs_decoder_process(struct camu_decoder *dec) +{ + (void)dec; + return CAMU_ERR_EOF; +} + +static void wuffs_decoder_free(struct camu_decoder **dec) +{ + struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)*dec; + al_free(wfs); + *dec = NULL; +} + +struct camu_decoder *camu_wuffs_decoder_create(void) +{ + struct camu_wuffs_decoder *wfs = al_alloc_object(struct camu_wuffs_decoder); + wfs->dec.mode = CAMU_NORMAL; + wfs->dec.init = wuffs_decoder_init; + wfs->dec.push = wuffs_decoder_push; + wfs->dec.process = wuffs_decoder_process; + wfs->dec.flush = wuffs_decoder_flush; + wfs->dec.free = wuffs_decoder_free; + return (struct camu_decoder *)wfs; +} diff --git a/src/codec/wuffs/impl.c b/src/codec/wuffs/impl.c index 2c8f162..ab291cb 100644 --- a/src/codec/wuffs/impl.c +++ b/src/codec/wuffs/impl.c @@ -1,204 +1,2 @@ -#include <nnwt/common.h> #define WUFFS_IMPLEMENTATION -#define WUFFS_CONFIG__STATIC_FUNCTIONS -#define WUFFS_CONFIG__MODULES -#define WUFFS_CONFIG__MODULE__BASE -#define WUFFS_CONFIG__MODULE__ADLER32 -#define WUFFS_CONFIG__MODULE__DEFLATE -#define WUFFS_CONFIG__MODULE__ZLIB -#define WUFFS_CONFIG__MODULE__CRC32 -#define WUFFS_CONFIG__MODULE__PNG -#define WUFFS_CONFIG__MODULE__JPEG -#define WUFFS_CONFIG__MODULE__IMAGE -#include <wuffs-unsupported-snapshot.c> - -#include "../../cache/entry.h" - -#include "demuxer.h" -#include "decoder.h" - -static bool wuffs_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle) -{ - struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux; - - wfs->handle = handle; - nn_buffer_init(&wfs->buffer); - wfs->eof = false; - - cch_handle_seek(wfs->handle, 0, SEEK_SET); - off_t size = cch_entry_get_size(wfs->handle->entry); - nn_buffer_ensure_space(&wfs->buffer, size); - cch_handle_read(wfs->handle, nn_buffer_get_ptr(&wfs->buffer, 0), size); - wfs->buffer.size = size; - - wuffs_png__decoder wf_dec = { 0 }; - wuffs_base__status status = wuffs_png__decoder__initialize(&wf_dec, sizeof(wf_dec), WUFFS_VERSION, 0); - if (!wuffs_base__status__is_ok(&status)) goto err; - - wuffs_png__decoder__set_quirk(&wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true); - - wuffs_base__io_buffer src = { 0 }; - src.data.ptr = nn_buffer_get_ptr(&wfs->buffer, 0); - src.data.len = wfs->buffer.size; - src.meta.wi = wfs->buffer.size; - src.meta.closed = true; - - wuffs_base__image_config ic = { 0 }; - status = wuffs_png__decoder__decode_image_config(&wf_dec, &ic, &src); - if (!wuffs_base__status__is_ok(&status)) goto err; - if (!wuffs_base__image_config__is_valid(&ic)) goto err; - - struct camu_codec_stream stream; - stream.mode = CAMU_NORMAL; - stream.type = CAMU_STREAM_VIDEO; - stream.video.width = wuffs_base__pixel_config__width(&ic.pixcfg); - stream.video.height = wuffs_base__pixel_config__height(&ic.pixcfg); - stream.video.format = CAMU_PIXEL_FORMAT_RGBA; - - al_array_push(wfs->demux.streams, stream); - - return true; -err: - return false; -} - -static s32 wuffs_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet) -{ - struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux; - if (!wfs->eof) { - packet->mode = CAMU_NORMAL; - packet->buffer = &wfs->buffer; - wfs->eof = true; - return CAMU_OK; - } - return CAMU_ERR_EOF; -} - -static u64 wuffs_demuxer_get_duration(struct camu_demuxer *demux) -{ - (void)demux; - return 0; -} - -static bool wuffs_demuxer_seek(struct camu_demuxer *demux, u64 pos) -{ - (void)demux; - (void)pos; - return true; -} - -static void wuffs_demuxer_free(struct camu_demuxer **demux) -{ - struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)*demux; - nn_buffer_free(&wfs->buffer); - al_array_free(wfs->demux.streams); - al_free(wfs); - *demux = NULL; -} - -static bool wuffs_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_codec_stream *stream, - void (*callback)(void *, struct camu_codec_frame *), void *userdata) -{ - struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; - (void)renderer; - wfs->stream = stream; - wfs->callback = callback; - wfs->userdata = userdata; - return true; -} - -static s32 wuffs_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet) -{ - struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; - if (!packet) return CAMU_OK; - - struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame); - frame->mode = CAMU_NORMAL; - frame->data = NULL; - frame->flags = 0; - frame->width = wfs->stream->video.width; - frame->height = wfs->stream->video.height; - frame->format = CAMU_PIXEL_FMT_RGBA; - - wuffs_png__decoder wf_dec = { 0 }; - wuffs_base__status status = wuffs_png__decoder__initialize(&wf_dec, sizeof(wf_dec), WUFFS_VERSION, 0); - if (!wuffs_base__status__is_ok(&status)) goto err; - - wuffs_png__decoder__set_quirk(&wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true); - - wuffs_base__io_buffer src = { 0 }; - src.data.ptr = nn_buffer_get_ptr(packet->buffer, 0); - src.data.len = packet->buffer->size; - src.meta.wi = packet->buffer->size; - src.meta.closed = true; - - wuffs_base__image_config ic = { 0 }; - status = wuffs_png__decoder__decode_image_config(&wf_dec, &ic, &src); - if (!wuffs_base__status__is_ok(&status)) goto err; - if (!wuffs_base__image_config__is_valid(&ic)) goto err; - - u32 pixsub = WUFFS_BASE__PIXEL_SUBSAMPLING__NONE; - u32 pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL; - wuffs_base__pixel_config__set(&ic.pixcfg, pixfmt, pixsub, frame->width, frame->height); - - wuffs_base__pixel_buffer pb = { 0 }; - size_t dst_size = frame->width * frame->height * 4; - size_t wrk_size = wuffs_png__decoder__workbuf_len(&wf_dec).max_incl; - frame->data = camu_page_alloc(dst_size + wrk_size); - status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, wuffs_base__make_slice_u8(frame->data, dst_size)); - if (!wuffs_base__status__is_ok(&status)) goto err; - wuffs_base__slice_u8 wrk = wuffs_base__make_slice_u8(frame->data + dst_size, wrk_size); - - status = wuffs_png__decoder__decode_frame(&wf_dec, &pb, &src, 0, wrk, NULL); - if (!wuffs_base__status__is_ok(&status)) goto err; - - wfs->callback(wfs->userdata, frame); - - return CAMU_OK; -err: - camu_codec_frame_discard(frame); - return CAMU_ERR_ERROR; -} - -static void wuffs_decoder_flush(struct camu_decoder *dec) -{ - (void)dec; -} - -static s32 wuffs_decoder_process(struct camu_decoder *dec) -{ - (void)dec; - return CAMU_ERR_EOF; -} - -static void wuffs_decoder_free(struct camu_decoder **dec) -{ - struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)*dec; - al_free(wfs); - *dec = NULL; -} - -struct camu_demuxer *camu_wuffs_demuxer_create(void) -{ - struct camu_wuffs_demuxer *wfs = al_alloc_object(struct camu_wuffs_demuxer); - wfs->demux.mode = CAMU_NORMAL; - al_array_init(wfs->demux.streams); - wfs->demux.init = wuffs_demuxer_init; - wfs->demux.get_packet = wuffs_demuxer_get_packet; - wfs->demux.get_duration = wuffs_demuxer_get_duration; - wfs->demux.seek = wuffs_demuxer_seek; - wfs->demux.free = wuffs_demuxer_free; - return (struct camu_demuxer *)wfs; -} - -struct camu_decoder *camu_wuffs_decoder_create(void) -{ - struct camu_wuffs_decoder *wfs = al_alloc_object(struct camu_wuffs_decoder); - wfs->dec.mode = CAMU_NORMAL; - wfs->dec.init = wuffs_decoder_init; - wfs->dec.push = wuffs_decoder_push; - wfs->dec.process = wuffs_decoder_process; - wfs->dec.flush = wuffs_decoder_flush; - wfs->dec.free = wuffs_decoder_free; - return (struct camu_decoder *)wfs; -} +#include "inc.h" diff --git a/src/codec/wuffs/inc.h b/src/codec/wuffs/inc.h new file mode 100644 index 0000000..51e3743 --- /dev/null +++ b/src/codec/wuffs/inc.h @@ -0,0 +1,12 @@ +#pragma once + +#define WUFFS_CONFIG__MODULES +#define WUFFS_CONFIG__MODULE__BASE +#define WUFFS_CONFIG__MODULE__ADLER32 +#define WUFFS_CONFIG__MODULE__DEFLATE +#define WUFFS_CONFIG__MODULE__ZLIB +#define WUFFS_CONFIG__MODULE__CRC32 +#define WUFFS_CONFIG__MODULE__PNG +#define WUFFS_CONFIG__MODULE__JPEG +#define WUFFS_CONFIG__MODULE__IMAGE +#include <wuffs-unsupported-snapshot.c> diff --git a/src/codec/wuffs/meson.build b/src/codec/wuffs/meson.build index bb5007a..5e5c398 100644 --- a/src/codec/wuffs/meson.build +++ b/src/codec/wuffs/meson.build @@ -1,3 +1,6 @@ wuffs = subproject('wuffs').get_variable('wuffs') -#codec_server_deps += declare_dependency(sources: ['server.c'], dependencies: wuffs) -#codec_client_deps += declare_dependency(sources: ['client.c'], dependencies: wuffs) +wuffs_args = ['-DCAMU_HAVE_WUFFS'] +codec_server_deps += declare_dependency(sources: ['server.c', 'impl.c'], + dependencies: wuffs, compile_args: wuffs_args) +codec_client_deps += declare_dependency(sources: ['client.c', 'impl.c'], + dependencies: wuffs, compile_args: wuffs_args) diff --git a/src/codec/wuffs/server.c b/src/codec/wuffs/server.c new file mode 100644 index 0000000..5e7e885 --- /dev/null +++ b/src/codec/wuffs/server.c @@ -0,0 +1,102 @@ +#include "../../cache/entry.h" + +#include "demuxer.h" +#include "inc.h" + +static bool wuffs_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle) +{ + struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux; + + wfs->handle = handle; + nn_buffer_init(&wfs->buffer); + wfs->eof = false; + + cch_handle_seek(wfs->handle, 0, SEEK_SET); + struct cch_backing *backing = wfs->handle->entry->backing; + off_t size = backing->get_size_if_known(backing); + nn_buffer_ensure_space(&wfs->buffer, size); + cch_handle_read(wfs->handle, nn_buffer_get_ptr(&wfs->buffer, 0), size); + wfs->buffer.size = size; + + wuffs_png__decoder *wf_dec = wuffs_png__decoder__alloc(); + if (!wf_dec) goto err; + + wuffs_png__decoder__set_quirk(wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true); + + wuffs_base__io_buffer src = { 0 }; + src.data.ptr = nn_buffer_get_ptr(&wfs->buffer, 0); + src.data.len = size; + src.meta.wi = size; + src.meta.closed = true; + + wuffs_base__image_config ic = { 0 }; + wuffs_base__status status = wuffs_png__decoder__decode_image_config(wf_dec, &ic, &src); + if (!wuffs_base__status__is_ok(&status)) goto err; + if (!wuffs_base__image_config__is_valid(&ic)) goto err; + + struct camu_codec_stream stream = { 0 }; + stream.mode = CAMU_NORMAL; + stream.type = CAMU_STREAM_VIDEO; + struct camu_video_format *fmt = &stream.video.fmt; + fmt->width = wuffs_base__pixel_config__width(&ic.pixcfg); + fmt->height = wuffs_base__pixel_config__height(&ic.pixcfg); + fmt->format = CAMU_PIXEL_FORMAT_RGBA; + + al_array_push(wfs->demux.streams, stream); + + free(wf_dec); + + return true; +err: + if (wf_dec) free(wf_dec); + + return false; +} + +static s32 wuffs_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet) +{ + struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux; + if (!wfs->eof) { + packet->mode = CAMU_NORMAL; + packet->buffer = &wfs->buffer; + wfs->eof = true; + return CAMU_OK; + } + return CAMU_ERR_EOF; +} + +static u64 wuffs_demuxer_get_duration(struct camu_demuxer *demux) +{ + (void)demux; + return 0; +} + +static bool wuffs_demuxer_seek(struct camu_demuxer *demux, u64 pos, bool bytes) +{ + (void)demux; + (void)pos; + (void)bytes; + return true; +} + +static void wuffs_demuxer_free(struct camu_demuxer **demux) +{ + struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)*demux; + nn_buffer_free(&wfs->buffer); + al_array_free(wfs->demux.streams); + al_free(wfs); + *demux = NULL; +} + +struct camu_demuxer *camu_wuffs_demuxer_create(void) +{ + struct camu_wuffs_demuxer *wfs = al_alloc_object(struct camu_wuffs_demuxer); + wfs->demux.mode = CAMU_NORMAL; + al_array_init(wfs->demux.streams); + wfs->demux.init = wuffs_demuxer_init; + wfs->demux.get_packet = wuffs_demuxer_get_packet; + wfs->demux.get_duration = wuffs_demuxer_get_duration; + wfs->demux.seek = wuffs_demuxer_seek; + wfs->demux.free = wuffs_demuxer_free; + return (struct camu_demuxer *)wfs; +} diff --git a/src/liana/client.c b/src/liana/client.c index 5222d7a..d853acf 100644 --- a/src/liana/client.c +++ b/src/liana/client.c @@ -41,6 +41,10 @@ static void collect_streams(struct lia_client *client, struct nn_packet *packet) for (u32 i = 0; i < count; i++) { // Very important zero-initialization. struct camu_codec_stream stream = { 0 }; + str codec; + nn_packet_read_str(packet, &codec); + // @TODO: NULL unhandled. + stream.codec_info = camu_codec_info_by_name(&codec); u8 mode = nn_packet_read_u8(packet); u8 type = nn_packet_read_u8(packet); u64 duration = nn_packet_read_u64(packet); @@ -125,8 +129,8 @@ static const char *type_to_str[] = { static void parse_info_packet(struct lia_client *client, struct nn_packet *packet) { - str liana; - nn_packet_read_str(packet, &liana); + str handler; + nn_packet_read_str(packet, &handler); client->duration = nn_packet_read_u64(packet); collect_streams(client, packet); struct lia_prefs *prefs = &client->prefs; @@ -146,11 +150,9 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe const AVDictionaryEntry *lang_entry = av_dict_get(metadata, "language", NULL, 0); if (lang_entry && !accept_defaults) { u8 lang = CAMU_LANG_UNKNOWN; - if (strcmp(lang_entry->value, "eng") == 0) { - lang = CAMU_LANG_ENGLISH; - } else if (strcmp(lang_entry->value, "jpn") == 0) { - lang = CAMU_LANG_JAPANESE; - } + str lang_str = al_str_cr(lang_entry->value); + if (al_str_eq(&lang_str, &al_str_c("eng"))) lang = CAMU_LANG_ENGLISH; + else if (al_str_eq(&lang_str, &al_str_c("jpn"))) lang = CAMU_LANG_JAPANESE; switch (stream->type) { case CAMU_STREAM_AUDIO: if (prefs->audio_lang != lang) continue; @@ -173,7 +175,7 @@ static void parse_info_packet(struct lia_client *client, struct nn_packet *packe client->mask |= 1 << stream->index; struct lia_vcr_track *track = al_alloc_object(struct lia_vcr_track); track->stream = stream; - track->client = lia_handler_by_name(&liana)->create_client_handler(); + track->client = lia_handler_by_name(&handler)->create_client_handler(); track->client->callback = client->callback; track->client->userdata = client->userdata; if (!track->client->init(track->client, client->renderer, track->stream)) { diff --git a/src/liana/handlers.h b/src/liana/handlers.h index 223ead5..a72bdb9 100644 --- a/src/liana/handlers.h +++ b/src/liana/handlers.h @@ -1,6 +1,6 @@ #pragma once -#include "handler.h" +#include "handlers/handler.h" struct lia_handler_entry { str name; diff --git a/src/liana/handlers/cdio.h b/src/liana/handlers/cdio.h index 3b0e991..7fa0caf 100644 --- a/src/liana/handlers/cdio.h +++ b/src/liana/handlers/cdio.h @@ -1,6 +1,6 @@ #pragma once -#include "../handler.h" +#include "handler.h" #ifdef LIANA_SERVER struct lia_cdio_server { diff --git a/src/liana/handlers/codec.h b/src/liana/handlers/codec.h index be43f63..f179190 100644 --- a/src/liana/handlers/codec.h +++ b/src/liana/handlers/codec.h @@ -3,7 +3,8 @@ #include "../../codec/codec.h" #include "../server.h" -#include "../handler.h" + +#include "handler.h" // FFmpeg Independence: // - [ ] CAMU_CODEC_* only for explicitly non-ffmpeg codecs. @@ -14,6 +15,7 @@ #ifdef LIANA_SERVER struct lia_codec_server { struct lia_server_handler handler; + struct camu_codec_info *codec_info; struct camu_demuxer *demux; #ifdef LIANA_SERVER_LOOP u64 pts_offset; diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c index 267187f..a3614bf 100644 --- a/src/liana/handlers/codec_client.c +++ b/src/liana/handlers/codec_client.c @@ -1,12 +1,8 @@ #include "../../codec/codec.h" - +#include "../../codec/codecs.h" #ifdef CAMU_HAVE_FFMPEG -#include "../../codec/ffmpeg/decoder.h" #include "../../codec/ffmpeg/packet_ext.h" #endif -#include "../../codec/stb_image/decoder.h" -#include "../../codec/spng/decoder.h" -#include "../../codec/wuffs/decoder.h" #include "../vcr.h" #include "../client.h" @@ -25,10 +21,7 @@ static bool codec_client_init(struct lia_client_handler *handler, struct camu_re struct lia_codec_client *codec = (struct lia_codec_client *)handler; codec->handler.stream = stream; if (stream->type == CAMU_STREAM_AUDIO || stream->type == CAMU_STREAM_VIDEO) { - codec->dec = camu_ff_decoder_create(); - //codec->dec = camu_stbi_decoder_create(); - //codec->dec = camu_spng_decoder_create(); - //codec->dec = camu_wuffs_decoder_create(); + codec->dec = stream->codec_info->create_decoder(); if (!codec->dec->init(codec->dec, renderer, stream, data_callback, codec)) { return false; } diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c index c324481..801a3e1 100644 --- a/src/liana/handlers/codec_server.c +++ b/src/liana/handlers/codec_server.c @@ -1,15 +1,12 @@ -#include "../../codec/codec.h" -#include "../../server/common.h" +#define AL_LOG_SECTION "codec_server" +#include <al/log.h> +#include "../../server/common.h" +#include "../../codec/codec.h" +#include "../../codec/codecs.h" #ifdef CAMU_HAVE_FFMPEG -#include "../../codec/ffmpeg/demuxer.h" #include "../../codec/ffmpeg/packet_ext.h" #endif -#include "../../codec/stb_image/demuxer.h" -#include "../../codec/spng/demuxer.h" -#include "../../codec/wuffs/demuxer.h" - -#include "../handler.h" #include "codec.h" @@ -17,11 +14,13 @@ static bool codec_server_init(struct lia_server_handler *handler, struct cch_han { struct lia_codec_server *codec = (struct lia_codec_server *)handler; - codec->demux = camu_ff_demuxer_create(); - //codec->demux = camu_stbi_demuxer_create(); - //codec->demux = camu_spng_demuxer_create(); - //codec->demux = camu_wuffs_demuxer_create(); - + codec->demux = NULL; + codec->codec_info = camu_codec_info_by_type(cch_entry_guess_format(handle->entry)); + if (!codec->codec_info) { + return false; + } + log_info("Selected demuxer: %.*s.", al_str_x(&codec->codec_info->name)); + codec->demux = codec->codec_info->create_demuxer(); if (!codec->demux->init(codec->demux, handle)) { return false; } @@ -55,6 +54,7 @@ static void codec_server_write_info(struct lia_server_handler *handler, struct n nn_packet_write_u32(packet, codec->demux->streams.count); struct camu_codec_stream *stream; al_array_foreach_ptr(codec->demux->streams, i, stream) { + nn_packet_write_str(packet, &codec->codec_info->name); nn_packet_write_u8(packet, stream->mode); nn_packet_write_u8(packet, stream->type); nn_packet_write_u64(packet, stream->duration); @@ -159,18 +159,20 @@ static void codec_server_write_packet(struct lia_server_handler *handler, struct static void codec_server_free(struct lia_server_handler **handler) { struct lia_codec_server *codec = (struct lia_codec_server *)*handler; - switch (codec->demux->mode) { - case CAMU_NORMAL: - break; + if (codec->demux) { + switch (codec->demux->mode) { + case CAMU_NORMAL: + break; #ifdef CAMU_HAVE_FFMPEG - case CAMU_FFMPEG_COMPAT: + case CAMU_FFMPEG_COMPAT: #ifndef CAMU_DIRECT_MODE - av_packet_free(&codec->packet.av.pkt); + av_packet_free(&codec->packet.av.pkt); #endif - break; + break; #endif + } + codec->demux->free(&codec->demux); } - codec->demux->free(&codec->demux); al_free(codec); *handler = NULL; } diff --git a/src/liana/handlers/dvd.h b/src/liana/handlers/dvd.h index dd5ac0a..c0f0544 100644 --- a/src/liana/handlers/dvd.h +++ b/src/liana/handlers/dvd.h @@ -1,6 +1,6 @@ #pragma once -#include "../handler.h" +#include "handler.h" #ifdef LIANA_SERVER #include <dvdnav/dvdnav.h> diff --git a/src/liana/handler.h b/src/liana/handlers/handler.h index 1fa77a0..48fcef3 100644 --- a/src/liana/handler.h +++ b/src/liana/handlers/handler.h @@ -1,9 +1,9 @@ #pragma once -#include <nnwt/packet_pool.h> +#include <nnwt/packet.h> -#include "../codec/codec.h" -#include "../cache/handle.h" +#include "../../cache/handle.h" +#include "../../codec/codec.h" enum { LIANA_PACKET_DATA = 0, diff --git a/src/liana/server.c b/src/liana/server.c index d07cb8d..db61e20 100644 --- a/src/liana/server.c +++ b/src/liana/server.c @@ -1,5 +1,4 @@ #include "server.h" -#include "handler.h" #include "handlers.h" #include "list.h" @@ -217,7 +216,7 @@ static void handle_connection(struct lia_node_connection *conn, struct nn_packet if (mask == 0) { struct nn_packet *rpacket = nn_packet_create(); nn_packet_write_u32(rpacket, conn->id); - nn_packet_write_str(rpacket, cch_entry_get_liana(conn->node->entry)); + nn_packet_write_str(rpacket, cch_entry_get_handler(conn->node->entry)); conn->handler->write_info(conn->handler, rpacket); stream->packet_callback = subscribe_packet_callback; stream->packet_sent_callback = subscribe_packet_sent_callback; @@ -363,7 +362,7 @@ static void packet_callback(void *userdata, struct nn_packet_stream *stream, str nn_signal_init(&conn->signal, server->loop, signal_callback, conn); nn_signal_start(&conn->signal); cch_entry_get_handle(node->entry, &conn->handle); - conn->handler = lia_handler_by_name(cch_entry_get_liana(node->entry))->create_server_handler(); + conn->handler = lia_handler_by_name(cch_entry_get_handler(node->entry))->create_server_handler(); conn->errored = false; conn->disconnected = false; conn->ref = false; @@ -468,7 +467,7 @@ void lia_node_get_duration(struct lia_node *node) nn_signal_init(&node->signal, node->server->loop, duration_signal_callback, node); nn_signal_start(&node->signal); cch_entry_get_handle(node->entry, &node->handle); - node->handler = lia_handler_by_name(cch_entry_get_liana(node->entry))->create_server_handler(); + node->handler = lia_handler_by_name(cch_entry_get_handler(node->entry))->create_server_handler(); nn_thread_create(&node->thread, init_duration_thread, node); } diff --git a/src/liana/vcr.c b/src/liana/vcr.c index 518311a..d2c6b33 100644 --- a/src/liana/vcr.c +++ b/src/liana/vcr.c @@ -1,8 +1,9 @@ #define AL_LOG_SECTION "vcr" #include <al/log.h> +#include "handlers/handler.h" + #include "vcr.h" -#include "handler.h" #define VCR_BUFFER_BUFFERED MB(2) diff --git a/src/libsink/sink.c b/src/libsink/sink.c index 2bcc943..ff91a51 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -1548,7 +1548,7 @@ static void identify_callback(void *userdata, struct nn_rpc_connection *conn, st } #else (void)sink; - log_info("Sink locally bridged to server."); + log_info("Sink directly bridged to server."); #endif nn_packet_stream_return_packet(conn->stream, packet); } diff --git a/src/portal/py/modules/youtube.py b/src/portal/py/modules/youtube.py index 77e17b3..9783127 100644 --- a/src/portal/py/modules/youtube.py +++ b/src/portal/py/modules/youtube.py @@ -28,7 +28,8 @@ ydl_opts = { 'logger': YDLLogger(), 'cachedir': False, 'socket_timeout': 10, - 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['tv', 'ios']}} # 'android_vr', + 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['android_vr']}} +# 'extractor_args': {'youtube': {'skip': ['hls'], 'player_client': ['tv', 'ios']}} # 'cookiefile': '' } diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c index 1864607..01cd366 100644 --- a/src/render/queue_libplacebo.c +++ b/src/render/queue_libplacebo.c @@ -62,7 +62,7 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src masks[3] = 0xff000000; pixel_stride = 4; break; - case CAMU_PIXEL_FORMAT_RGB8: + case CAMU_PIXEL_FORMAT_RGB24: masks[0] = 0x000000ff; masks[1] = 0x0000ff00; masks[2] = 0x00ff0000; diff --git a/src/render/renderer.h b/src/render/renderer.h index 8e80696..bbb7b70 100644 --- a/src/render/renderer.h +++ b/src/render/renderer.h @@ -38,6 +38,7 @@ struct camu_renderer { #if defined STELA_API_VULKAN VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *), VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *), + VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR), const char *const *(*vk_get_extensions)(u32 *), #elif defined STELA_API_DX11 HWND win32_window, diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c index c5f4de8..cdf09bf 100644 --- a/src/render/renderer_libplacebo.c +++ b/src/render/renderer_libplacebo.c @@ -119,6 +119,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid #if defined STELA_API_VULKAN VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *), VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *), + VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR), const char *const *(*vk_get_extensions)(u32 *), #elif defined STELA_API_DX11 HWND win32_window, @@ -159,7 +160,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid )); #if defined STELA_API_VULKAN - VkResult err; + lr->vk_destroy_surface = vk_destroy_surface; u32 num; const char *const *extensions = vk_get_extensions(&num); @@ -174,8 +175,8 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid goto err; } - err = vk_create_surface(priv, lr->vk_inst->instance, &lr->surface); - if (err != VK_SUCCESS) { + VkResult ret = vk_create_surface(priv, lr->vk_inst->instance, &lr->surface); + if (ret != VK_SUCCESS) { log_error("Failed to create vulkan surface."); goto err; } @@ -333,6 +334,7 @@ static struct camu_frame_queue *renderer_lp_create_queue(struct camu_renderer *r static void renderer_lp_add_font(struct camu_renderer *renderer, struct camu_codec_stream *attachment) { struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer; + // @TODO: No FFmpeg + HAVE_SUBTITLES (no usecase yet). #ifdef CAMU_HAVE_SUBTITLES AVStream *stream = attachment->av.stream; AVDictionaryEntry *entry = av_dict_get(stream->metadata, "filename", NULL, 0); @@ -463,7 +465,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree } if (!pl_swapchain_submit_frame(lr->swapchain)) { - log_error("Failed to submit frame, likely fatal."); + log_error("Failed to submit frame, possibly fatal."); } lr->have_frame = false; @@ -490,6 +492,11 @@ void renderer_lp_free(struct camu_renderer **renderer) if (lr->renderer) pl_renderer_destroy(&lr->renderer); if (lr->swapchain) pl_swapchain_destroy(&lr->swapchain); #if defined STELA_API_VULKAN + if (lr->vk) pl_vulkan_destroy(&lr->vk); + lr->vk_destroy_surface(lr->vk_inst->instance, lr->surface); + if (lr->vk_inst) pl_vk_inst_destroy(&lr->vk_inst); +#elif defined STELA_API_DX11 + if (lr->d3d11) pl_d3d11_destroy(&lr->d3d11); #elif defined STELA_API_OPENGL if (lr->gl) pl_opengl_destroy(&lr->gl); #endif diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h index c8962d2..fd34f7a 100644 --- a/src/render/renderer_libplacebo.h +++ b/src/render/renderer_libplacebo.h @@ -24,6 +24,7 @@ struct camu_renderer_lp { VkSurfaceKHR surface; pl_vulkan vk; pl_vk_inst vk_inst; + VkResult (*vk_destroy_surface)(VkInstance, VkSurfaceKHR); #elif defined STELA_API_DX11 pl_d3d11 d3d11; #elif defined STELA_API_OPENGL diff --git a/src/screen/screen.c b/src/screen/screen.c index bed1a26..d0d78e2 100644 --- a/src/screen/screen.c +++ b/src/screen/screen.c @@ -517,6 +517,7 @@ bool camu_screen_create_renderer(struct camu_screen *scr, struct camu_renderer * #if defined STELA_API_VULKAN scr->window->get_vk_proc_address, scr->window->vk_create_surface, + scr->window->vk_destroy_surface, scr->window->vk_get_extensions, #elif defined STELA_API_DX11 scr->window->win32_window, |