简体   繁体   中英

Slow read from HttpUrlConnection's inputstream

I have a URL that links to a livestream - the live stream itself is in a ".ts" file.

I'm using vlcj to display the video using Java, but the network code is in pure Java. Here's what I have so far:

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;


import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
import uk.co.caprica.vlcj.player.media.callback.DefaultCallbackMedia;

public class Main {

  public static class StreamMedia extends DefaultCallbackMedia{

    private InputStream stream;

    public StreamMedia(InputStream stream, String[] mediaOptions) {
      //512 bytes to read per call to onRead
      super(false, 512, mediaOptions);
      this.stream = stream;
    }

    @Override
    protected int onRead(byte[] arg0, int arg1) throws IOException {
      int amnt = stream.read(arg0);
      return amnt;
    }

    @Override
    protected void onClose() {
      try {
        stream.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    @Override
    protected long onGetSize() {
      return 0;
    }

    @Override
    protected boolean onOpen() {
      return true;
    }

    @Override
    protected boolean onSeek(long arg0) {
      return false;
    }

  }

  public static void main(String[] args) throws Exception{    
      //The url I'm streaming to my machine.
      //It's a ".ts" resource 
      URL url = new URL("STREAM URL");

      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setUseCaches(false);
      connection.connect();

      StreamMedia test = new StreamMedia(connection.getInputStream(), new String[0]);


      //Just sets up my VLC JFrame. Right from the vlc tutorials
      new NativeDiscovery().discover();
      SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new JFrame("A GUI");
        frame.setBounds(100, 100, 600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        EmbeddedMediaPlayerComponent mediaPlayer = new EmbeddedMediaPlayerComponent();
        frame.setContentPane(mediaPlayer);

        frame.setVisible(true);

        //play the StreamMedia object I've created
        mediaPlayer.getMediaPlayer().playMedia(test);
      }
    });

    }

}

The main bottleneck occurs at the method onRead() in the class StreamMedia since my program has to block until more data is received. This results in a choppy playback with significant freezes.

However, when I play the stream using VLC the program, it plays nicely so I don't think it's a problem with my server.

I've tried using buffered streams, but it only allowed for fluent playback at the initial stages. I also tried having a worker thread read from the input while another actually played it, but there was no change.

Anyway I can fix this? Thanks.

This approach using Java to read your stream is really NOT recommended at all.

If you have a network stream to play, then play it using the standard network MRL using mediaPlayer.playMedia. So, if VLC can play your stream, use the same MRL when you use vlcj.

With a network stream and a .ts file, you will need to deal with sub-items in vlcj. There are numerous examples in the vlcj test sources that play network streams.

If you must persist with this approach, I'm not sure 512 bytes is a good size for a buffer so you could try increasing that. vlcj's default buffer size for this was 10k, but even so this approach is sub-optimal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM