From 94d198a60cbcf937464a46b380f4617e2d1c4066 Mon Sep 17 00:00:00 2001 From: Dione Julek Date: Thu, 18 Apr 2024 01:02:49 -0300 Subject: [PATCH] Add f16 format --- src/filters/bilateral.zig | 12 +++++----- src/filters/boxblur.zig | 4 +++- src/filters/planeaverage.zig | 13 ++++++----- src/filters/planeminmax.zig | 13 ++++++----- src/filters/process/bilateral.zig | 27 ++++++++++++---------- src/helper.zig | 37 +++++++++++++++++++++++++++---- 6 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/filters/bilateral.zig b/src/filters/bilateral.zig index 664d202..952b886 100644 --- a/src/filters/bilateral.zig +++ b/src/filters/bilateral.zig @@ -12,7 +12,7 @@ const allocator = std.heap.c_allocator; pub const filter_name = "Bilateral"; pub const BilateralData = struct { - node1: *vs.Node, + node1: ?*vs.Node, node2: ?*vs.Node, vi: *const vs.VideoInfo, dt: helper.DataType, @@ -65,6 +65,7 @@ export fn bilateralGetFrame(n: c_int, activation_reason: vs.ActivationReason, in switch (d.dt) { .U8 => bilateral2D(u8, srcp, refp, dstp, stride, w, h, plane, d), .U16 => bilateral2D(u16, srcp, refp, dstp, stride, w, h, plane, d), + .F16 => bilateral2DFloat(f16, srcp, refp, dstp, stride, w, h, plane, d), .F32 => bilateral2DFloat(f32, srcp, refp, dstp, stride, w, h, plane, d), } } @@ -100,13 +101,12 @@ pub export fn bilateralCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ?*an var d: BilateralData = undefined; var err: vs.MapPropertyError = undefined; - d.node1 = vsapi.?.mapGetNode.?(in, "clip", 0, &err).?; - d.vi = vsapi.?.getVideoInfo.?(d.node1); - d.dt = @enumFromInt(d.vi.format.bytesPerSample); + const map = zapi.Map.init(in, out, vsapi); + d.node1, d.vi = map.getNodeVi("clip"); + d.dt = helper.DataType.select(map, d.node1, d.vi, filter_name) catch return; const yuv: bool = (d.vi.format.colorFamily == vs.ColorFamily.YUV); - const bps = d.vi.format.bitsPerSample; - const peak: u32 = if (d.vi.format.sampleType == .Integer) math.shl(u32, 1, bps) else 65535; + const peak: u32 = if (d.vi.format.sampleType == .Integer) math.shl(u32, 1, d.vi.format.bitsPerSample) else 65535; d.peak = @floatFromInt(peak); var i: u32 = 0; diff --git a/src/filters/boxblur.zig b/src/filters/boxblur.zig index 66c82ee..d7380ea 100644 --- a/src/filters/boxblur.zig +++ b/src/filters/boxblur.zig @@ -38,6 +38,7 @@ export fn boxBlurRTGetFrame(n: c_int, activation_reason: vs.ActivationReason, in switch (d.dt) { .U8 => hvBlurRT(u8, src, dst, d), .U16 => hvBlurRT(u16, src, dst, d), + .F16 => hvBlurRT(f16, src, dst, d), .F32 => hvBlurRT(f32, src, dst, d), } @@ -71,6 +72,7 @@ export fn boxBlurCTGetFrame(n: c_int, activation_reason: vs.ActivationReason, in switch (d.dt) { .U8 => process_ct.hvBlur(u8, srcp, dstp, stride, w, h, d.vradius), .U16 => process_ct.hvBlur(u16, srcp, dstp, stride, w, h, d.vradius), + .F16 => process_ct.hvBlur(f16, srcp, dstp, stride, w, h, d.vradius), .F32 => process_ct.hvBlur(f32, srcp, dstp, stride, w, h, d.vradius), } } @@ -96,7 +98,7 @@ pub export fn boxBlurCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ?*anyo var map = zapi.Map.init(in, out, vsapi); d.node, d.vi = map.getNodeVi("clip"); - d.dt = @enumFromInt(d.vi.format.bytesPerSample); + d.dt = helper.DataType.select(map, d.node, d.vi, filter_name) catch return; d.tmp_size = @intCast(@max(d.vi.width, d.vi.height)); var nodes = [_]?*vs.Node{d.node}; diff --git a/src/filters/planeaverage.zig b/src/filters/planeaverage.zig index be7be94..e57dffe 100644 --- a/src/filters/planeaverage.zig +++ b/src/filters/planeaverage.zig @@ -62,6 +62,7 @@ export fn planeAverageGetFrame(n: c_int, activation_reason: vs.ActivationReason, avg = switch (d.dt) { .U8 => process.average(u8, srcp, stride, w, h, d.exclude, d.peak), .U16 => process.average(u16, srcp, stride, w, h, d.exclude, d.peak), + .F16 => process.average(f16, srcp, stride, w, h, d.exclude, d.peak), .F32 => process.average(f32, srcp, stride, w, h, d.exclude, d.peak), }; } else { @@ -69,6 +70,7 @@ export fn planeAverageGetFrame(n: c_int, activation_reason: vs.ActivationReason, const stats = switch (d.dt) { .U8 => process.averageRef(u8, srcp, refp, stride, w, h, d.exclude, d.peak), .U16 => process.averageRef(u16, srcp, refp, stride, w, h, d.exclude, d.peak), + .F16 => process.averageRef(f16, srcp, refp, stride, w, h, d.exclude, d.peak), .F32 => process.averageRef(f32, srcp, refp, stride, w, h, d.exclude, d.peak), }; _ = vsapi.?.mapSetFloat.?(props, if (d.prop != null) d.prop.?.d.ptr else "psmDiff", stats.diff, .Append); @@ -103,10 +105,11 @@ pub export fn planeAverageCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ? var map = zapi.Map.init(in, out, vsapi); d.node1, d.vi = map.getNodeVi("clipa"); + d.dt = helper.DataType.select(map, d.node1, d.vi, filter_name) catch return; + d.node2, const vi2 = map.getNodeVi("clipb"); helper.compareNodes(out, d.node1, d.node2, d.vi, vi2, filter_name, vsapi) catch return; - d.dt = @enumFromInt(d.vi.format.bytesPerSample); d.peak = @floatFromInt(math.shl(i32, 1, d.vi.format.bitsPerSample) - 1); var nodes = [_]?*vs.Node{ d.node1, d.node2 }; var planes = [3]bool{ true, false, false }; @@ -116,7 +119,7 @@ pub export fn planeAverageCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ? d.prop = getPropData(map, "prop", allocator, &d.prop_buff); const exclude_in = map.getIntArray("exclude"); if (exclude_in) |ein| { - if (d.dt == .F32) { + if (d.vi.format.sampleType == .Float) { d.exclude = process.Exclude{ .f = allocator.alloc(f32, ein.len) catch unreachable }; for (d.exclude.f, ein) |*df, *ei| { df.* = @floatFromInt(ei.*); @@ -157,15 +160,15 @@ pub export fn planeAverageCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ? vsapi.?.createVideoFilter.?(out, filter_name, d.vi, planeAverageGetFrame, planeAverageFree, .Parallel, deps, deps_len, data, core); } -pub fn getPropData(self: zapi.Map, comptime key: []const u8, data_allocator: std.mem.Allocator, data_buff: *?[]u8) ?StringProp { +pub fn getPropData(map: zapi.Map, comptime key: []const u8, data_allocator: std.mem.Allocator, data_buff: *?[]u8) ?StringProp { var err: vs.MapPropertyError = undefined; data_buff.* = null; - const data_ptr = self.vsapi.?.mapGetData.?(self.in, key.ptr, 0, &err); + const data_ptr = map.vsapi.?.mapGetData.?(map.in, key.ptr, 0, &err); if (err != .Success) { return null; } - const data_len = self.vsapi.?.mapGetDataSize.?(self.in, key.ptr, 0, &err); + const data_len = map.vsapi.?.mapGetDataSize.?(map.in, key.ptr, 0, &err); if ((err != .Success) or (data_len < 1)) { return null; } diff --git a/src/filters/planeminmax.zig b/src/filters/planeminmax.zig index 89f68ba..c4c0e4e 100644 --- a/src/filters/planeminmax.zig +++ b/src/filters/planeminmax.zig @@ -64,6 +64,7 @@ export fn planeMinMaxGetFrame(n: c_int, activation_reason: vs.ActivationReason, stats = switch (d.dt) { .U8 => process.minMaxInt(u8, srcp, stride, w, h, d), .U16 => process.minMaxInt(u16, srcp, stride, w, h, d), + .F16 => process.minMaxFloat(f16, srcp, stride, w, h, d), .F32 => process.minMaxFloat(f32, srcp, stride, w, h, d), }; } else { @@ -71,6 +72,7 @@ export fn planeMinMaxGetFrame(n: c_int, activation_reason: vs.ActivationReason, stats = switch (d.dt) { .U8 => process.minMaxIntRef(u8, srcp, refp, stride, w, h, d), .U16 => process.minMaxIntRef(u16, srcp, refp, stride, w, h, d), + .F16 => process.minMaxFloatRef(f16, srcp, refp, stride, w, h, d), .F32 => process.minMaxFloatRef(f32, srcp, refp, stride, w, h, d), }; @@ -114,16 +116,17 @@ pub export fn planeMinMaxCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ?* var map = zapi.Map.init(in, out, vsapi); d.node1, d.vi = map.getNodeVi("clipa"); + d.dt = helper.DataType.select(map, d.node1, d.vi, filter_name) catch return; + d.node2, const vi2 = map.getNodeVi("clipb"); helper.compareNodes(out, d.node1, d.node2, d.vi, vi2, filter_name, vsapi) catch return; - d.dt = @enumFromInt(d.vi.format.bytesPerSample); var nodes = [_]?*vs.Node{ d.node1, d.node2 }; var planes = [3]bool{ true, false, false }; helper.mapGetPlanes(in, out, &nodes, &planes, d.vi.format.numPlanes, filter_name, vsapi) catch return; d.planes = planes; - d.hist_size = if (d.dt == .F32) 65536 else math.shl(u32, 1, d.vi.format.bitsPerSample); + d.hist_size = if (d.vi.format.sampleType == .Float) 65536 else math.shl(u32, 1, d.vi.format.bitsPerSample); d.peak = @intCast(d.hist_size - 1); d.maxthr = getThr(in, out, &nodes, "maxthr", vsapi) catch return; d.minthr = getThr(in, out, &nodes, "minthr", vsapi) catch return; @@ -173,15 +176,15 @@ pub fn getThr(in: ?*const vs.Map, out: ?*vs.Map, nodes: []?*vs.Node, comptime ke return thr; } -pub fn getPropData(self: zapi.Map, comptime key: []const u8, data_allocator: std.mem.Allocator, data_buff: *?[]u8) ?StringProp { +pub fn getPropData(map: zapi.Map, comptime key: []const u8, data_allocator: std.mem.Allocator, data_buff: *?[]u8) ?StringProp { var err: vs.MapPropertyError = undefined; data_buff.* = null; - const data_ptr = self.vsapi.?.mapGetData.?(self.in, key.ptr, 0, &err); + const data_ptr = map.vsapi.?.mapGetData.?(map.in, key.ptr, 0, &err); if (err != .Success) { return null; } - const data_len = self.vsapi.?.mapGetDataSize.?(self.in, key.ptr, 0, &err); + const data_len = map.vsapi.?.mapGetDataSize.?(map.in, key.ptr, 0, &err); if ((err != .Success) or (data_len < 1)) { return null; } diff --git a/src/filters/process/bilateral.zig b/src/filters/process/bilateral.zig index 7c8fefa..1cd2045 100644 --- a/src/filters/process/bilateral.zig +++ b/src/filters/process/bilateral.zig @@ -226,7 +226,7 @@ pub fn bilateralAlg1Float(comptime T: type, srcp: []const T, dstp: []T, refp: [] var i = stride * j; const upper = i + width; while (i < upper) : (i += 1) { - wk[i] = gr_lut[@intFromFloat(@abs(PBFICk[k] - refp[i]) * 65535 + 0.5)]; + wk[i] = gr_lut[@intFromFloat(@as(f32, @abs(PBFICk[k] - refp[i])) * 65535 + 0.5)]; jk[i] = wk[i] * srcp[i]; } } @@ -256,7 +256,10 @@ pub fn bilateralAlg1Float(comptime T: type, srcp: []const T, dstp: []T, refp: [] } } - dstp[i] = ((PBFICk[k + 1] - refp[i]) * PBFIC[k][i] + (refp[i] - PBFICk[k]) * PBFIC[k + 1][i]) / (PBFICk[k + 1] - PBFICk[k]); + const iF: f32 = refp[i]; + const PBFICk0F: f32 = PBFICk[k]; + const PBFICk1F: f32 = PBFICk[k + 1]; + dstp[i] = @floatCast(((PBFICk1F - iF) * PBFIC[k][i] + (iF - PBFICk0F) * PBFIC[k + 1][i]) / (PBFICk1F - PBFICk0F)); } } @@ -301,16 +304,16 @@ pub fn bilateralAlg2Float(comptime T: type, dst: []T, src: []const T, gs_lut: [] const cxx4: T = srcbuff[tmp2 - tmp3 + xx]; const swei = gs_lut[yy * radius2 + xx]; - const rwei1 = gr_lut[@intFromFloat(@abs(cx - cxx1) * 65535 + 0.5)]; - const rwei2 = gr_lut[@intFromFloat(@abs(cx - cxx2) * 65535 + 0.5)]; - const rwei3 = gr_lut[@intFromFloat(@abs(cx - cxx3) * 65535 + 0.5)]; - const rwei4 = gr_lut[@intFromFloat(@abs(cx - cxx4) * 65535 + 0.5)]; + const rwei1 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx1)) * 65535 + 0.5)]; + const rwei2 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx2)) * 65535 + 0.5)]; + const rwei3 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx3)) * 65535 + 0.5)]; + const rwei4 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx4)) * 65535 + 0.5)]; weight_sum += swei * (rwei1 + rwei2 + rwei3 + rwei4); sum += swei * (cxx1 * rwei1 + cxx2 * rwei2 + cxx3 * rwei3 + cxx4 * rwei4); } } - dstp[x] = sum / weight_sum; + dstp[x] = @floatCast(sum / weight_sum); } srcp = srcp[stride..]; dstp = dstp[stride..]; @@ -360,16 +363,16 @@ pub fn bilateralAlg2RefFloat(comptime T: type, dst: []T, src: []const T, ref: [] const cxx4f: f32 = srcbuff[tmp2 - tmp3 + xx]; const swei = gs_lut[yy * radius2 + xx]; - const rwei1 = gr_lut[@intFromFloat(@abs(cx - cxx1r) * 65535 + 0.5)]; - const rwei2 = gr_lut[@intFromFloat(@abs(cx - cxx2r) * 65535 + 0.5)]; - const rwei3 = gr_lut[@intFromFloat(@abs(cx - cxx3r) * 65535 + 0.5)]; - const rwei4 = gr_lut[@intFromFloat(@abs(cx - cxx4r) * 65535 + 0.5)]; + const rwei1 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx1r)) * 65535 + 0.5)]; + const rwei2 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx2r)) * 65535 + 0.5)]; + const rwei3 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx3r)) * 65535 + 0.5)]; + const rwei4 = gr_lut[@intFromFloat(@as(f32, @abs(cx - cxx4r)) * 65535 + 0.5)]; weight_sum += swei * (rwei1 + rwei2 + rwei3 + rwei4); sum += swei * (cxx1f * rwei1 + cxx2f * rwei2 + cxx3f * rwei3 + cxx4f * rwei4); } } - dstp[x] = sum / weight_sum; + dstp[x] = @floatCast(sum / weight_sum); } srcp = srcp[stride..]; refp = refp[stride..]; diff --git a/src/helper.zig b/src/helper.zig index eb88ee6..dee82c9 100644 --- a/src/helper.zig +++ b/src/helper.zig @@ -4,10 +4,39 @@ const vs = vszip.vs; const vsh = vszip.vsh; const zapi = vszip.zapi; -pub const DataType = enum(c_int) { - U8 = 1, - U16 = 2, - F32 = 4, +pub const DataType = enum { + U8, + U16, + F16, + F32, + + pub fn select(map: zapi.Map, node: ?*vs.Node, vi: *const vs.VideoInfo, comptime name: []const u8) !DataType { + var err_msg: ?[*]const u8 = null; + errdefer { + map.vsapi.?.mapSetError.?(map.out, err_msg.?); + map.vsapi.?.freeNode.?(node); + } + + if (vi.format.sampleType == .Integer) { + switch (vi.format.bytesPerSample) { + 1 => return .U8, + 2 => return .U16, + else => return { + err_msg = name ++ ": not supported Int format."; + return error.format; + }, + } + } else { + switch (vi.format.bytesPerSample) { + 2 => return .F16, + 4 => return .F32, + else => return { + err_msg = name ++ ": not supported Float format."; + return error.format; + }, + } + } + } }; pub fn absDiff(x: anytype, y: anytype) @TypeOf(x) {