如何使用javacv和ffmpeg以编程方式读取音频RTP流?

时间:2019-05-21 04:44:47

标签: java audio ffmpeg rtp javacv

我正在尝试使用javaCV在命令行中读取来自ffmpeg的音频RTP流。我创建了一个侦听指定端口但无法获取音频帧的DatagramSocket。

我尝试使用不同类型的缓冲区将音频播放到扬声器,但是我收到很多“流协议的无效返回值0”错误消息,扬声器中没有音频。

我正在运行以下命令以流式传输音频文件:

ffmpeg -re -i /some/file.wav -ar 44100 -f mulaw -f rtp rtp://127.0.0.1:7780

到目前为止,我的代码节选:

公共类FrameGrabber实现了Runnable {

private static final TimeUnit SECONDS = TimeUnit.SECONDS;
private InetAddress ipAddress;
private DatagramSocket serverSocket;

public FrameGrabber(Integer port) throws UnknownHostException, SocketException {
    super();

    this.ipAddress = InetAddress.getByName("192.168.44.18");
    serverSocket = new DatagramSocket(port, ipAddress);

}

public AudioFormat getAudioFormat() {
    float sampleRate = 44100.0F;
    // 8000,11025,16000,22050,44100
    int sampleSizeInBits = 16;
    // 8,16
    int channels = 1;
    // 1,2
    boolean signed = true;
    // true,false
    boolean bigEndian = false;
    // true,false
    return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}

@Override
public void run() {


    byte[] buffer = new byte[2048];
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(packet.getData(), packet.getOffset(), packet.getLength()));


    FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(dis);
    grabber.setFormat("mulaw");
    grabber.setSampleRate((int) getAudioFormat().getSampleRate());
    grabber.setAudioChannels(getAudioFormat().getChannels());

    SourceDataLine soundLine = null;


    try {
        grabber.start();


        if (grabber.getSampleRate() > 0 && grabber.getAudioChannels() > 0) {

            AudioFormat audioFormat = new AudioFormat(grabber.getSampleRate(), 16, grabber.getAudioChannels(), true, true);

            DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
            soundLine = (SourceDataLine) AudioSystem.getLine(info);
            soundLine.open(audioFormat);

            soundLine.start();
        }

        ExecutorService executor = Executors.newSingleThreadExecutor();


        while (true) {

            try {
                serverSocket.receive(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }

            Frame frame = grabber.grab();

            //if (frame == null) break;


            if (frame != null && frame.samples != null) {

                ShortBuffer channelSamplesFloatBuffer = (ShortBuffer) frame.samples[0];
                channelSamplesFloatBuffer.rewind();

                ByteBuffer outBuffer = ByteBuffer.allocate(channelSamplesFloatBuffer.capacity() * 2);
                float[] samples = new float[channelSamplesFloatBuffer.capacity()];

                for (int i = 0; i < channelSamplesFloatBuffer.capacity(); i++) {
                    short val = channelSamplesFloatBuffer.get(i);
                    outBuffer.putShort(val);
                }

                if (soundLine == null) return;
                try {
                    SourceDataLine finalSoundLine = soundLine;
                    executor.submit(() -> {
                        finalSoundLine.write(outBuffer.array(), 0, outBuffer.capacity());
                        outBuffer.clear();
                    }).get();
                } catch (InterruptedException interruptedException) {
                    Thread.currentThread().interrupt();
                }
            }

        }

        /*
        executor.shutdownNow();
        executor.awaitTermination(1, SECONDS);

        if (soundLine != null) {
            soundLine.stop();
        }

        grabber.stop();
        grabber.release();*/

        } catch (ExecutionException ex) {
        System.out.println("ExecutionException");
        ex.printStackTrace();
    } catch (org.bytedeco.javacv.FrameGrabber.Exception ex) {
        System.out.println("FrameGrabberException");
        ex.printStackTrace();
    } catch (LineUnavailableException ex) {
        System.out.println("LineUnavailableException");
        ex.printStackTrace();
    }/* catch (InterruptedException e) {
        System.out.println("InterruptedException");
        e.printStackTrace();
    }*/


}

public static void main(String[] args) throws SocketException, UnknownHostException {
    Runnable apRunnable = new FrameGrabber(7780);
    Thread ap = new Thread(apRunnable);
    ap.start();
}

}

在这个阶段,我正在尝试在扬声器中播放音频文件,但是我收到以下日志:

  

任务:FrameGrabber.main()   流协议的无效返回值0   流协议的无效返回值0   从'java.io.DataInputStream@474e6cea'输入#0,mulaw:     持续时间:不适用,比特率:352 kb / s       流#0:0:音频:pcm_mulaw,44100 Hz,1个通道,s16、352 kb / s   流协议的无效返回值0   流协议的无效返回值0   流协议的无效返回值0   流协议的无效返回值0   ...

我在做什么错了?

谢谢!

0 个答案:

没有答案