From 2daa31c0629f2eb4af84d6f4fed8ac89813de056 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 22 Jan 2025 20:56:04 -0500 Subject: Big build update Signed-off-by: Andrew Opalach --- src/codec/codec.h | 17 +++-- src/codec/ffmpeg/decoder.c | 8 +- src/codec/ffmpeg/meson.build | 70 +++++++++++++++++ src/codec/meson.build | 79 +++---------------- src/codec/spng/client.c | 77 +++++++++++++++++++ src/codec/spng/impl.c | 164 ---------------------------------------- src/codec/spng/meson.build | 3 + src/codec/spng/server.c | 90 ++++++++++++++++++++++ src/codec/stb_image/client.c | 71 +++++++++++++++++ src/codec/stb_image/impl.c | 161 --------------------------------------- src/codec/stb_image/meson.build | 3 + src/codec/stb_image/server.c | 87 +++++++++++++++++++++ src/codec/wuffs/meson.build | 3 + 13 files changed, 430 insertions(+), 403 deletions(-) create mode 100644 src/codec/ffmpeg/meson.build create mode 100644 src/codec/spng/client.c create mode 100644 src/codec/spng/meson.build create mode 100644 src/codec/spng/server.c create mode 100644 src/codec/stb_image/client.c create mode 100644 src/codec/stb_image/meson.build create mode 100644 src/codec/stb_image/server.c create mode 100644 src/codec/wuffs/meson.build (limited to 'src/codec') 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 #include +#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 + +#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 -#include -#include - -#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 + +#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 + +#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 -#include #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 -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 + +#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) -- cgit v1.2.3-101-g0448