summaryrefslogtreecommitdiff
path: root/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/codec.h17
-rw-r--r--src/codec/ffmpeg/decoder.c8
-rw-r--r--src/codec/ffmpeg/meson.build70
-rw-r--r--src/codec/meson.build79
-rw-r--r--src/codec/spng/client.c77
-rw-r--r--src/codec/spng/impl.c164
-rw-r--r--src/codec/spng/meson.build3
-rw-r--r--src/codec/spng/server.c90
-rw-r--r--src/codec/stb_image/client.c71
-rw-r--r--src/codec/stb_image/impl.c161
-rw-r--r--src/codec/stb_image/meson.build3
-rw-r--r--src/codec/stb_image/server.c87
-rw-r--r--src/codec/wuffs/meson.build3
13 files changed, 430 insertions, 403 deletions
diff --git a/src/codec/codec.h b/src/codec/codec.h
index b70e3cb..af824d7 100644
--- a/src/codec/codec.h
+++ b/src/codec/codec.h
@@ -9,12 +9,6 @@
#include "../cache/handle.h"
-#ifndef CAMU_SINK_NO_VIDEO
-#include "../render/renderer.h"
-#else
-struct camu_renderer;
-#endif
-
#ifdef CAMU_HAVE_FFMPEG
enum {
CAMU_OK = 0,
@@ -22,9 +16,11 @@ enum {
CAMU_ERR_EOF = AVERROR_EOF,
CAMU_ERR_AGAIN = AVERROR(EAGAIN)
};
+
enum {
CAMU_SEEK_SIZE = AVSEEK_SIZE
};
+
enum {
CAMU_STREAM_UNKNOWN = AVMEDIA_TYPE_UNKNOWN,
CAMU_STREAM_AUDIO = AVMEDIA_TYPE_AUDIO, // 1
@@ -32,6 +28,7 @@ enum {
CAMU_STREAM_SUBTITLE = AVMEDIA_TYPE_SUBTITLE,
CAMU_STREAM_ATTACHMENT = AVMEDIA_TYPE_ATTACHMENT
};
+
enum {
CAMU_SAMPLE_FORMAT_NONE = AV_SAMPLE_FMT_NONE,
CAMU_SAMPLE_FORMAT_U8 = AV_SAMPLE_FMT_U8,
@@ -47,12 +44,14 @@ enum {
CAMU_SAMPLE_FORMAT_S64 = AV_SAMPLE_FMT_S64,
CAMU_SAMPLE_FORMAT_S64P = AV_SAMPLE_FMT_S64P
};
+
enum {
CAMU_PIXEL_FORMAT_RGBA = AV_PIX_FMT_RGBA,
CAMU_PIXEL_FORMAT_RGB = AV_PIX_FMT_RGB8,
CAMU_PIXEL_FORMAT_GREYA = AV_PIX_FMT_GRAY8A,
CAMU_PIXEL_FORMAT_GREY = AV_PIX_FMT_GRAY8
};
+
#define CAMU_PLANAR_DATA_POINTERS AV_NUM_DATA_POINTERS
#else
enum {
@@ -61,9 +60,11 @@ enum {
CAMU_ERR_EOF = -1,
CAMU_ERR_AGAIN = -2
};
+
enum {
CAMU_SEEK_SIZE = 0x10000
};
+
enum {
CAMU_STREAM_UNKNOWN = -1,
CAMU_STREAM_AUDIO,
@@ -71,6 +72,7 @@ enum {
CAMU_STREAM_SUBTITLE,
CAMU_STREAM_ATTACHMENT
};
+
enum {
CAMU_SAMPLE_FORMAT_NONE = -1,
CAMU_SAMPLE_FORMAT_U8,
@@ -86,12 +88,14 @@ enum {
CAMU_SAMPLE_FORMAT_S64,
CAMU_SAMPLE_FORMAT_S64P
};
+
enum {
CAMU_PIXEL_FORMAT_RGBA = 0,
CAMU_PIXEL_FORMAT_RGB,
CAMU_PIXEL_FORMAT_GREYA,
CAMU_PIXEL_FORMAT_GREY
};
+
#define CAMU_PLANAR_DATA_POINTERS 8
#endif
@@ -176,6 +180,7 @@ struct camu_demuxer {
s32 subscribed;
};
+struct camu_renderer;
struct camu_decoder {
u8 mode;
bool (*init)(struct camu_decoder *, struct camu_renderer *, struct camu_codec_stream *,
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index 36e59dd..5ff99d7 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -2,9 +2,13 @@
#include <al/log.h>
#include <libavutil/cpu.h>
+#ifndef CAMU_SINK_NO_VIDEO
+#include "../../render/renderer.h"
+#endif
+
#include "decoder.h"
-#if !defined CAMU_SINK_NO_VIDEO
+#ifndef CAMU_SINK_NO_VIDEO
static s32 get_buffer2(AVCodecContext *context, AVFrame *pic, s32 flags)
{
struct camu_ff_decoder *av = (struct camu_ff_decoder *)context->opaque;
@@ -236,7 +240,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
}
#endif
-#if !defined CAMU_SINK_NO_VIDEO
+#ifndef CAMU_SINK_NO_VIDEO
if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO && renderer && renderer->get_buffer2) {
av->renderer = renderer;
av->codec_context->opaque = av;
diff --git a/src/codec/ffmpeg/meson.build b/src/codec/ffmpeg/meson.build
new file mode 100644
index 0000000..fc0bc91
--- /dev/null
+++ b/src/codec/ffmpeg/meson.build
@@ -0,0 +1,70 @@
+ffmpeg_src = [
+ 'common.c',
+ 'packet_ext.c',
+]
+ffmpeg_args = ['-DCAMU_HAVE_FFMPEG']
+ffmpeg_deps = []
+
+ffmpeg_server_src = [
+ ffmpeg_src,
+ 'demuxer.c',
+ 'avio.c'
+]
+ffmpeg_server_deps = []
+
+# This is layed out based on how things work currently.
+# Obviously the decoder, resampler, scaler, and encoder should
+# be a part of a server-side transcoding function.
+ffmpeg_client_src = [
+ ffmpeg_src,
+ 'decoder.c',
+ 'resampler.c',
+ 'scaler.c',
+ 'encoder.c'
+]
+ffmpeg_client_deps = []
+
+libavutil = dependency('libavutil', required: false)
+libavformat = dependency('libavformat', required: false)
+libavcodec = dependency('libavcodec', required: false)
+libswresample = dependency('libswresample', required: false)
+libswscale = dependency('libswscale', required: false)
+if not (libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found())
+ ffmpeg_proj = subproject('ffmpeg', required: false)
+ if ffmpeg_proj.found()
+ libavutil = ffmpeg_proj.get_variable('avutil')
+ libavformat = ffmpeg_proj.get_variable('avformat')
+ libavcodec = ffmpeg_proj.get_variable('avcodec')
+ libswresample = ffmpeg_proj.get_variable('swresample')
+ libswscale = ffmpeg_proj.get_variable('swscale')
+ # Only used to set include dirs for FFmpeg.
+ ffmpeg_deps += [ffmpeg_proj.get_variable('ffmpeg_inc_dep')]
+ # We explicitly enable zlib in the FFmpeg build.
+ ffmpeg_deps += [dependency('zlib')]
+ if is_windows
+ # Extra static dependencies for Windows.
+ ffmpeg_client_deps += [compiler.find_library('bcrypt')]
+ elif is_android
+ # Android MediaCodec HW decoding.
+ ffmpeg_client_deps += [compiler.find_library('mediandk')]
+ endif
+ soxr = compiler.find_library('soxr', required: false)
+ if soxr.found()
+ ffmpeg_client_deps += [soxr]
+ ffmpeg_args += ['-DCAMU_HAVE_SOXR']
+ endif
+ endif
+endif
+
+if libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found()
+ ffmpeg_server_deps += [libavutil, libavformat, libavcodec]
+ ffmpeg_client_deps += [libavutil, libavformat, libavcodec, libswresample, libswscale]
+ codec_server_deps += [
+ declare_dependency(sources: ffmpeg_server_src,
+ dependencies: [ffmpeg_deps, ffmpeg_server_deps], compile_args: ffmpeg_args)
+ ]
+ codec_client_deps += [
+ declare_dependency(sources: ffmpeg_client_src,
+ dependencies: [ffmpeg_deps, ffmpeg_client_deps], compile_args: ffmpeg_args)
+ ]
+endif
diff --git a/src/codec/meson.build b/src/codec/meson.build
index 2e89d95..4c9e16b 100644
--- a/src/codec/meson.build
+++ b/src/codec/meson.build
@@ -1,86 +1,25 @@
-codec_deps = []
+codec_server_deps = []
+codec_client_deps = []
if get_option('codecs').contains('ffmpeg')
- ffmpeg_src = [
- 'ffmpeg/common.c',
- 'ffmpeg/packet_ext.c',
- 'ffmpeg/decoder.c',
- 'ffmpeg/resampler.c',
- 'ffmpeg/scaler.c',
- 'ffmpeg/encoder.c',
- ]
- if not get_option('sink-only')
- ffmpeg_src += [
- 'ffmpeg/demuxer.c',
- 'ffmpeg/avio.c'
- ]
- endif
- ffmpeg_inc = []
- ffmpeg_deps = []
- ffmpeg_args = []
-
- libavutil = dependency('libavutil', required: false)
- libavformat = dependency('libavformat', required: false)
- libavcodec = dependency('libavcodec', required: false)
- libswresample = dependency('libswresample', required: false)
- libswscale = dependency('libswscale', required: false)
- if not (libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found())
- ffmpeg_proj = subproject('ffmpeg', required: false)
- if ffmpeg_proj.found()
- libavutil = ffmpeg_proj.get_variable('avutil')
- libavformat = ffmpeg_proj.get_variable('avformat')
- libavcodec = ffmpeg_proj.get_variable('avcodec')
- libswresample = ffmpeg_proj.get_variable('swresample')
- libswscale = ffmpeg_proj.get_variable('swscale')
- # Only used to set include dirs for FFmpeg.
- ffmpeg_deps += [ffmpeg_proj.get_variable('ffmpeg_inc_dep')]
- # We explicitly enable zlib in the FFmpeg build.
- ffmpeg_deps += [dependency('zlib')]
- if is_windows
- # Extra static dependencies for Windows.
- ffmpeg_deps += [compiler.find_library('bcrypt')]
- elif is_android
- ffmpeg_deps += [compiler.find_library('mediandk')]
- endif
- soxr = compiler.find_library('soxr', required: false)
- if soxr.found()
- ffmpeg_deps += [soxr]
- ffmpeg_args += ['-DCAMU_HAVE_SOXR']
- endif
- endif
- endif
-
- if libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found()
- ffmpeg_deps += [libavutil, libavformat, libavcodec, libswresample, libswscale]
- ffmpeg_args += ['-DCAMU_HAVE_FFMPEG']
- ffmpeg_codec = declare_dependency(sources: ffmpeg_src, dependencies: ffmpeg_deps,
- include_directories: ffmpeg_inc, compile_args: ffmpeg_args)
- codec_deps += [ffmpeg_codec]
- endif
+ subdir('ffmpeg')
endif
if get_option('codecs').contains('stb_image')
- stb = subproject('stb').get_variable('stb')
- stb_image_codec = declare_dependency(sources: ['stb_image/impl.c'], dependencies: stb)
- codec_deps += [stb_image_codec]
+ subdir('stb_image')
endif
if get_option('codecs').contains('spng')
- spng = dependency('spng', required: false)
- if spng.found()
- spng_codec = declare_dependency(sources: ['spng/impl.c'], dependencies: spng)
- codec_deps += [spng_codec]
- endif
+ subdir('spng')
endif
if get_option('codecs').contains('wuffs')
- wuffs = subproject('wuffs').get_variable('wuffs')
- wuffs_codec = declare_dependency(sources: ['wuffs/impl.c'], dependencies: wuffs)
- codec_deps += [wuffs_codec]
+ subdir('wuffs')
endif
if not no_video
- codec_deps += [stela]
+ codec_client_deps += [stela]
endif
-codecs = declare_dependency(dependencies: codec_deps)
+codecs_server = declare_dependency(dependencies: codec_server_deps)
+codecs_client = declare_dependency(dependencies: codec_client_deps)
diff --git a/src/codec/spng/client.c b/src/codec/spng/client.c
new file mode 100644
index 0000000..6edb9c9
--- /dev/null
+++ b/src/codec/spng/client.c
@@ -0,0 +1,77 @@
+#include <spng.h>
+
+#include "../common.h"
+
+#include "decoder.h"
+
+static bool spng_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_spng_decoder *spng = (struct camu_spng_decoder *)dec;
+ (void)renderer;
+ spng->stream = stream;
+ spng->callback = callback;
+ spng->userdata = userdata;
+ return true;
+}
+
+static s32 spng_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet)
+{
+ struct camu_spng_decoder *spng = (struct camu_spng_decoder *)dec;
+ if (!packet) return CAMU_OK;
+
+ spng_ctx *ctx = spng_ctx_new(SPNG_CTX_IGNORE_ADLER32);
+ spng_set_png_buffer(ctx, nn_buffer_get_ptr(packet->buffer, 0), packet->buffer->size);
+ spng_set_option(ctx, SPNG_CHUNK_COUNT_LIMIT, 6250);
+ spng_set_crc_action(ctx, SPNG_CRC_DISCARD, SPNG_CRC_DISCARD);
+
+ size_t out_size;
+ spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size);
+
+ struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
+ frame->mode = CAMU_NORMAL;
+ frame->data = camu_page_alloc(out_size);
+ spng_decode_chunks(ctx);
+ spng_decode_image(ctx, frame->data, out_size, SPNG_FMT_RGBA8, 0);
+ spng_ctx_free(ctx);
+ frame->flags = 0;
+ frame->format = CAMU_PIXEL_FORMAT_RGBA;
+ struct camu_video_format *fmt = &spng->stream->video.fmt;
+ frame->video.width = fmt->width;
+ frame->video.height = fmt->height;
+ frame->pts = 0.0;
+
+ spng->callback(spng->userdata, frame);
+
+ return CAMU_OK;
+}
+
+static void spng_decoder_flush(struct camu_decoder *dec)
+{
+ (void)dec;
+}
+
+static s32 spng_decoder_process(struct camu_decoder *dec)
+{
+ (void)dec;
+ return CAMU_ERR_EOF;
+}
+
+static void spng_decoder_free(struct camu_decoder **dec)
+{
+ struct camu_spng_decoder *spng = (struct camu_spng_decoder *)*dec;
+ al_free(spng);
+ *dec = NULL;
+}
+
+struct camu_decoder *camu_spng_decoder_create(void)
+{
+ struct camu_spng_decoder *spng = al_alloc_object(struct camu_spng_decoder);
+ spng->dec.mode = CAMU_NORMAL;
+ spng->dec.init = spng_decoder_init;
+ spng->dec.push = spng_decoder_push;
+ spng->dec.process = spng_decoder_process;
+ spng->dec.flush = spng_decoder_flush;
+ spng->dec.free = spng_decoder_free;
+ return (struct camu_decoder *)spng;
+}
diff --git a/src/codec/spng/impl.c b/src/codec/spng/impl.c
index 3fb7e21..e69de29 100644
--- a/src/codec/spng/impl.c
+++ b/src/codec/spng/impl.c
@@ -1,164 +0,0 @@
-#include <al/lib.h>
-#include <nnwt/common.h>
-#include <spng.h>
-
-#include "../../cache/entry.h"
-
-#include "../common.h"
-
-#include "demuxer.h"
-#include "decoder.h"
-
-static bool spng_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle)
-{
- struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)demux;
-
- spng->handle = handle;
- nn_buffer_init(&spng->buffer);
- spng->eof = false;
-
- cch_handle_seek(spng->handle, 0, SEEK_SET);
- off_t size = cch_entry_get_size(spng->handle->entry);
- nn_buffer_ensure_space(&spng->buffer, size);
- cch_handle_read(spng->handle, nn_buffer_get_ptr(&spng->buffer, 0), size);
- spng->buffer.size = size;
-
- spng_ctx *ctx = spng_ctx_new(SPNG_CTX_IGNORE_ADLER32);
- spng_set_png_buffer(ctx, nn_buffer_get_ptr(&spng->buffer, 0), spng->buffer.size);
- spng_set_option(ctx, SPNG_CHUNK_COUNT_LIMIT, 6250);
- spng_set_crc_action(ctx, SPNG_CRC_DISCARD, SPNG_CRC_DISCARD);
-
- struct spng_ihdr ihdr;
- spng_get_ihdr(ctx, &ihdr);
-
- struct camu_codec_stream stream;
- stream.mode = CAMU_NORMAL;
- stream.type = CAMU_STREAM_VIDEO;
- stream.video.width = ihdr.width;
- stream.video.height = ihdr.height;
- stream.video.format = CAMU_PIXEL_FORMAT_RGBA;
-
- al_array_push(spng->demux.streams, stream);
-
- spng_ctx_free(ctx);
-
- return true;
-}
-
-static s32 spng_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet)
-{
- struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)demux;
- if (!spng->eof) {
- packet->mode = CAMU_NORMAL;
- packet->buffer = &spng->buffer;
- spng->eof = true;
- return CAMU_OK;
- }
- return CAMU_ERR_EOF;
-}
-
-static u64 spng_demuxer_get_duration(struct camu_demuxer *demux)
-{
- (void)demux;
- return 0;
-}
-
-static bool spng_demuxer_seek(struct camu_demuxer *demux, u64 pos)
-{
- (void)demux;
- (void)pos;
- return true;
-}
-
-static void spng_demuxer_free(struct camu_demuxer **demux)
-{
- struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)*demux;
- nn_buffer_free(&spng->buffer);
- al_array_free(spng->demux.streams);
- al_free(spng);
- *demux = NULL;
-}
-
-static bool spng_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_spng_decoder *spng = (struct camu_spng_decoder *)dec;
- (void)renderer;
- spng->stream = stream;
- spng->callback = callback;
- spng->userdata = userdata;
- return true;
-}
-
-static s32 spng_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet)
-{
- struct camu_spng_decoder *spng = (struct camu_spng_decoder *)dec;
- if (!packet) return CAMU_OK;
-
- spng_ctx *ctx = spng_ctx_new(SPNG_CTX_IGNORE_ADLER32);
- spng_set_png_buffer(ctx, nn_buffer_get_ptr(packet->buffer, 0), packet->buffer->size);
- spng_set_option(ctx, SPNG_CHUNK_COUNT_LIMIT, 6250);
- spng_set_crc_action(ctx, SPNG_CRC_DISCARD, SPNG_CRC_DISCARD);
-
- size_t out_size;
- spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size);
-
- struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
- frame->mode = CAMU_NORMAL;
- frame->data = camu_page_alloc(out_size);
- spng_decode_chunks(ctx);
- spng_decode_image(ctx, frame->data, out_size, SPNG_FMT_RGBA8, 0);
- spng_ctx_free(ctx);
- frame->flags = 0;
- frame->format = CAMU_PIXEL_FORMAT_RGBA;
- frame->width = spng->stream->video.width;
- frame->height = spng->stream->video.height;
- frame->pts = 0.0;
-
- spng->callback(spng->userdata, frame);
-
- return CAMU_OK;
-}
-
-static void spng_decoder_flush(struct camu_decoder *dec)
-{
- (void)dec;
-}
-
-static s32 spng_decoder_process(struct camu_decoder *dec)
-{
- (void)dec;
- return CAMU_ERR_EOF;
-}
-
-static void spng_decoder_free(struct camu_decoder **dec)
-{
- struct camu_spng_decoder *spng = (struct camu_spng_decoder *)*dec;
- al_free(spng);
- *dec = NULL;
-}
-
-struct camu_demuxer *camu_spng_demuxer_create(void)
-{
- struct camu_spng_demuxer *spng = al_alloc_object(struct camu_spng_demuxer);
- spng->demux.mode = CAMU_NORMAL;
- al_array_init(spng->demux.streams);
- spng->demux.init = spng_demuxer_init;
- spng->demux.get_packet = spng_demuxer_get_packet;
- spng->demux.get_duration = spng_demuxer_get_duration;
- spng->demux.seek = spng_demuxer_seek;
- spng->demux.free = spng_demuxer_free;
- return (struct camu_demuxer *)spng;
-}
-
-struct camu_decoder *camu_spng_decoder_create(void)
-{
- struct camu_spng_decoder *spng = al_alloc_object(struct camu_spng_decoder);
- spng->dec.mode = CAMU_NORMAL;
- spng->dec.init = spng_decoder_init;
- spng->dec.push = spng_decoder_push;
- spng->dec.process = spng_decoder_process;
- spng->dec.flush = spng_decoder_flush;
- spng->dec.free = spng_decoder_free;
- return (struct camu_decoder *)spng;
-}
diff --git a/src/codec/spng/meson.build b/src/codec/spng/meson.build
new file mode 100644
index 0000000..d8af781
--- /dev/null
+++ b/src/codec/spng/meson.build
@@ -0,0 +1,3 @@
+spng = dependency('spng')
+codec_server_deps += [declare_dependency(sources: ['server.c'], dependencies: spng)]
+codec_client_deps += [declare_dependency(sources: ['client.c'], dependencies: spng)]
diff --git a/src/codec/spng/server.c b/src/codec/spng/server.c
new file mode 100644
index 0000000..8eb941b
--- /dev/null
+++ b/src/codec/spng/server.c
@@ -0,0 +1,90 @@
+#include <spng.h>
+
+#include "../../cache/entry.h"
+
+#include "demuxer.h"
+
+static bool spng_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle)
+{
+ struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)demux;
+
+ spng->handle = handle;
+ nn_buffer_init(&spng->buffer);
+ spng->eof = false;
+
+ cch_handle_seek(spng->handle, 0, SEEK_SET);
+ off_t size = cch_entry_get_size(spng->handle->entry);
+ nn_buffer_ensure_space(&spng->buffer, size);
+ cch_handle_read(spng->handle, nn_buffer_get_ptr(&spng->buffer, 0), size);
+ spng->buffer.size = size;
+
+ spng_ctx *ctx = spng_ctx_new(SPNG_CTX_IGNORE_ADLER32);
+ spng_set_png_buffer(ctx, nn_buffer_get_ptr(&spng->buffer, 0), spng->buffer.size);
+ spng_set_option(ctx, SPNG_CHUNK_COUNT_LIMIT, 6250);
+ spng_set_crc_action(ctx, SPNG_CRC_DISCARD, SPNG_CRC_DISCARD);
+
+ struct spng_ihdr ihdr;
+ spng_get_ihdr(ctx, &ihdr);
+
+ 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 = ihdr.width;
+ fmt->height = ihdr.height;
+ fmt->format = CAMU_PIXEL_FORMAT_RGBA;
+
+ al_array_push(spng->demux.streams, stream);
+
+ spng_ctx_free(ctx);
+
+ return true;
+}
+
+static s32 spng_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet)
+{
+ struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)demux;
+ if (!spng->eof) {
+ packet->mode = CAMU_NORMAL;
+ packet->buffer = &spng->buffer;
+ spng->eof = true;
+ return CAMU_OK;
+ }
+ return CAMU_ERR_EOF;
+}
+
+static u64 spng_demuxer_get_duration(struct camu_demuxer *demux)
+{
+ (void)demux;
+ return 0;
+}
+
+static bool spng_demuxer_seek(struct camu_demuxer *demux, u64 pos)
+{
+ (void)demux;
+ (void)pos;
+ return true;
+}
+
+static void spng_demuxer_free(struct camu_demuxer **demux)
+{
+ struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)*demux;
+ nn_buffer_free(&spng->buffer);
+ al_array_free(spng->demux.streams);
+ al_free(spng);
+ *demux = NULL;
+}
+
+
+struct camu_demuxer *camu_spng_demuxer_create(void)
+{
+ struct camu_spng_demuxer *spng = al_alloc_object(struct camu_spng_demuxer);
+ spng->demux.mode = CAMU_NORMAL;
+ al_array_init(spng->demux.streams);
+ spng->demux.init = spng_demuxer_init;
+ spng->demux.get_packet = spng_demuxer_get_packet;
+ spng->demux.get_duration = spng_demuxer_get_duration;
+ spng->demux.seek = spng_demuxer_seek;
+ spng->demux.free = spng_demuxer_free;
+ return (struct camu_demuxer *)spng;
+}
diff --git a/src/codec/stb_image/client.c b/src/codec/stb_image/client.c
new file mode 100644
index 0000000..3742def
--- /dev/null
+++ b/src/codec/stb_image/client.c
@@ -0,0 +1,71 @@
+#include <stb_image.h>
+
+#include "decoder.h"
+
+static bool stbi_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_stbi_decoder *stb = (struct camu_stbi_decoder *)dec;
+ (void)renderer;
+ stb->stream = stream;
+ stb->callback = callback;
+ stb->userdata = userdata;
+ return true;
+}
+
+static s32 stbi_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet)
+{
+ struct camu_stbi_decoder *stb = (struct camu_stbi_decoder *)dec;
+ if (!packet) return CAMU_OK;
+
+ s32 w, h, channels;
+ u8 *data = nn_buffer_get_ptr(packet->buffer, 0);
+ u8 *pixels = stbi_load_from_memory(data, packet->buffer->size, &w, &h, &channels, 0);
+ if (!pixels) return CAMU_ERR_ERROR;
+ struct camu_video_format *fmt = &stb->stream->video.fmt;
+ al_assert(w == fmt->width && h == fmt->height);
+
+ struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
+ frame->mode = CAMU_NORMAL;
+ frame->flags = 0;
+ frame->data = pixels;
+ frame->video.width = w;
+ frame->video.height = h;
+ frame->format = camu_pixel_format_from_channels(channels);
+ al_assert(frame->format == fmt->format);
+ frame->pts = 0.0;
+
+ stb->callback(stb->userdata, frame);
+
+ return CAMU_OK;
+}
+
+static void stbi_decoder_flush(struct camu_decoder *dec)
+{
+ (void)dec;
+}
+
+static s32 stbi_decoder_process(struct camu_decoder *dec)
+{
+ (void)dec;
+ return CAMU_ERR_EOF;
+}
+
+static void stbi_decoder_free(struct camu_decoder **dec)
+{
+ struct camu_stbi_decoder *stb = (struct camu_stbi_decoder *)*dec;
+ al_free(stb);
+ *dec = NULL;
+}
+
+struct camu_decoder *camu_stbi_decoder_create(void)
+{
+ struct camu_stbi_decoder *stb = al_alloc_object(struct camu_stbi_decoder);
+ stb->dec.mode = CAMU_NORMAL;
+ stb->dec.init = stbi_decoder_init;
+ stb->dec.push = stbi_decoder_push;
+ stb->dec.process = stbi_decoder_process;
+ stb->dec.flush = stbi_decoder_flush;
+ stb->dec.free = stbi_decoder_free;
+ return (struct camu_decoder *)stb;
+}
diff --git a/src/codec/stb_image/impl.c b/src/codec/stb_image/impl.c
index 1d3a4a1..e59d581 100644
--- a/src/codec/stb_image/impl.c
+++ b/src/codec/stb_image/impl.c
@@ -1,169 +1,8 @@
-#include <al/lib.h>
-#include <nnwt/common.h>
#include "../common.h"
#define STB_IMAGE_IMPLEMENTATION
-#define STB_IMAGE_STATIC
#define STBI_NO_STDIO
#define STBI_NO_FAILURE_STRINGS
#define STBI_MALLOC camu_page_alloc
#define STBI_FREE al_free
#define STBI_REALLOC camu_page_realloc
-AL_UNUSED_FUNCTION_PUSH
#include <stb_image.h>
-AL_UNUSED_FUNCTION_POP
-
-#include "../../cache/entry.h"
-
-#include "demuxer.h"
-#include "decoder.h"
-
-static bool stbi_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle)
-{
- struct camu_stbi_demuxer *stb = (struct camu_stbi_demuxer *)demux;
-
- stb->handle = handle;
- nn_buffer_init(&stb->buffer);
- stb->eof = false;
-
- cch_handle_seek(stb->handle, 0, SEEK_SET);
- off_t size = cch_entry_get_size(stb->handle->entry);
- nn_buffer_ensure_space(&stb->buffer, size);
- cch_handle_read(stb->handle, nn_buffer_get_ptr(&stb->buffer, 0), size);
- stb->buffer.size = size;
-
- s32 w, h, channels;
- u8 *data = nn_buffer_get_ptr(&stb->buffer, 0);
- if (!stbi_info_from_memory(data, stb->buffer.size, &w, &h, &channels)) {
- 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 = w;
- fmt->height = h;
- fmt->format = camu_pixel_format_from_channels(channels);
-
- al_array_push(stb->demux.streams, stream);
-
- return true;
-err:
- return false;
-}
-
-static s32 stbi_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet)
-{
- struct camu_stbi_demuxer *stb = (struct camu_stbi_demuxer *)demux;
- if (!stb->eof) {
- packet->mode = CAMU_NORMAL;
- packet->buffer = &stb->buffer;
- stb->eof = true;
- return CAMU_OK;
- }
- return CAMU_ERR_EOF;
-}
-
-static u64 stbi_demuxer_get_duration(struct camu_demuxer *demux)
-{
- (void)demux;
- return 0;
-}
-
-static bool stbi_demuxer_seek(struct camu_demuxer *demux, u64 pos)
-{
- (void)demux;
- (void)pos;
- return true;
-}
-
-static void stbi_demuxer_free(struct camu_demuxer **demux)
-{
- struct camu_stbi_demuxer *stb = (struct camu_stbi_demuxer *)*demux;
- nn_buffer_free(&stb->buffer);
- al_array_free(stb->demux.streams);
- al_free(stb);
- *demux = NULL;
-}
-
-
-static bool stbi_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_stbi_decoder *stb = (struct camu_stbi_decoder *)dec;
- (void)renderer;
- stb->stream = stream;
- stb->callback = callback;
- stb->userdata = userdata;
- return true;
-}
-
-static s32 stbi_decoder_push(struct camu_decoder *dec, struct camu_codec_packet *packet)
-{
- struct camu_stbi_decoder *stb = (struct camu_stbi_decoder *)dec;
- if (!packet) return CAMU_OK;
-
- s32 w, h, channels;
- u8 *data = nn_buffer_get_ptr(packet->buffer, 0);
- u8 *pixels = stbi_load_from_memory(data, packet->buffer->size, &w, &h, &channels, 0);
- if (!pixels) return CAMU_ERR_ERROR;
- struct camu_video_format *fmt = &stb->stream->video.fmt;
- al_assert(w == fmt->width && h == fmt->height);
-
- struct camu_codec_frame *frame = al_alloc_object(struct camu_codec_frame);
- frame->mode = CAMU_NORMAL;
- frame->flags = 0;
- frame->data = pixels;
- frame->video.width = w;
- frame->video.height = h;
- frame->format = camu_pixel_format_from_channels(channels);
- al_assert(frame->format == fmt->format);
- frame->pts = 0.0;
-
- stb->callback(stb->userdata, frame);
-
- return CAMU_OK;
-}
-
-static void stbi_decoder_flush(struct camu_decoder *dec)
-{
- (void)dec;
-}
-
-static s32 stbi_decoder_process(struct camu_decoder *dec)
-{
- (void)dec;
- return CAMU_ERR_EOF;
-}
-
-static void stbi_decoder_free(struct camu_decoder **dec)
-{
- struct camu_stbi_decoder *stb = (struct camu_stbi_decoder *)*dec;
- al_free(stb);
- *dec = NULL;
-}
-
-struct camu_demuxer *camu_stbi_demuxer_create(void)
-{
- struct camu_stbi_demuxer *stb = al_alloc_object(struct camu_stbi_demuxer);
- stb->demux.mode = CAMU_NORMAL;
- al_array_init(stb->demux.streams);
- stb->demux.init = stbi_demuxer_init;
- stb->demux.get_packet = stbi_demuxer_get_packet;
- stb->demux.get_duration = stbi_demuxer_get_duration;
- stb->demux.seek = stbi_demuxer_seek;
- stb->demux.free = stbi_demuxer_free;
- return (struct camu_demuxer *)stb;
-}
-
-struct camu_decoder *camu_stbi_decoder_create(void)
-{
- struct camu_stbi_decoder *stb = al_alloc_object(struct camu_stbi_decoder);
- stb->dec.mode = CAMU_NORMAL;
- stb->dec.init = stbi_decoder_init;
- stb->dec.push = stbi_decoder_push;
- stb->dec.process = stbi_decoder_process;
- stb->dec.flush = stbi_decoder_flush;
- stb->dec.free = stbi_decoder_free;
- return (struct camu_decoder *)stb;
-}
diff --git a/src/codec/stb_image/meson.build b/src/codec/stb_image/meson.build
new file mode 100644
index 0000000..fea86ff
--- /dev/null
+++ b/src/codec/stb_image/meson.build
@@ -0,0 +1,3 @@
+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)
diff --git a/src/codec/stb_image/server.c b/src/codec/stb_image/server.c
new file mode 100644
index 0000000..3642a64
--- /dev/null
+++ b/src/codec/stb_image/server.c
@@ -0,0 +1,87 @@
+#include <stb_image.h>
+
+#include "../../cache/entry.h"
+
+#include "demuxer.h"
+
+static bool stbi_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handle)
+{
+ struct camu_stbi_demuxer *stb = (struct camu_stbi_demuxer *)demux;
+
+ stb->handle = handle;
+ nn_buffer_init(&stb->buffer);
+ stb->eof = false;
+
+ cch_handle_seek(stb->handle, 0, SEEK_SET);
+ off_t size = cch_entry_get_size(stb->handle->entry);
+ nn_buffer_ensure_space(&stb->buffer, size);
+ cch_handle_read(stb->handle, nn_buffer_get_ptr(&stb->buffer, 0), size);
+ stb->buffer.size = size;
+
+ s32 w, h, channels;
+ u8 *data = nn_buffer_get_ptr(&stb->buffer, 0);
+ if (!stbi_info_from_memory(data, stb->buffer.size, &w, &h, &channels)) {
+ 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 = w;
+ fmt->height = h;
+ fmt->format = camu_pixel_format_from_channels(channels);
+
+ al_array_push(stb->demux.streams, stream);
+
+ return true;
+err:
+ return false;
+}
+
+static s32 stbi_demuxer_get_packet(struct camu_demuxer *demux, struct camu_codec_packet *packet)
+{
+ struct camu_stbi_demuxer *stb = (struct camu_stbi_demuxer *)demux;
+ if (!stb->eof) {
+ packet->mode = CAMU_NORMAL;
+ packet->buffer = &stb->buffer;
+ stb->eof = true;
+ return CAMU_OK;
+ }
+ return CAMU_ERR_EOF;
+}
+
+static u64 stbi_demuxer_get_duration(struct camu_demuxer *demux)
+{
+ (void)demux;
+ return 0;
+}
+
+static bool stbi_demuxer_seek(struct camu_demuxer *demux, u64 pos)
+{
+ (void)demux;
+ (void)pos;
+ return true;
+}
+
+static void stbi_demuxer_free(struct camu_demuxer **demux)
+{
+ struct camu_stbi_demuxer *stb = (struct camu_stbi_demuxer *)*demux;
+ nn_buffer_free(&stb->buffer);
+ al_array_free(stb->demux.streams);
+ al_free(stb);
+ *demux = NULL;
+}
+
+struct camu_demuxer *camu_stbi_demuxer_create(void)
+{
+ struct camu_stbi_demuxer *stb = al_alloc_object(struct camu_stbi_demuxer);
+ stb->demux.mode = CAMU_NORMAL;
+ al_array_init(stb->demux.streams);
+ stb->demux.init = stbi_demuxer_init;
+ stb->demux.get_packet = stbi_demuxer_get_packet;
+ stb->demux.get_duration = stbi_demuxer_get_duration;
+ stb->demux.seek = stbi_demuxer_seek;
+ stb->demux.free = stbi_demuxer_free;
+ return (struct camu_demuxer *)stb;
+}
diff --git a/src/codec/wuffs/meson.build b/src/codec/wuffs/meson.build
new file mode 100644
index 0000000..bb5007a
--- /dev/null
+++ b/src/codec/wuffs/meson.build
@@ -0,0 +1,3 @@
+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)