aboutsummaryrefslogtreecommitdiffstats
path: root/src/hap.zig
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2025-03-20 13:39:03 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-20 16:57:56 +0000
commit6616300ed47e5b349704e64a06b1ece036b16463 (patch)
tree7f9c5ae88d3a261736cb7713f352ea293fc7e242 /src/hap.zig
parentprint effective OSC address on listen, reload messages (diff)
downloadglsl-view-6616300ed47e5b349704e64a06b1ece036b16463.tar.gz
glsl-view-6616300ed47e5b349704e64a06b1ece036b16463.zip
wrap Texture in Source
Diffstat (limited to 'src/hap.zig')
-rw-r--r--src/hap.zig137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/hap.zig b/src/hap.zig
new file mode 100644
index 0000000..696b905
--- /dev/null
+++ b/src/hap.zig
@@ -0,0 +1,137 @@
+const std = @import("std");
+const c = @import("c.zig");
+const gl = @import("gl.zig");
+const ffmpeg = @import("ffmpeg.zig");
+
+fn check(err: c_uint) ffmpeg.Errors!void {
+ return switch (err) {
+ c.HapResult_No_Error => return,
+ c.HapResult_Bad_Arguments => return error.HAPBadArguments,
+ c.HapResult_Buffer_Too_Small => return error.HAPBufferTooSmall,
+ c.HapResult_Bad_Frame => return error.HAPBadFrame,
+ c.HapResult_Internal_Error => return error.HAPInternalError,
+ else => unreachable,
+ };
+}
+
+pub const HAPDecoder = struct {
+ decoder: ffmpeg.Decoder,
+
+ codec_par: c.AVCodecParameters,
+ format: ?c.HapTextureFormat,
+ gl_format: c.GLenum,
+
+ pub fn init(
+ allocator: std.mem.Allocator,
+ codec_par: c.AVCodecParameters,
+ ) ffmpeg.Errors!*ffmpeg.Decoder {
+ const self = try allocator.create(HAPDecoder);
+
+ self.* = .{
+ .decoder = .{
+ .process_packet_fn = processPacket,
+ .init_texture_fn = initTexture,
+ .reset_fn = null,
+ .deinit_fn = deinit,
+ .num_frames = 0,
+ },
+ .codec_par = codec_par,
+ .format = null,
+ .gl_format = undefined,
+ };
+ return &self.decoder;
+ }
+
+ fn deinit(decoder: *ffmpeg.Decoder, allocator: std.mem.Allocator) void {
+ const self: *HAPDecoder = @fieldParentPtr("decoder", decoder);
+ allocator.destroy(self);
+ }
+
+ fn initTexture(decoder: *ffmpeg.Decoder, texture: *const gl.Texture) void {
+ const self: *HAPDecoder = @fieldParentPtr("decoder", decoder);
+
+ texture.allocate(
+ self.codec_par.width,
+ self.codec_par.height,
+ self.decoder.num_frames,
+ self.gl_format,
+ );
+ }
+
+ fn launchThread(
+ workfn: c.HapDecodeWorkFunction,
+ p: ?*anyopaque,
+ count: c_uint,
+ info: ?*anyopaque,
+ ) callconv(.C) void {
+ _ = info;
+
+ var i: c_uint = 0;
+ while (i < count) : (i += 1) {
+ workfn.?(p, i);
+ }
+ }
+
+ fn processPacket(
+ decoder: *ffmpeg.Decoder,
+ packet: *c.AVPacket,
+ texture: ?*const gl.Texture,
+ ) ffmpeg.Errors!bool {
+ const self: *HAPDecoder = @fieldParentPtr("decoder", decoder);
+
+ var textureCount: u32 = undefined;
+ try check(c.HapGetFrameTextureCount(packet.data, @intCast(packet.size), &textureCount));
+ if (textureCount != 1) {
+ return error.UnsupportedCodec;
+ }
+
+ var format: c.HapTextureFormat = undefined;
+
+ if (texture) |tex| {
+ var buffer: [16 * 1024 * 1024]u8 = undefined;
+ var length: c_ulong = undefined;
+ try check(c.HapDecode(
+ packet.data,
+ @intCast(packet.size),
+ 0,
+ launchThread,
+ self,
+ &buffer,
+ buffer.len,
+ &length,
+ &format,
+ ));
+
+ tex.setLayerCompressed(
+ self.codec_par.width,
+ self.codec_par.height,
+ self.decoder.num_frames,
+ self.gl_format,
+ buffer[0..length],
+ );
+
+ if (tex.type == .TEXTURE_2D) return false;
+ } else {
+ try check(c.HapGetFrameTextureFormat(packet.data, @intCast(packet.size), 0, &format));
+ if (self.format) |fmt| {
+ if (fmt != format) return error.UnsupportedCodec;
+ } else {
+ self.format = format;
+ self.gl_format = switch (format) {
+ c.HapTextureFormat_RGB_DXT1 => c.GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ c.HapTextureFormat_RGBA_DXT5 => c.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ c.HapTextureFormat_YCoCg_DXT5,
+ c.HapTextureFormat_A_RGTC1,
+ c.HapTextureFormat_RGBA_BPTC_UNORM,
+ c.HapTextureFormat_RGB_BPTC_UNSIGNED_FLOAT,
+ c.HapTextureFormat_RGB_BPTC_SIGNED_FLOAT,
+ => return error.UnsupportedCodec,
+ else => unreachable,
+ };
+ }
+ }
+
+ self.decoder.num_frames += 1;
+ return true;
+ }
+};