GStreamer Java Binding cleanup issue after playback from AppSrc

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

GStreamer Java Binding cleanup issue after playback from AppSrc

superrei

I'm trying to use GStreamer Java Binding on Raspberry Pi to play some dynamic audio data which is Opus encoded. I'm almost done. My final issue is I cannot have GStreamer clean up nicely when the data reaching the end. My testing code is as below.

    
    package org.freedesktop.gstreamer.examples;
   
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.nio.ByteBuffer;
   
    import javax.swing.JFrame;
    import org.freedesktop.gstreamer.Bin;
    import org.freedesktop.gstreamer.Buffer;
    import org.freedesktop.gstreamer.Bus;
    import org.freedesktop.gstreamer.Element;
    import org.freedesktop.gstreamer.ElementFactory;
    import org.freedesktop.gstreamer.FlowReturn;
    import org.freedesktop.gstreamer.Gst;
    import org.freedesktop.gstreamer.GstObject;
    import org.freedesktop.gstreamer.Message;
    import org.freedesktop.gstreamer.Pad;
    import org.freedesktop.gstreamer.PadLinkReturn;
    import org.freedesktop.gstreamer.Pipeline;
    import org.freedesktop.gstreamer.State;
    import org.freedesktop.gstreamer.elements.AppSrc;
    import org.freedesktop.gstreamer.lowlevel.MainLoop;
   
    /**
     *
     * @author Superrei
     */
    public class AudioTest {
       
        //private static final int BUFFER_SIZE = 4096;
        private static byte[] soundBytes = null;
        private static int pointer = 0;
        private static String filename = null;
   
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
   
            Gst.init("AudioTest", args);
            filename = args[0];
            EventQueue.invokeLater(new Runnable() {
   
                @Override
                public void run() {
                    File soundFile = new File(filename);
                    FileInputStream inStream = null;
                   
                    if (soundFile.exists()){
                        try {
                            System.out.println("Read media file.");
                            long fileSize = soundFile.length();
                            soundBytes = new byte[(int)fileSize];
                            inStream = new FileInputStream(soundFile);
                            int byteCount = inStream.read(soundBytes);
                            System.out.println("Number of byte read: " + byteCount);
                        } catch (IOException e) {
                            e.printStackTrace();
                            return;
                        }
                    }
                    final MainLoop loop = new MainLoop();
                    AppSrc source = (AppSrc)ElementFactory.make("appsrc", "app-source");
                    Element demuxer = ElementFactory.make("oggdemux", "ogg-demuxer");
                    final Element decoder = ElementFactory.make("opusdec", "opus-decoder");
                    Element conv = ElementFactory.make("audioconvert", "converter");
                    Element sink = ElementFactory.make("autoaudiosink", "audio-output");
                   
                    //source.set("location", "/home/pi/gstJavaTest/transcript.ogg");
                   
                    Pipeline pipe = new Pipeline();
                    Bus bus = pipe.getBus();
                    bus.connect(new Bus.EOS() {
   
                        @Override
                        public void endOfStream(GstObject source) {
                            loop.quit();
                        }
                       
                    });
                    bus.connect(new Bus.ERROR() {
                       
                        @Override
                        public void errorMessage(GstObject source, int code, String message) {
                            System.out.println("Error detected");
                            System.out.println("Error source: " + source.getName());
                            System.out.println("Error code: " + code);
                            System.out.println("Message: " + message);
                            loop.quit();
                        }
                    });
                   
                    pipe.addMany(source, demuxer, decoder, conv, sink);
                    source.link(demuxer);
                    source.set("emit-signals", true);
                    source.connect(new AppSrc.NEED_DATA() {
   
                        private ByteBuffer bb = ByteBuffer.wrap(soundBytes);
                       
                        @Override
                        public void needData(AppSrc elem, int size) {
                            if (bb.hasRemaining()) {
                                // TODO Auto-generated method stub
                                System.out.println("needData: size = " + size);
                                byte[] tempBuffer;
                                Buffer buf;
                                if (bb.remaining() > size) {
                                    tempBuffer = new byte[size];
                                    buf = new Buffer(size);
                                } else {
                                    tempBuffer = new byte[bb.remaining()];
                                    buf = new Buffer(bb.remaining());
                                }
                                //System.out.println("Buffer size: " + buf.map(true).remaining());
                                //System.arraycopy(soundBytes, pointer, tempBuffer, 0, size);
                                bb.get(tempBuffer);
                                System.out.println("Temp Buffer remaining bytes: " + bb.remaining());
                                buf.map(true).put(ByteBuffer.wrap(tempBuffer));
                                elem.pushBuffer(buf);
                            } else {
                                elem.emit("end-of-stream", elem);
                            }
                            //pointer += size;
                        }
                    });
                   
                    source.connect(new AppSrc.ENOUGH_DATA() {
                       
                        @Override
                        public void enoughData(AppSrc elem) {
                            System.out.println("enoughData: " + elem.toString());
                           
                        }
                    });
                    source.connect(new AppSrc.END_OF_STREAM() {
                       
                        @Override
                        public FlowReturn endOfStream(AppSrc elem) {
                            // TODO Auto-generated method stub
                            return FlowReturn.OK;
                        }
                    });
                    Element.linkMany(decoder, conv, sink);
                    demuxer.connect(new Element.PAD_ADDED() {
   
                        @Override
                        public void padAdded(Element element, Pad pad) {
                            System.out.println("Dynamic pad created, linking demuxer/decoder");
                            System.out.println("Pad name: " + pad.getName());
                            System.out.println("Pad type: " + pad.getTypeName());
                            Pad sinkPad = decoder.getStaticPad("sink");
                            //boolean linked = element.link(decoder);
                            PadLinkReturn ret = pad.link(sinkPad);
                            if (ret.equals(PadLinkReturn.OK)){
                                System.out.println("Pad linked.");
                            } else {
                                System.out.println("Pad link failed");
                            }
                            //System.out.println("Pad Link Return: " + ret.toString());
                        }
                       
                    });
                   
                    System.out.println("Now Playing...");
                    pipe.play();
                    System.out.println("Running...");
                    loop.run();
                    System.out.println("Returned, stopping playback");
                    pipe.stop();
                }
            });
        }
   
    }


