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