Exemplo n.º 1
0
 public static extern void gst_buffer_unmap(IntPtr buffer, out GstMapInfo info);
Exemplo n.º 2
0
        public static void test()
        {
            string pathvar = System.Environment.GetEnvironmentVariable("PATH");

            System.Environment.SetEnvironmentVariable("PATH",
                                                      pathvar +
                                                      @";C:\gstreamer\1.0\x86_64\bin\;D:\gstreamer\1.0\x86_64\bin\;E:\gstreamer\1.0\x86_64\bin\;F:\gstreamer\1.0\x86_64\bin\");
            pathvar = System.Environment.GetEnvironmentVariable("PATH");
            System.Environment.SetEnvironmentVariable("PATH",
                                                      pathvar +
                                                      @";C:\gstreamer\1.0\x86\bin\;D:\gstreamer\1.0\x86\bin\;E:\gstreamer\1.0\x86\bin\;F:\gstreamer\1.0\x86\bin\");

            gst_init(IntPtr.Zero, IntPtr.Zero);

            IntPtr error;

            gst_init_check(IntPtr.Zero, IntPtr.Zero, out error);

            uint v1 = 0, v2 = 0, v3 = 0, v4 = 0;

            gst_version(ref v1, ref v2, ref v3, ref v4);

            /* Set up the pipeline */

            var pipeline = gst_parse_launch(
                //@"videotestsrc ! video/x-raw, width=1280, height=720, framerate=30/1 ! clockoverlay ! x264enc speed-preset=1 threads=1 sliced-threads=1 mb-tree=0 rc-lookahead=0 sync-lookahead=0 bframes=0 ! rtph264pay ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                @"-v udpsrc port=5601 buffer-size=300000 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                out error);

            Console.WriteLine(error);

            var appsink = gst_bin_get_by_name(pipeline, "outsink");

            /* Start playing */
            gst_element_set_state(pipeline, GstState.GST_STATE_PLAYING);

            gst_app_sink_set_max_buffers(appsink, 5);

            /* Wait until error or EOS */
            var bus = gst_element_get_bus(pipeline);
            //var msg = GStreamer.gst_bus_timed_pop_filtered(bus, GStreamer.GST_CLOCK_TIME_NONE, GStreamer.GstMessageType.GST_MESSAGE_ERROR | GStreamer.GstMessageType.GST_MESSAGE_EOS);

            int Width  = 0;
            int Height = 0;

            while (true)
            {
                var sample = gst_app_sink_try_pull_sample(appsink, GST_SECOND);
                if (sample != IntPtr.Zero)
                {
                    //var caps = gst_app_sink_get_caps(appsink);
                    var caps   = gst_sample_get_caps(sample);
                    var caps_s = gst_caps_get_structure(caps, 0);
                    gst_structure_get_int(caps_s, "width", out Width);
                    gst_structure_get_int(caps_s, "height", out Height);

                    //var capsstring = gst_caps_to_string(caps_s);
                    //var structure = gst_sample_get_info(sample);
                    //var structstring = gst_structure_to_string(structure);
                    var buffer = gst_sample_get_buffer(sample);
                    if (buffer != IntPtr.Zero)
                    {
                        var info = new GstMapInfo();
                        if (gst_buffer_map(buffer, out info, GstMapFlags.GST_MAP_READ))
                        {
                            //byte[] data = new byte[info.size];
                            //Marshal.Copy(info.data, data, 0, (int) info.size);

                            var image = new Bitmap(Width, Height, 4 * Width, System.Drawing.Imaging.PixelFormat.Format32bppArgb, info.data);

                            FlightData.myhud.bgimage = image;

                            //image.Save("image.bmp");

                            //gst_mini_object_unref(info.memory);

                            gst_buffer_unmap(buffer, out info);
                        }
                        // gst_buffer_unref(buffer);
                        //gst_mini_object_unref(buffer);
                    }
                    //gst_mini_object_unref(sample);
                    gst_sample_unref(sample);
                }

                //image.Save("image.bmp");



                //image.Save("image2.bmp");

                //File.WriteAllBytes("image.raw", data);
            }

            /*
             * fixed (byte* data = new byte[info.size])
             * {
             *  File.WriteAllBytes("image.raw", data);
             * }
             */
        }
Exemplo n.º 3
0
 public static extern bool gst_buffer_map(IntPtr buffer, out GstMapInfo info, GstMapFlags GstMapFlags);
Exemplo n.º 4
0
        public static void StartA(string stringpipeline)
        {
            int argc = 1;

            string[] argv = new string[] { "-vvv" };

            NativeMethods.gst_init(ref argc, argv);

            IntPtr error;

            NativeMethods.gst_init_check(IntPtr.Zero, IntPtr.Zero, out error);

            if (error != IntPtr.Zero)
            {
                var er = Marshal.PtrToStructure <GError>(error);
                log.Error("gst_init_check: " + er.message);
                return;
            }

            uint v1 = 0, v2 = 0, v3 = 0, v4 = 0;

            NativeMethods.gst_version(ref v1, ref v2, ref v3, ref v4);

            log.InfoFormat("GStreamer {0}.{1}.{2}.{3}", v1, v2, v3, v4);

            /* Set up the pipeline */

            var pipeline = NativeMethods.gst_parse_launch(
                stringpipeline,
                //@"videotestsrc ! video/x-raw, width=1280, height=720, framerate=30/1 ! x264enc speed-preset=1 threads=1 sliced-threads=1 mb-tree=0 rc-lookahead=0 sync-lookahead=0 bframes=0 ! rtph264pay ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                //@"-v udpsrc port=5601 buffer-size=300000 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                //@"rtspsrc location=rtsp://192.168.1.252/video1 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                out error);

            if (error != IntPtr.Zero)
            {
                var er = Marshal.PtrToStructure <GError>(error);
                log.Error("gst_parse_launch: " + er.message);
                return;
            }

            var appsink = NativeMethods.gst_bin_get_by_name(pipeline, "outsink");

            /* Start playing */
            NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_PLAYING);

            NativeMethods.gst_app_sink_set_max_buffers(appsink, 5);

            /* Wait until error or EOS */
            var bus = NativeMethods.gst_element_get_bus(pipeline);

            //var msg = GStreamer.gst_bus_timed_pop_filtered(bus, GStreamer.GST_CLOCK_TIME_NONE, GStreamer.GstMessageType.GST_MESSAGE_ERROR | GStreamer.GstMessageType.GST_MESSAGE_EOS);

            int Width  = 0;
            int Height = 0;
            int trys   = 0;

            while (true)
            {
                var sample = NativeMethods.gst_app_sink_try_pull_sample(appsink, GST_SECOND);
                if (sample != IntPtr.Zero)
                {
                    trys = 0;
                    //var caps = gst_app_sink_get_caps(appsink);
                    var caps   = NativeMethods.gst_sample_get_caps(sample);
                    var caps_s = NativeMethods.gst_caps_get_structure(caps, 0);
                    NativeMethods.gst_structure_get_int(caps_s, "width", out Width);
                    NativeMethods.gst_structure_get_int(caps_s, "height", out Height);

                    //var capsstring = gst_caps_to_string(caps_s);
                    //var structure = gst_sample_get_info(sample);
                    //var structstring = gst_structure_to_string(structure);
                    var buffer = NativeMethods.gst_sample_get_buffer(sample);
                    if (buffer != IntPtr.Zero)
                    {
                        var info = new GstMapInfo();
                        if (NativeMethods.gst_buffer_map(buffer, out info, GstMapFlags.GST_MAP_READ))
                        {
                            var image = new Bitmap(Width, Height, 4 * Width, System.Drawing.Imaging.PixelFormat.Format32bppArgb, info.data);

                            _onNewImage?.Invoke(null, image);

                            NativeMethods.gst_buffer_unmap(buffer, out info);
                        }
                    }
                    NativeMethods.gst_sample_unref(sample);
                }
                else
                {
                    log.Info("failed gst_app_sink_try_pull_sample");
                    trys++;
                    if (trys > 10)
                    {
                        break;
                    }
                }
            }

            NativeMethods.gst_buffer_unref(bus);
            NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_NULL);
            //NativeMethods.gst_buffer_unref(pipeline);

            log.Info("Gstreamer Exit");
        }
Exemplo n.º 5
0
        public static Thread StartA(string stringpipeline)
        {
            int argc = 1;

            string[] argv = new string[] { "-vvv" };

            try
            {
                //https://github.com/GStreamer/gstreamer/blob/master/tools/gst-launch.c#L1125
                NativeMethods.gst_init(ref argc, argv);
            }
            catch (DllNotFoundException ex)
            {
                CustomMessageBox.Show("The file was not found at " + gstlaunch +
                                      "\nPlease verify permissions " + ex.ToString());
                return(null);
            }
            catch (BadImageFormatException)
            {
                CustomMessageBox.Show("The incorrect exe architecture has been detected at " + gstlaunch +
                                      "\nPlease install gstreamer for the correct architecture");
                return(null);
            }

            uint v1 = 0, v2 = 0, v3 = 0, v4 = 0;

            NativeMethods.gst_version(ref v1, ref v2, ref v3, ref v4);

            log.InfoFormat("GStreamer {0}.{1}.{2}.{3}", v1, v2, v3, v4);

            IntPtr error;

            NativeMethods.gst_init_check(IntPtr.Zero, IntPtr.Zero, out error);

            if (error != IntPtr.Zero)
            {
                var er = Marshal.PtrToStructure <GError>(error);
                log.Error("gst_init_check: " + er.message);
                return(null);
            }

            /* Set up the pipeline */

            var pipeline = NativeMethods.gst_parse_launch(
                stringpipeline,
                //@"videotestsrc ! video/x-raw, width=1280, height=720, framerate=30/1 ! x264enc speed-preset=1 threads=1 sliced-threads=1 mb-tree=0 rc-lookahead=0 sync-lookahead=0 bframes=0 ! rtph264pay ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                //@"-v udpsrc port=5601 buffer-size=300000 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                //@"rtspsrc location=rtsp://192.168.1.252/video1 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                out error);

            //rtspsrc location=rtsp://192.168.1.21/live ! application/x-rtp ! rtph265depay ! avdec_h265 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink


            if (error != IntPtr.Zero)
            {
                var er = Marshal.PtrToStructure <GError>(error);
                log.Error("gst_parse_launch: " + er.message);
                return(null);
            }

            // appsink is part of the parse launch
            var appsink = NativeMethods.gst_bin_get_by_name(pipeline, "outsink");

            //var appsink = NativeMethods.gst_element_factory_make("appsink", null);

            bool newdata = false;
            GstAppSinkCallbacks callbacks = new GstAppSinkCallbacks();

            callbacks.new_buffer += (sink, data) =>
            {
                newdata = true;
                return(GstFlowReturn.GST_FLOW_OK);
            };
            callbacks.new_preroll += (sink, data) => { log.Info("new_preroll"); return(GstFlowReturn.GST_FLOW_OK); };
            callbacks.eos         += (sink, data) => { log.Info("EOS"); };

            NativeMethods.gst_app_sink_set_drop(appsink, true);
            NativeMethods.gst_app_sink_set_max_buffers(appsink, 1);
            NativeMethods.gst_app_sink_set_callbacks(appsink, callbacks, IntPtr.Zero, IntPtr.Zero);

            /* Start playing */
            var running = NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_PLAYING) != GstStateChangeReturn.GST_STATE_CHANGE_FAILURE;

            /* Wait until error or EOS */
            var bus = NativeMethods.gst_element_get_bus(pipeline);

            NativeMethods.gst_debug_bin_to_dot_file(pipeline, GstDebugGraphDetails.GST_DEBUG_GRAPH_SHOW_ALL,
                                                    "pipeline");

            log.Info("graphviz of pipeline is at " + Path.GetTempPath() + "pipeline.dot");

            //var msg = GStreamer.gst_bus_timed_pop_filtered(bus, GStreamer.GST_CLOCK_TIME_NONE, GStreamer.GstMessageType.GST_MESSAGE_ERROR | GStreamer.GstMessageType.GST_MESSAGE_EOS);

            int Width  = 0;
            int Height = 0;
            int trys   = 0;

            var th = new Thread(delegate()
            {
                // prevent it falling out of scope
                GstAppSinkCallbacks callbacks2 = callbacks;

                Thread.Sleep(500);

                run = true;

                while (run && !NativeMethods.gst_app_sink_is_eos(appsink))
                {
                    try
                    {
                        var sample = NativeMethods.gst_app_sink_try_pull_sample(appsink, GST_SECOND);
                        if (sample != IntPtr.Zero)
                        {
                            trys = 0;
                            //var caps = gst_app_sink_get_caps(appsink);
                            var caps   = NativeMethods.gst_sample_get_caps(sample);
                            var caps_s = NativeMethods.gst_caps_get_structure(caps, 0);
                            NativeMethods.gst_structure_get_int(caps_s, "width", out Width);
                            NativeMethods.gst_structure_get_int(caps_s, "height", out Height);

                            //var capsstring = gst_caps_to_string(caps_s);
                            //var structure = gst_sample_get_info(sample);
                            //var structstring = gst_structure_to_string(structure);
                            var buffer = NativeMethods.gst_sample_get_buffer(sample);
                            if (buffer != IntPtr.Zero)
                            {
                                var info = new GstMapInfo();
                                if (NativeMethods.gst_buffer_map(buffer, out info, GstMapFlags.GST_MAP_READ))
                                {
                                    var image = new Bitmap(Width, Height, 4 * Width,
                                                           SkiaSharp.SKColorType.Bgra8888, info.data);

                                    _onNewImage?.Invoke(null, image);
                                }
                                NativeMethods.gst_buffer_unmap(buffer, out info);
                            }

                            NativeMethods.gst_sample_unref(sample);
                        }
                        else
                        {
                            log.Info("failed gst_app_sink_try_pull_sample " + trys + "/60");
                            trys++;
                            if (trys > 60)
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex);
                        trys++;
                        if (trys > 60)
                        {
                            break;
                        }
                    }
                }

                NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_NULL);
                NativeMethods.gst_buffer_unref(bus);

                // cleanup
                _onNewImage?.Invoke(null, null);

                log.Info("Gstreamer Exit");
            })
            {
                IsBackground = true, Name = "gstreamer"
            };

            th.Start();

            return(th);
        }
Exemplo n.º 6
0
        public static Thread StartA(string stringpipeline)
        {
            int argc = 1;

            string[] argv = new string[] { "-vvv" };

            NativeMethods.gst_init(ref argc, argv);

            uint v1 = 0, v2 = 0, v3 = 0, v4 = 0;

            NativeMethods.gst_version(ref v1, ref v2, ref v3, ref v4);

            log.InfoFormat("GStreamer {0}.{1}.{2}.{3}", v1, v2, v3, v4);

            IntPtr error;

            NativeMethods.gst_init_check(IntPtr.Zero, IntPtr.Zero, out error);

            if (error != IntPtr.Zero)
            {
                var er = Marshal.PtrToStructure <GError>(error);
                log.Error("gst_init_check: " + er.message);
                return(null);
            }

            /* Set up the pipeline */

            var pipeline = NativeMethods.gst_parse_launch(
                stringpipeline,
                //@"videotestsrc ! video/x-raw, width=1280, height=720, framerate=30/1 ! x264enc speed-preset=1 threads=1 sliced-threads=1 mb-tree=0 rc-lookahead=0 sync-lookahead=0 bframes=0 ! rtph264pay ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                //@"-v udpsrc port=5601 buffer-size=300000 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                //@"rtspsrc location=rtsp://192.168.1.252/video1 ! application/x-rtp ! rtph264depay ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink",
                out error);

            //rtspsrc location=rtsp://192.168.1.21/live ! application/x-rtp ! rtph265depay ! avdec_h265 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink


            if (error != IntPtr.Zero)
            {
                var er = Marshal.PtrToStructure <GError>(error);
                log.Error("gst_parse_launch: " + er.message);
                return(null);
            }

            // appsink is part of the parse launch
            var appsink = NativeMethods.gst_bin_get_by_name(pipeline, "outsink");

            //var appsink = NativeMethods.gst_element_factory_make("appsink", null);

            int testdata = 0;
            GstAppSinkCallbacks callbacks = new GstAppSinkCallbacks();

            callbacks.new_buffer += (sink, data) => { return(GstFlowReturn.GST_FLOW_OK); };
            //callbacks.new_preroll += (sink, data) => { return GstFlowReturn.GST_FLOW_OK; };
            callbacks.eos += (sink, data) => { };

            NativeMethods.gst_app_sink_set_drop(appsink, true);
            NativeMethods.gst_app_sink_set_max_buffers(appsink, 1);
            NativeMethods.gst_app_sink_set_callbacks(appsink, callbacks, ref testdata, null);

            /* Start playing */
            NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_PLAYING);

            /* Wait until error or EOS */
            var bus = NativeMethods.gst_element_get_bus(pipeline);

            NativeMethods.gst_debug_bin_to_dot_file(pipeline, GstDebugGraphDetails.GST_DEBUG_GRAPH_SHOW_ALL,
                                                    "pipeline");

            //var msg = GStreamer.gst_bus_timed_pop_filtered(bus, GStreamer.GST_CLOCK_TIME_NONE, GStreamer.GstMessageType.GST_MESSAGE_ERROR | GStreamer.GstMessageType.GST_MESSAGE_EOS);

            int Width  = 0;
            int Height = 0;
            int trys   = 0;

            var th = new Thread(delegate()
            {
                while (!NativeMethods.gst_app_sink_is_eos(appsink))
                {
                    try
                    {
                        var sample = NativeMethods.gst_app_sink_try_pull_sample(appsink, GST_SECOND);
                        if (sample != IntPtr.Zero)
                        {
                            trys = 0;
                            //var caps = gst_app_sink_get_caps(appsink);
                            var caps   = NativeMethods.gst_sample_get_caps(sample);
                            var caps_s = NativeMethods.gst_caps_get_structure(caps, 0);
                            NativeMethods.gst_structure_get_int(caps_s, "width", out Width);
                            NativeMethods.gst_structure_get_int(caps_s, "height", out Height);

                            //var capsstring = gst_caps_to_string(caps_s);
                            //var structure = gst_sample_get_info(sample);
                            //var structstring = gst_structure_to_string(structure);
                            var buffer = NativeMethods.gst_sample_get_buffer(sample);
                            if (buffer != IntPtr.Zero)
                            {
                                var info = new GstMapInfo();
                                if (NativeMethods.gst_buffer_map(buffer, out info, GstMapFlags.GST_MAP_READ))
                                {
                                    var image = new Bitmap(Width, Height, 4 * Width,
                                                           SkiaSharp.SKColorType.Bgra8888, info.data);

                                    _onNewImage?.Invoke(null, image);

                                    NativeMethods.gst_buffer_unmap(buffer, out info);
                                }
                            }

                            NativeMethods.gst_sample_unref(sample);
                        }
                        else
                        {
                            log.Info("failed gst_app_sink_try_pull_sample");
                            trys++;
                            if (trys > 60)
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex);
                        trys++;
                        if (trys > 60)
                        {
                            break;
                        }
                    }
                }



                // cleanup
                _onNewImage?.Invoke(null, null);

                NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_NULL);
                NativeMethods.gst_buffer_unref(bus);

                log.Info("Gstreamer Exit");
            })
            {
                IsBackground = true, Name = "gstreamer"
            };

            th.Start();

            return(th);
        }
