diff options
| author | 2023-11-06 11:54:08 -0500 | |
|---|---|---|
| committer | 2023-11-06 11:54:08 -0500 | |
| commit | a48a68cfb04b2020737c0adfb0e7667451a22b5c (patch) | |
| tree | a92121897f84298c3798a4f2ba56de45cd100eab /src/codec/spng | |
| download | camu-a48a68cfb04b2020737c0adfb0e7667451a22b5c.tar.gz camu-a48a68cfb04b2020737c0adfb0e7667451a22b5c.tar.bz2 camu-a48a68cfb04b2020737c0adfb0e7667451a22b5c.zip | |
Add camu
- Subprojects temporarily omitted
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/codec/spng')
| -rw-r--r-- | src/codec/spng/decoder.h | 11 | ||||
| -rw-r--r-- | src/codec/spng/demuxer.h | 12 | ||||
| -rw-r--r-- | src/codec/spng/impl.c | 166 |
3 files changed, 189 insertions, 0 deletions
diff --git a/src/codec/spng/decoder.h b/src/codec/spng/decoder.h new file mode 100644 index 0000000..fee30c6 --- /dev/null +++ b/src/codec/spng/decoder.h @@ -0,0 +1,11 @@ +#pragma once + +#include "../codec.h" + +struct camu_spng_decoder { + struct camu_decoder dec; + void (*callback)(void *, struct camu_frame *); + void (*userdata); +}; + +struct camu_decoder *camu_spng_decoder_create(void); diff --git a/src/codec/spng/demuxer.h b/src/codec/spng/demuxer.h new file mode 100644 index 0000000..1947bb7 --- /dev/null +++ b/src/codec/spng/demuxer.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../codec.h" + +struct camu_spng_demuxer { + struct camu_demuxer demux; + struct cch_handle *handle; + struct aki_buffer buffer; + bool eof; +}; + +struct camu_demuxer *camu_spng_demuxer_create(void); diff --git a/src/codec/spng/impl.c b/src/codec/spng/impl.c new file mode 100644 index 0000000..d090bdc --- /dev/null +++ b/src/codec/spng/impl.c @@ -0,0 +1,166 @@ +#include <al/lib.h> +#include <aki/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; + aki_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); + aki_buffer_ensure_space(&spng->buffer, size); + cch_handle_read(spng->handle, aki_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, aki_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_stream stream; + stream.type = CAMU_NORMAL; + stream.video.width = ihdr.width; + stream.video.height = ihdr.height; + + 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_packet *packet) +{ + struct camu_spng_demuxer *spng = (struct camu_spng_demuxer *)demux; + if (spng->eof) return CAMU_ERR_EOF; + packet->type = CAMU_NORMAL; + packet->buffer = &spng->buffer; + spng->eof = true; + return CAMU_OK; +} + +static s64 spng_demuxer_get_duration(struct camu_demuxer *demux) +{ + (void)demux; + return 0; +} + +static bool spng_demuxer_seek(struct camu_demuxer *demux, s64 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; + al_free(spng); + *demux = NULL; +} + +static bool spng_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_stream *stream) +{ + struct camu_spng_decoder *spng = (struct camu_spng_decoder *)dec; + (void)spng; + (void)stream; + (void)renderer; + return true; +} + +static void spng_decoder_set_callback(struct camu_decoder *dec, void (*callback)(void *, struct camu_frame *), void *userdata) +{ + struct camu_spng_decoder *spng = (struct camu_spng_decoder *)dec; + spng->callback = callback; + spng->userdata = userdata; +} + +static s32 spng_decoder_push(struct camu_decoder *dec, struct camu_packet *packet) +{ + if (!packet) return CAMU_OK; + + struct camu_spng_decoder *spng = (struct camu_spng_decoder *)dec; + + spng_ctx *ctx = spng_ctx_new(SPNG_CTX_IGNORE_ADLER32); + spng_set_png_buffer(ctx, aki_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_frame *frame = al_alloc_object(struct camu_frame); + frame->type = CAMU_NORMAL; + frame->width = spng->dec.stream->video.width; + frame->height = spng->dec.stream->video.height; + frame->fmt = CAMU_PIXEL_FMT_RGBA; + frame->pts = 0.0; + frame->flags = 0; + + 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); + + 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.type = 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.init = spng_decoder_init; + spng->dec.set_callback = spng_decoder_set_callback; + 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; +} |