GirCore.Gst-1.0 Doesn't work on linux-arm
Describe the bug
When trying to play a video file or connect to an Ip camera, GStreamer does not start and sends a lot of WARNING.
Expected behavior
Successful connection to the camera and video playback.
Steps to Reproduce
In general, it is unknown. Try to run on the Linux arm platform... Right now I can only test on a device with an i.MX6Q processor.
Detailed Description
If you use gst-launch-1.0, then everything works fine. Here are examples of commands:
gst-launch-1.0 playbin uri=playbin uri=file:///opt/Costa_Rica_HD_25Fps.avi
gst-launch-1.0 filesrc location=/opt/Costa_Rica_HD_25Fps.avi ! decodebin ! autovideosink
Also worked fine when using gstreamer-sharp: https://github.com/vladkol/gstreamer-netcore
Test project source code: https://github.com/utlark/GirCoreArm Log files: https://github.com/utlark/GirCoreArm/tree/master/!res
Gir-log are logs that were received simply when the program was started. Full-log were received after exporting GST_DEBUG="*:6".
Environment
- OS: Embedded Linux
- CPU: i.MX6Q
- IDE: JetBrains Rider
- GirCore.Gst-1.0: 0.4.0 and 0.5.0-preview.2
Hm hard to say what is wrong.
Are you sure your platform is supported (https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md)? Especially in regard to glibc?
As the messages are coming from gst someone would need to understand what they actually mean. Sounds a bit like wrong states.
Which version of GStreamer are you using? If there are version mismatch's it could explain the problems.
The nuget packages are created for 3 platforms: MSYS2 (windows), Brew (Mac) and Flatpak (Linux gnome sdk). The code originates from some xml files. If those Gir files do not match your system things can go wrong.
So you could try to compile the bindings with the Gir files of your system.
Since this is Embedded Linux, everything is built from source, in our case through the Buildroot build system.
ASP.NET Core Runtime is downloaded from the official website: https://dotnet.microsoft.com/en-us/download/dotnet/6.0
Although in this case I used a self-contained assembly. In general, this is due to some difficulties updating the system, but recently our main application also works as self-contained and no problems arise.
So, the platform seems to be quite supported.
As for the versions, tests were carried out on two systems. The old system had glibc 2.29-30 and GStreamer 1.16.0. The new system has glibc 2.37-45 and GStreamer 1.22.6.
GStreamer sources for the new system: https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.22.6.tar.xz
Alright, I'll try to compile the binding with the Gir files of our system tomorrow.
Yes you can try to build it yourself.
From the gst version point of view your binaries are newer than the ones the nuget packages are referencing (see gir_files.txt). (The version in the txt file defines the version which is not going to be used: so it references the newest version which is older than the one mentioned in the file.) This is fine as GStreamer should be backwards compatible.
Alternatively to building yourself, you could try to manually write the bindings for the native methods. As you only need very few methods in your sample it should be pretty easy:
- For objects just use
IntPtras data type. - strings need to be converted to utf8 and ownership transfer needs to be taken into account. String helper classes are here.
Perhaps you get it working manually and we can figure out the differences to the generated code and fix Gir.core afterwards.
Eventually, I did manage to figure out what the problem was.
Initially spent a lot of time trying to rebuild the project using different Gir files, but it didn't produce any results. Then I tried to write the binding manually, and this immediately revealed the error.
And as usual, the Gstreamer log told me about the error, but I couldn't understand it without the right knowledge.
(<unknown>:525): GStreamer-WARNING **: 00:39:44.489: Unhandled state change from UNKNOWN!(536870911) to UNKNOWN!(7)
In this case, the problem is with the SetState method:
[[DllImport(ImportResolver.Library, EntryPoint = "gst_element_set_state")]
public static extern Gst.StateChangeReturn SetState(IntPtr element, Gst.State state);
Namely, in the State enumeration:
public enum State : long
{
VoidPending = 0,
Null = 1,
Ready = 2,
Paused = 3,
Playing = 4,
}
i.MX6Q is a 32 bit processor, and when trying to pass a long data type to SetState, nothing works. But if you replace long with uint, everything works in this simple example. I have checked both with manual binding and with correcting the generated code, but only with this enumeration.
So maybe it's not a Linux-ARM problem, but a x32 system problem.
Thank you for reporting back. To workaround your problem I would suggest that you implement the broken function manually (like in your test) including a fixed implementation of the enum.
I think there was some reason why enums are implemented as long but I can't remember right now. If you are interested in this topic you could try to update the generator (Enumeration.cs) and perhaps find a solution which works for 64 and 32 bit systems.
@utlark in release 0.5.0-preview.4 enums got rebased on int and bitfields on uint.
Can you check if your problem is solved?