Exemplo n.º 7
0
        static void ThreadStart(object datao)
        {
            var pipeline = (IntPtr)datao;
            // appsink is part of the parse launch
            var appsink = NativeMethods.gst_bin_get_by_name(pipeline, "outsink");

            //var appsink = NativeMethods.gst_element_factory_make("appsink", null);

            bool newdata = false;
            GstAppSinkCallbacks callbacks = new GstAppSinkCallbacks();

            callbacks.new_buffer += (sink, data) =>
            {
                newdata = true;
                return(GstFlowReturn.GST_FLOW_OK);
            };
            callbacks.new_preroll += (sink, data) =>
            {
                log.Info("new_preroll");
                return(GstFlowReturn.GST_FLOW_OK);
            };
            callbacks.eos += (sink, data) => { log.Info("EOS"); };

            NativeMethods.gst_app_sink_set_drop(appsink, true);
            NativeMethods.gst_app_sink_set_max_buffers(appsink, 1);
            NativeMethods.gst_app_sink_set_callbacks(appsink, callbacks, IntPtr.Zero, IntPtr.Zero);

            /* Start playing */
            var running = NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_PLAYING) != GstStateChangeReturn.GST_STATE_CHANGE_FAILURE;

            /* Wait until error or EOS */
            var bus = NativeMethods.gst_element_get_bus(pipeline);

            int Width  = 0;
            int Height = 0;
            int trys   = 0;
            // prevent it falling out of scope
            GstAppSinkCallbacks callbacks2 = callbacks;

            run = true;

            while (run && !NativeMethods.gst_app_sink_is_eos(appsink))
            {
                try
                {
                    var sample = NativeMethods.gst_app_sink_try_pull_sample(appsink, GST_SECOND * 5);
                    if (sample != IntPtr.Zero)
                    {
                        trys = 0;
                        //var caps = gst_app_sink_get_caps(appsink);
                        var caps   = NativeMethods.gst_sample_get_caps(sample);
                        var caps_s = NativeMethods.gst_caps_get_structure(caps, 0);
                        NativeMethods.gst_structure_get_int(caps_s, "width", out Width);
                        NativeMethods.gst_structure_get_int(caps_s, "height", out Height);

                        //var capsstring = gst_caps_to_string(caps_s);
                        //var structure = gst_sample_get_info(sample);
                        //var structstring = gst_structure_to_string(structure);
                        var buffer = NativeMethods.gst_sample_get_buffer(sample);
                        if (buffer != IntPtr.Zero)
                        {
                            var info = new GstMapInfo();
                            if (NativeMethods.gst_buffer_map(buffer, out info, GstMapFlags.GST_MAP_READ))
                            {
                                var image = new Bitmap(Width, Height, 4 * Width, SkiaSharp.SKColorType.Bgra8888,
                                                       info.data);

                                _onNewImage?.Invoke(null, image);
                            }

                            NativeMethods.gst_buffer_unmap(buffer, out info);
                        }

                        NativeMethods.gst_sample_unref(sample);
                    }
                    else
                    {
                        log.Info("failed gst_app_sink_try_pull_sample " + trys + "");
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                    trys++;
                    if (trys > 12)
                    {
                        break;
                    }
                }
            }

            NativeMethods.gst_element_set_state(pipeline, GstState.GST_STATE_NULL);
            NativeMethods.gst_buffer_unref(bus);

            // cleanup
            _onNewImage?.Invoke(null, null);

            log.Info("Gstreamer Exit");
        }