diff options
| author | s-ol <s+removethis@s-ol.nu> | 2025-03-20 13:39:03 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-20 16:57:56 +0000 |
| commit | 6616300ed47e5b349704e64a06b1ece036b16463 (patch) | |
| tree | 7f9c5ae88d3a261736cb7713f352ea293fc7e242 /src/hap.zig | |
| parent | print effective OSC address on listen, reload messages (diff) | |
| download | glsl-view-6616300ed47e5b349704e64a06b1ece036b16463.tar.gz glsl-view-6616300ed47e5b349704e64a06b1ece036b16463.zip | |
wrap Texture in Source
Diffstat (limited to 'src/hap.zig')
| -rw-r--r-- | src/hap.zig | 137 |
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; + } +}; |