I don't use playbin since the audio data will come from byte stream finally.

The test runs well until the end. When I reach the end of file. I get error messages and follow by JVM crush. The error message is like this:


    (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
   
    (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

    Returned, stopping playback
   
    (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
   
    (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
   
    (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
   
    (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
   
    (AudioTest:4643): GLib-GObject-CRITICAL **: g_value_set_object: assertion 'G_IS_OBJECT (v_object)' failed
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  SIGSEGV (0xb) at pc=0x63d8b8ec, pid=4643, tid=1658819680
    #
    # JRE version: Java(TM) SE Runtime Environment (8.0_65-b17) (build
    1.8.0_65-b17)
    # Java VM: Java HotSpot(TM) Client VM (25.65-b01 mixed mode linux-arm )
    # Problematic frame:
    # C  [libglib-2.0.so.0+0x928ec]  g_rec_mutex_lock+0x8
    #
    # Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
    #
    # An error report file with more information is saved as:
    # /home/pi/gstJavaTest/hs_err_pid4643.log
    #
    # If you would like to submit a bug report, please visit:
    #   http://bugreport.java.com/bugreport/crash.jsp
    # The crash happened outside the Java Virtual Machine in native code.
    # See problematic frame for where to report the bug.
    # Aborted

I cannot find any example on using AppSrc to play something with an end. Any help will be appreciated. Thank you.



_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: GStreamer Java Binding cleanup issue after playback from AppSrc

Sebastian Dröge-3
On Di, 2016-05-31 at 21:26 +0800, Alex Hui wrote:
> I'm trying to use GStreamer Java Binding on Raspberry Pi to play some
> dynamic audio data which is Opus encoded. I'm almost done. My final
> issue is I cannot have GStreamer clean up nicely when the data
> reaching the end. My testing code is as below.
> [...]
>     (AudioTest:4643): GLib-GObject-CRITICAL **: g_object_unref:
> assertion 'G_IS_OBJECT (object)' failed

This would be a bug in the Java bindings. You don't do any explicit
reference counting (and shouldn't!), it's the Java binding's job to do
that correctly.

Please report that to the GStreamer Java project, thanks!

--
Sebastian Dröge, Centricular Ltd · http://www.centricular.com
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

signature.asc (968 bytes) Download Attachment