从AppSrc播放后,GStreamer Java Binding清理问题

时间:2016-05-30 16:51:35

标签: java-gstreamer

我正在尝试在Raspberry Pi上使用GStreamer Java Binding来播放一些Opus编码的动态音频数据。我就快完成了。我的最后一个问题是,当数据到达终点时,我不能很好地清理GStreamer。我的测试代码如下。

MusicPlayer

我不使用playbin,因为音频数据最终将以字节流的形式出现。

测试运行良好直至结束。当我到达文件的末尾。我得到错误消息,并遵循JVM粉碎。错误消息如下:

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();
            }
        });
    }

}

我找不到任何使用AppSrc播放结尾的例子。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我解决了这个问题。解决方案是使用AppSrc.endOfStream()方法而不是发出信号。此外,我删除了AppSrc.END_OF_STREAM的回调,因为没有必要。所以我对needData的回调是这样的:

            @Override
            public void needData(AppSrc elem, int size) {
                if (bb.hasRemaining()) {
                    System.out.println("needData: size = " + size);
                    byte[] tempBuffer;
                    Buffer buf;
                    int copyLength = (bb.remaining() >= size) ? size : bb.remaining();
                    tempBuffer = new byte[copyLength];
                    buf = new Buffer(copyLength);
                    //System.arraycopy(soundBytes, pointer, tempBuffer, 0, copyLength);
                    System.out.println("Buffer size: " + buf.map(true).remaining());
                    bb.get(tempBuffer);
                    System.out.println("Temp Buffer remaining bytes: " + bb.remaining());
                    buf.map(true).put(ByteBuffer.wrap(tempBuffer));
                    elem.pushBuffer(buf);
                    //pointer += size;
                } else {
                    elem.endOfStream();
                }
            }