moved files from gstreamer minimal example
This commit is contained in:
parent
972fd2eeb8
commit
304e065762
5 changed files with 339 additions and 2 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,6 +1,6 @@
|
||||||
# ---> Zig
|
# ---> Zig
|
||||||
zig-cache/
|
.zig-cache/*
|
||||||
zig-out/
|
zig-out/*
|
||||||
build/
|
build/
|
||||||
build-*/
|
build-*/
|
||||||
docgen_tmp/
|
docgen_tmp/
|
||||||
|
|
81
build.zig
Normal file
81
build.zig
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
// Although this function looks imperative, note that its job is to
|
||||||
|
// declaratively construct a build graph that will be executed by an external
|
||||||
|
// runner.
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard optimization options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||||
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "zig-gst",
|
||||||
|
.root_source_file = b.path("src/main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
|
// These environment vars are set with the `nix develop` command
|
||||||
|
const gst_dev_path = b.graph.env_map.get("GST_DEV_PATH");
|
||||||
|
const glib_dev_path = b.graph.env_map.get("GLIB_DEV_PATH");
|
||||||
|
const glib_path = b.graph.env_map.get("GLIB_PATH");
|
||||||
|
|
||||||
|
if (gst_dev_path == null) {
|
||||||
|
std.debug.panic("GST_DEV_PATH environment variable was not set. Has the nix flake been updated? This should point at the gstreamer.XXX-dev folder", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glib_dev_path == null) {
|
||||||
|
std.debug.panic("GLIB_DEV_PATH environment variable was not set. Has the nix flake been updated? This should point at the glib.XXX-dev folder", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glib_path == null) {
|
||||||
|
std.debug.panic("GLIB_PATH environment variable was not set. Has the nix flake been updated? This should point at the glib.XXX folder", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
exe.linkSystemLibrary("c");
|
||||||
|
exe.addIncludePath(.{ .cwd_relative = b.fmt("{s}/include/gstreamer-1.0", .{gst_dev_path.?}) }); // not sure why both are needed, but
|
||||||
|
exe.addIncludePath(.{ .cwd_relative = b.fmt("{s}/include/gstreamer-1.0/gst", .{gst_dev_path.?}) }); // it won't compile without them
|
||||||
|
exe.addIncludePath(.{ .cwd_relative = b.fmt("{s}/include/glib-2.0", .{glib_dev_path.?}) });
|
||||||
|
exe.addIncludePath(.{ .cwd_relative = b.fmt("{s}/lib/glib-2.0/include", .{glib_path.?}) });
|
||||||
|
|
||||||
|
|
||||||
|
exe.linkSystemLibrary("gstreamer-1.0");
|
||||||
|
exe.linkSystemLibrary("glib-2.0");
|
||||||
|
exe.linkSystemLibrary("gobject-2.0");
|
||||||
|
|
||||||
|
// This declares intent for the executable to be installed into the
|
||||||
|
// standard location when the user invokes the "install" step (the default
|
||||||
|
// step when running `zig build`).
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
// This *creates* a Run step in the build graph, to be executed when another
|
||||||
|
// step is evaluated that depends on it. The next line below will establish
|
||||||
|
// such a dependency.
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
|
||||||
|
// By making the run step depend on the install step, it will be run from the
|
||||||
|
// installation directory rather than directly from within the cache directory.
|
||||||
|
// This is not necessary, however, if the application depends on other installed
|
||||||
|
// files, this ensures they will be present and in the expected location.
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
// This allows the user to pass arguments to the application in the build
|
||||||
|
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||||
|
// and can be selected like this: `zig build run`
|
||||||
|
// This will evaluate the `run` step rather than the default, which is "install".
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
}
|
147
flake.lock
Normal file
147
flake.lock
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1696426674,
|
||||||
|
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1726560853,
|
||||||
|
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1705309234,
|
||||||
|
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1727802920,
|
||||||
|
"narHash": "sha256-HP89HZOT0ReIbI7IJZJQoJgxvB2Tn28V6XS3MNKnfLs=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "27e30d177e57d912d614c88c622dcfdb2e6e6515",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1708161998,
|
||||||
|
"narHash": "sha256-6KnemmUorCvlcAvGziFosAVkrlWZGIc6UNT9GUYr0jQ=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "84d981bae8b5e783b3b548de505b22880559515f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-23.11",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"zig": "zig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zig": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1727656237,
|
||||||
|
"narHash": "sha256-qfZ7nYqYmzPc3Ei9hvWRrFu3Mn3WJ2akyYvaoPOOHcM=",
|
||||||
|
"owner": "mitchellh",
|
||||||
|
"repo": "zig-overlay",
|
||||||
|
"rev": "5bdd678ad99cd0069dfa6a5822c1d82d45d34ad2",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "mitchellh",
|
||||||
|
"repo": "zig-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
34
flake.nix
Normal file
34
flake.nix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
zig.url = "github:mitchellh/zig-overlay";
|
||||||
|
flake-utils = { url = "github:numtide/flake-utils"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, zig, flake-utils, ... }:
|
||||||
|
flake-utils.lib.eachDefaultSystem(system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
zig_exe = zig.packages.${system}.master;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
zig_exe
|
||||||
|
glib
|
||||||
|
glib.dev
|
||||||
|
gst_all_1.gstreamer
|
||||||
|
gst_all_1.gstreamer.dev
|
||||||
|
gst_all_1.gst-plugins-base
|
||||||
|
gst_all_1.gst-plugins-good
|
||||||
|
];
|
||||||
|
|
||||||
|
GST_DEV_PATH = pkgs.gst_all_1.gstreamer.dev;
|
||||||
|
GLIB_DEV_PATH = pkgs.glib.dev;
|
||||||
|
GLIB_PATH = pkgs.glib.out;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
75
src/main.zig
Normal file
75
src/main.zig
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const gst = @cImport({ // glib-object for g_object_* functions
|
||||||
|
@cInclude("glib-object.h");
|
||||||
|
@cInclude("gst.h");
|
||||||
|
@cInclude("glib.h"); // and glib for other g_* functions
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn main() void {
|
||||||
|
// This allows me to utilize the same command line args and gstreamer
|
||||||
|
gst.gst_init(@ptrCast(&std.os.argv.len), @ptrCast(&std.os.argv.ptr));
|
||||||
|
|
||||||
|
const source: ?*gst.GstElement = gst.gst_element_factory_make("videotestsrc", "source");
|
||||||
|
const sink: ?*gst.GstElement = gst.gst_element_factory_make("autovideosink", "sink");
|
||||||
|
|
||||||
|
const pipeline: ?*gst.GstElement = gst.gst_pipeline_new("test-pipeline");
|
||||||
|
|
||||||
|
if (source == null or sink == null or pipeline == null) {
|
||||||
|
std.debug.panic("Not all elements could be created!", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
// When you look into the GST_BIN macro that zig can't compile,
|
||||||
|
// it really is just this pointer cast with extra steps of verification
|
||||||
|
const bin: *gst.GstBin = @ptrCast(pipeline);
|
||||||
|
|
||||||
|
|
||||||
|
// Gstreamer gives a critical warning when using gst.gst_bin_add_many, but doesn't
|
||||||
|
// when calling each individually
|
||||||
|
_ = gst.gst_bin_add(bin, source);
|
||||||
|
_ = gst.gst_bin_add(bin, sink);
|
||||||
|
|
||||||
|
// the failure return code is -1 I believe
|
||||||
|
if (gst.gst_element_link(source, sink) < 0) {
|
||||||
|
gst.gst_object_unref(pipeline);
|
||||||
|
std.debug.panic("Elements could not be linked\n", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
// g_int is just i32. You can
|
||||||
|
gst.g_object_set(source, "pattern", @as(i16, 0));
|
||||||
|
|
||||||
|
const ret = gst.gst_element_set_state(pipeline, gst.GST_STATE_PLAYING);
|
||||||
|
if (ret == gst.GST_STATE_CHANGE_FAILURE) {
|
||||||
|
gst.gst_object_unref(pipeline);
|
||||||
|
std.debug.panic("Could not start pipeline", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
const bus: *gst.GstBus = gst.gst_element_get_bus(pipeline);
|
||||||
|
const msg: *gst.GstMessage = gst.gst_bus_timed_pop_filtered( // This call holds until there is a valid message
|
||||||
|
bus,
|
||||||
|
gst.GST_CLOCK_TIME_NONE,
|
||||||
|
gst.GST_MESSAGE_ERROR | gst.GST_MESSAGE_EOS,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (gst.GST_MESSAGE_TYPE(msg) == gst.GST_MESSAGE_ERROR) {
|
||||||
|
const err: [*c][*c]gst.GError = null;
|
||||||
|
var debug_info: ?*gst.gchar = null;
|
||||||
|
|
||||||
|
switch (gst.GST_MESSAGE_TYPE(msg)) {
|
||||||
|
gst.GST_MESSAGE_ERROR => {
|
||||||
|
gst.gst_message_parse_error(msg, err, &debug_info);
|
||||||
|
std.debug.print("Error received from element {s}: {s}", .{ gst.GST_OBJECT_NAME(msg.src), err.*.*.message });
|
||||||
|
if (debug_info != null) { // I couldn't figure out how to do a orelse statement for this unwrap.
|
||||||
|
std.debug.print("Debugging information: {s}", .{debug_info.?});
|
||||||
|
}
|
||||||
|
gst.g_clear_error(err);
|
||||||
|
gst.g_free(debug_info);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
gst.gst_message_unref(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst.gst_object_unref(bus);
|
||||||
|
_ = gst.gst_element_set_state(pipeline, gst.GST_STATE_NULL);
|
||||||
|
gst.gst_object_unref(pipeline);
|
||||||
|
}
|
Loading…
Reference in a new issue