summaryrefslogtreecommitdiff
path: root/src/codec/wuffs
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2023-11-06 11:54:08 -0500
committerAndrew Opalach <andrew@akon.city> 2023-11-06 11:54:08 -0500
commita48a68cfb04b2020737c0adfb0e7667451a22b5c (patch)
treea92121897f84298c3798a4f2ba56de45cd100eab /src/codec/wuffs
downloadcamu-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.h13
-rw-r--r--src/codec/wuffs/demuxer.h12
-rw-r--r--src/codec/wuffs/impl.c213
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;
+}