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/wuffs | |
| 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/wuffs')
| -rw-r--r-- | src/codec/wuffs/decoder.h | 13 | ||||
| -rw-r--r-- | src/codec/wuffs/demuxer.h | 12 | ||||
| -rw-r--r-- | src/codec/wuffs/impl.c | 213 |
3 files changed, 238 insertions, 0 deletions
diff --git a/src/codec/wuffs/decoder.h b/src/codec/wuffs/decoder.h new file mode 100644 index 0000000..71f0290 --- /dev/null +++ b/src/codec/wuffs/decoder.h @@ -0,0 +1,13 @@ +#pragma once + +#include "../common.h" +#include "../codec.h" + +struct camu_wuffs_decoder { + struct camu_decoder dec; + u8 file_type; + void (*callback)(void *, struct camu_frame *); + void (*userdata); +}; + +struct camu_decoder *camu_wuffs_decoder_create(void); diff --git a/src/codec/wuffs/demuxer.h b/src/codec/wuffs/demuxer.h new file mode 100644 index 0000000..6e9e391 --- /dev/null +++ b/src/codec/wuffs/demuxer.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../codec.h" + +struct camu_wuffs_demuxer { + struct camu_demuxer demux; + struct cch_handle *handle; + struct aki_buffer buffer; + bool eof; +}; + +struct camu_demuxer *camu_wuffs_demuxer_create(void); diff --git a/src/codec/wuffs/impl.c b/src/codec/wuffs/impl.c new file mode 100644 index 0000000..a1e58e4 --- /dev/null +++ b/src/codec/wuffs/impl.c @@ -0,0 +1,213 @@ +#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 <aki/common.h> + +#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; + aki_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); + aki_buffer_ensure_space(&wfs->buffer, size); + cch_handle_read(wfs->handle, aki_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); + (void)status; + //if (!wuffs_base__status__is_ok(&status)) goto err; + + wuffs_png__decoder__set_quirk(&wf_dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true); + + //wuffs_png__decoder__set_report_metadata(&wf_dec, WUFFS_BASE__FOURCC__ICCP, true); + + wuffs_base__io_buffer src = {0}; + src.data.ptr = aki_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_stream stream; + stream.type = CAMU_NORMAL; + stream.video.width = wuffs_base__pixel_config__width(&ic.pixcfg); + stream.video.height = wuffs_base__pixel_config__height(&ic.pixcfg); + + al_array_push(wfs->demux.streams, stream); + + return true; +} + +static s32 wuffs_demuxer_get_packet(struct camu_demuxer *demux, struct camu_packet *packet) +{ + struct camu_wuffs_demuxer *wfs = (struct camu_wuffs_demuxer *)demux; + if (wfs->eof) return CAMU_ERR_EOF; + packet->type = CAMU_NORMAL; + packet->buffer = &wfs->buffer; + wfs->eof = true; + return CAMU_OK; +} + +static s64 wuffs_demuxer_get_duration(struct camu_demuxer *demux) +{ + (void)demux; + return 0; +} + +static bool wuffs_demuxer_seek(struct camu_demuxer *demux, s64 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; + al_free(wfs); + *demux = NULL; +} + +static bool wuffs_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_stream *stream) +{ + struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; + (void)wfs; + (void)stream; + (void)renderer; + return true; +} + +static void wuffs_decoder_set_callback(struct camu_decoder *dec, void (*callback)(void *, struct camu_frame *), void *userdata) +{ + struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; + wfs->callback = callback; + wfs->userdata = userdata; +} + +static s32 wuffs_decoder_push(struct camu_decoder *dec, struct camu_packet *packet) +{ + if (!packet) return CAMU_OK; + + struct camu_wuffs_decoder *wfs = (struct camu_wuffs_decoder *)dec; + + 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_png__decoder__set_report_metadata(&wf_dec, WUFFS_BASE__FOURCC__ICCP, true); + + wuffs_base__io_buffer src = {0}; + src.data.ptr = aki_buffer_get_ptr(packet->buffer, 0); + src.data.len = packet->buffer->size; + src.meta.wi = packet->buffer->size; + src.meta.closed = true; + + //wf_dec.private_impl.p_decode_iccp[0] = 1; + + 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_frame *frame = al_alloc_object(struct camu_frame); + frame->type = CAMU_NORMAL; + frame->width = wfs->dec.stream->video.width; + frame->height = wfs->dec.stream->video.height; + frame->fmt = CAMU_PIXEL_FMT_RGBA; + + 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; + /* + void *device_ptr = dec->renderer->get_device_ptr(dec->renderer, dst_size + wrk_size); + wuffs_base__slice_u8 wrk = wuffs_base__make_slice_u8(device_ptr + dst_size, wrk_size); + status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, + wuffs_base__make_slice_u8(device_ptr, dst_size)); + */ + 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); + (void)status; + //if (!wuffs_base__status__is_ok(&status)) goto err; + + wfs->callback(wfs->userdata, frame); + + return CAMU_OK; +} + +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.type = 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.init = wuffs_decoder_init; + wfs->dec.set_callback = wuffs_decoder_set_callback; + 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; +} |