<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <p>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.<br>
      <br>
           <br>
      <font face="Courier New, Courier, monospace" size="-1">    package
        org.freedesktop.gstreamer.examples;<br>
            <br>
            import java.awt.Dimension;<br>
            import java.awt.EventQueue;<br>
            import java.io.File;<br>
            import java.io.FileInputStream;<br>
            import java.io.FileNotFoundException;<br>
            import java.io.IOException;<br>
            import java.nio.ByteBuffer;<br>
            <br>
            import javax.swing.JFrame;<br>
            import org.freedesktop.gstreamer.Bin;<br>
            import org.freedesktop.gstreamer.Buffer;<br>
            import org.freedesktop.gstreamer.Bus;<br>
            import org.freedesktop.gstreamer.Element;<br>
            import org.freedesktop.gstreamer.ElementFactory;<br>
            import org.freedesktop.gstreamer.FlowReturn;<br>
            import org.freedesktop.gstreamer.Gst;<br>
            import org.freedesktop.gstreamer.GstObject;<br>
            import org.freedesktop.gstreamer.Message;<br>
            import org.freedesktop.gstreamer.Pad;<br>
            import org.freedesktop.gstreamer.PadLinkReturn;<br>
            import org.freedesktop.gstreamer.Pipeline;<br>
            import org.freedesktop.gstreamer.State;<br>
            import org.freedesktop.gstreamer.elements.AppSrc;<br>
            import org.freedesktop.gstreamer.lowlevel.MainLoop;<br>
            <br>
            /**<br>
             *<br>
             * @author Superrei<br>
             */<br>
            public class AudioTest {<br>
                <br>
                //private static final int BUFFER_SIZE = 4096;<br>
                private static byte[] soundBytes = null;<br>
                private static int pointer = 0;<br>
                private static String filename = null;<br>
            <br>
                /**<br>
                 * @param args the command line arguments<br>
                 */<br>
                public static void main(String[] args) {<br>
            <br>
                    Gst.init("AudioTest", args);<br>
                    filename = args[0];<br>
                    EventQueue.invokeLater(new Runnable() {<br>
            <br>
                        @Override<br>
                        public void run() {<br>
                            File soundFile = new File(filename);<br>
                            FileInputStream inStream = null;<br>
                            <br>
                            if (soundFile.exists()){<br>
                                try {<br>
                                    System.out.println("Read media
        file.");<br>
                                    long fileSize = soundFile.length();<br>
                                    soundBytes = new
        byte[(int)fileSize];<br>
                                    inStream = new
        FileInputStream(soundFile);<br>
                                    int byteCount =
        inStream.read(soundBytes);<br>
                                    System.out.println("Number of byte
        read: " + byteCount);<br>
                                } catch (IOException e) {<br>
                                    e.printStackTrace();<br>
                                    return;<br>
                                }<br>
                            }<br>
                            final MainLoop loop = new MainLoop(); <br>
                            AppSrc source =
        (AppSrc)ElementFactory.make("appsrc", "app-source");<br>
                            Element demuxer =
        ElementFactory.make("oggdemux", "ogg-demuxer");<br>
                            final Element decoder =
        ElementFactory.make("opusdec", "opus-decoder");<br>
                            Element conv =
        ElementFactory.make("audioconvert", "converter");<br>
                            Element sink =
        ElementFactory.make("autoaudiosink", "audio-output");<br>
                            <br>
                            //source.set("location",
        "/home/pi/gstJavaTest/transcript.ogg");<br>
                            <br>
                            Pipeline pipe = new Pipeline();<br>
                            Bus bus = pipe.getBus();<br>
                            bus.connect(new Bus.EOS() {<br>
            <br>
                                @Override<br>
                                public void endOfStream(GstObject
        source) {<br>
                                    loop.quit();<br>
                                }<br>
                                <br>
                            });<br>
                            bus.connect(new Bus.ERROR() {<br>
                                <br>
                                @Override<br>
                                public void errorMessage(GstObject
        source, int code, String message) {<br>
                                    System.out.println("Error
        detected");<br>
                                    System.out.println("Error source: "
        + source.getName());<br>
                                    System.out.println("Error code: " +
        code);<br>
                                    System.out.println("Message: " +
        message);<br>
                                    loop.quit();<br>
                                }<br>
                            });<br>
                            <br>
                            pipe.addMany(source, demuxer, decoder, conv,
        sink);<br>
                            source.link(demuxer);<br>
                            source.set("emit-signals", true);<br>
                            source.connect(new AppSrc.NEED_DATA() {<br>
            <br>
                                private ByteBuffer bb =
        ByteBuffer.wrap(soundBytes);<br>
                                <br>
                                @Override<br>
                                public void needData(AppSrc elem, int
        size) {<br>
                                    if (bb.hasRemaining()) {<br>
                                        // TODO Auto-generated method
        stub<br>
                                        System.out.println("needData:
        size = " + size);<br>
                                        byte[] tempBuffer;<br>
                                        Buffer buf;<br>
                                        if (bb.remaining() > size) {<br>
                                            tempBuffer = new byte[size];<br>
                                            buf = new Buffer(size);<br>
                                        } else {<br>
                                            tempBuffer = new
        byte[bb.remaining()];<br>
                                            buf = new
        Buffer(bb.remaining());<br>
                                        }<br>
                                        //System.out.println("Buffer
        size: " + buf.map(true).remaining());<br>
                                        //System.arraycopy(soundBytes,
        pointer, tempBuffer, 0, size);<br>
                                        bb.get(tempBuffer);<br>
                                        System.out.println("Temp Buffer
        remaining bytes: " + bb.remaining());<br>
                                       
        buf.map(true).put(ByteBuffer.wrap(tempBuffer));<br>
                                        elem.pushBuffer(buf);<br>
                                    } else {<br>
                                        elem.emit("end-of-stream",
        elem);<br>
                                    }<br>
                                    //pointer += size;<br>
                                }<br>
                            });<br>
                            <br>
                            source.connect(new AppSrc.ENOUGH_DATA() {<br>
                                <br>
                                @Override<br>
                                public void enoughData(AppSrc elem) {<br>
                                    System.out.println("enoughData: " +
        elem.toString());<br>
                                    <br>
                                }<br>
                            });<br>
                            source.connect(new AppSrc.END_OF_STREAM() {<br>
                                <br>
                                @Override<br>
                                public FlowReturn endOfStream(AppSrc
        elem) {<br>
                                    // TODO Auto-generated method stub<br>
                                    return FlowReturn.OK;<br>
                                }<br>
                            });<br>
                            Element.linkMany(decoder, conv, sink);<br>
                            demuxer.connect(new Element.PAD_ADDED() {<br>
            <br>
                                @Override<br>
                                public void padAdded(Element element,
        Pad pad) {<br>
                                    System.out.println("Dynamic pad
        created, linking demuxer/decoder");<br>
                                    System.out.println("Pad name: " +
        pad.getName());<br>
                                    System.out.println("Pad type: " +
        pad.getTypeName());<br>
                                    Pad sinkPad =
        decoder.getStaticPad("sink");<br>
                                    //boolean linked =
        element.link(decoder);<br>
                                    PadLinkReturn ret =
        pad.link(sinkPad);<br>
                                    if (ret.equals(PadLinkReturn.OK)){<br>
                                        System.out.println("Pad
        linked.");<br>
                                    } else {<br>
                                        System.out.println("Pad link
        failed");<br>
                                    }<br>
                                    //System.out.println("Pad Link
        Return: " + ret.toString());<br>
                                }<br>
                                <br>
                            });<br>
                            <br>
                            System.out.println("Now Playing...");<br>
                            pipe.play();<br>
                            System.out.println("Running...");<br>
                            loop.run();<br>
                            System.out.println("Returned, stopping
        playback");<br>
                            pipe.stop();<br>
                        }<br>
                    });<br>
                }<br>
            <br>
            }</font><br>
      <br>
      I don't use playbin since the audio data will come from byte
      stream finally. <br>
      <br>
      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:<br>
      <br>
      <br>
      <font size="-1"><tt>    (AudioTest:4643): GLib-GObject-CRITICAL
          **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed</tt><tt><br>
        </tt><tt>    </tt><tt><br>
        </tt><tt>    (AudioTest:4643): GLib-GObject-CRITICAL **:
          g_object_unref: assertion 'G_IS_OBJECT (object)' failed </tt><tt><br>
        </tt></font></p>
    <p><font size="-1"><tt>    Returned, stopping playback</tt><tt><br>
        </tt><tt>    </tt><tt><br>
        </tt><tt>    (AudioTest:4643): GLib-GObject-CRITICAL **:
          g_object_ref: assertion 'G_IS_OBJECT (object)' failed</tt><tt><br>
        </tt><tt>    </tt><tt><br>
        </tt><tt>    (AudioTest:4643): GLib-GObject-CRITICAL **:
          g_object_unref: assertion 'G_IS_OBJECT (object)' failed</tt><tt><br>
        </tt><tt>    </tt><tt><br>
        </tt><tt>    (AudioTest:4643): GLib-GObject-CRITICAL **:
          g_object_ref: assertion 'G_IS_OBJECT (object)' failed</tt><tt><br>
        </tt><tt>    </tt><tt><br>
        </tt><tt>    (AudioTest:4643): GLib-GObject-CRITICAL **:
          g_object_unref: assertion 'G_IS_OBJECT (object)' failed</tt><tt><br>
        </tt><tt>    </tt><tt><br>
        </tt><tt>    (AudioTest:4643): GLib-GObject-CRITICAL **:
          g_value_set_object: assertion 'G_IS_OBJECT (v_object)' failed</tt><tt><br>
        </tt><tt>    #</tt><tt><br>
        </tt><tt>    # A fatal error has been detected by the Java
          Runtime Environment:</tt><tt><br>
        </tt><tt>    #</tt><tt><br>
        </tt><tt>    #  SIGSEGV (0xb) at pc=0x63d8b8ec, pid=4643,
          tid=1658819680</tt><tt><br>
        </tt><tt>    #</tt><tt><br>
        </tt><tt>    # JRE version: Java(TM) SE Runtime Environment
          (8.0_65-b17) (build</tt><tt><br>
        </tt><tt>    1.8.0_65-b17)</tt><tt><br>
        </tt><tt>    # Java VM: Java HotSpot(TM) Client VM (25.65-b01
          mixed mode linux-arm )</tt><tt><br>
        </tt><tt>    # Problematic frame:</tt><tt><br>
        </tt><tt>    # C  [libglib-2.0.so.0+0x928ec] 
          g_rec_mutex_lock+0x8</tt><tt><br>
        </tt><tt>    #</tt><tt><br>
        </tt><tt>    # Failed to write core dump. Core dumps have been
          disabled. To enable core dumping, try "ulimit -c unlimited"
          before starting Java again</tt><tt><br>
        </tt><tt>    #</tt><tt><br>
        </tt><tt>    # An error report file with more information is
          saved as:</tt><tt><br>
        </tt><tt>    # /home/pi/gstJavaTest/hs_err_pid4643.log</tt><tt><br>
        </tt><tt>    #</tt><tt><br>
        </tt><tt>    # If you would like to submit a bug report, please
          visit:</tt><tt><br>
        </tt><tt>    #   <a class="moz-txt-link-freetext" href="http://bugreport.java.com/bugreport/crash.jsp">http://bugreport.java.com/bugreport/crash.jsp</a></tt><tt><br>
        </tt><tt>    # The crash happened outside the Java Virtual
          Machine in native code.</tt><tt><br>
        </tt><tt>    # See problematic frame for where to report the
          bug.</tt><tt><br>
        </tt><tt>    # Aborted</tt><tt><br>
        </tt></font><br>
      I cannot find any example on using AppSrc to play something with
      an end. Any help will be appreciated. Thank you.<br>
      <br>
      <br>
    </p>
  </body>
</html>