const std = @import("std"); const omt = @cImport(@cInclude("libomt.h")); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); std.log.info("Sending...", .{}); omt.omt_setloggingfilename("omtsendtest.log"); const sender = omt.omt_send_create("Omtoy Sender", omt.OMTQuality_Default) orelse undefined; defer omt.omt_send_destroy(sender); std.log.info("Sender created: Omtoy Sender", .{}); { var sender_info = std.mem.zeroes(omt.OMTSenderInfo); const product_name = "Omtoy"; const manufacturer = "Kasper Toy Productions"; const version = "0.1"; @memcpy(sender_info.ProductName[0..product_name.len], product_name); @memcpy(sender_info.Manufacturer[0..manufacturer.len], manufacturer); @memcpy(sender_info.Version[0..version.len], version); omt.omt_send_setsenderinformation(sender, &sender_info); } const width = 1920; const height = 1080; const stride = width * 2; const data_length = stride * height; const frame_buffer = allocator.alloc(u8, data_length) catch undefined; defer allocator.free(frame_buffer); var video_frame = omt.OMTMediaFrame{ .Type = omt.OMTFrameType_Video, .Width = width, .Height = height, .Codec = omt.OMTCodec_UYVY, .Timestamp = -1, .ColorSpace = omt.OMTColorSpace_BT709, .Flags = omt.OMTVideoFlags_None, .Stride = width * 2, .DataLength = width * 2 * height, .Data = @ptrCast(frame_buffer), .FrameRateN = 60000, .FrameRateD = 1000, .AspectRatio = @as(f32, width) / @as(f32, height), .CompressedData = null, .CompressedLength = 0, .FrameMetadata = null, .FrameMetadataLength = 0, }; const content = try std.fs.cwd().readFileAlloc("california-1080-uyvy.yuv", allocator, .unlimited); defer allocator.free(content); const audio_samples = 800; const audio_buffer = try allocator.alloc(f32, audio_samples); defer allocator.free(audio_buffer); var prng = std.Random.DefaultPrng.init(80085); const rng = prng.random(); fillAudioBuffer(rng, audio_buffer); var audio_frame = omt.OMTMediaFrame{ .Type = omt.OMTFrameType_Audio, .Timestamp = -1, .Codec = omt.OMTCodec_FPA1, .SampleRate = 48000, .Channels = 2, .SamplesPerChannel = audio_samples, .Data = @ptrCast(audio_buffer), .DataLength = @intCast(audio_buffer.len * 2), .FrameMetadata = null, .FrameMetadataLength = 0, }; var tally = omt.OMTTally{ .preview = 0, .program = 0 }; var stats = std.mem.zeroes(omt.OMTStatistics); var frame_count: i32 = 0; var bytes: i32 = 0; const two_lines_len = stride * 2; const two_lines = try allocator.alloc(u8, two_lines_len); defer allocator.free(two_lines); @memset(two_lines, 255); var line_position: usize = 0; // send 10000 frames while (frame_count < 10000) : (frame_count += 1) { @memcpy(frame_buffer, content); const two_lines_slice = frame_buffer[line_position..(line_position + two_lines_len)]; @memcpy(two_lines_slice, two_lines[0..two_lines_len]); line_position += stride * 2; if (line_position >= video_frame.DataLength) { line_position = 0; } bytes += omt.omt_send(sender, &video_frame); if (@mod(frame_count, 60) == 0) { std.log.info("sent: {}", .{bytes}); _ = omt.omt_send_gettally(sender, 0, &tally); std.log.info("tally preview: {}, program: {}", .{ tally.preview, tally.program }); const frame = omt.omt_send_receive(sender, 0); if (frame != null) { const metadata = frame.*.Data; if (metadata != null) { const metastr = @as([]u8, @ptrCast(metadata)); std.log.info("meta: {s}", .{metastr}); } } const connections = omt.omt_send_connections(sender); std.log.info("connections: {}", .{connections}); omt.omt_send_getvideostatistics(sender, &stats); std.log.info("statistics sent bytes: {}, frames: {}", .{ stats.BytesSent, stats.Frames }); } _ = omt.omt_send(sender, &audio_frame); fillAudioBuffer(rng, audio_buffer); } } fn fillAudioBuffer(rng: std.Random, buffer: []f32) void { for (buffer) |*val| { val.* = rng.float(f32) * 2 - 1.0; } }