GStreamer Java Binding cleanup issue after playback from AppSrc

Alex Hui alexhui at keyease.com
Tue May 31 13:26:10 UTC 2016


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.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20160531/47c87c3b/attachment-0001.html>


More information about the gstreamer-devel mailing list