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