从HttpUrlConnection的inputstream读取速度慢

时间:2018-08-15 10:16:01

标签: java http networking vlc vlcj

我有一个链接到实时流的URL-实时流本身在“ .ts”文件中。

我正在使用vlcj使用Java显示视频,但是网络代码使用的是纯Java。这是我到目前为止的内容:

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

    }

}

主要瓶颈出现在StreamMedia类中的onRead()方法上,因为我的程序必须阻塞直到收到更多数据为止。这会导致断断续续的播放并出现明显的冻结。

但是,当我使用VLC播放该流时,该程序可以很好地播放,因此我认为服务器没有问题。

我已经尝试过使用缓冲流,但是它只允许在初始阶段进行流畅的播放。我还尝试过从输入中读取一个工作线程,而另一个则实际播放了该线程,但是没有任何变化。

无论如何我都可以解决这个问题?谢谢。

1 个答案:

答案 0 :(得分:0)

完全不建议使用Java来读取流的这种方法。

如果要播放网络流,请使用mediaPlayer.playMedia使用标准网络MRL播放。因此,如果VLC可以播放您的流,请在使用vlcj时使用相同的MRL。

有了网络流和.ts文件,您将需要处理vlcj中的子项目。 vlcj测试源中有许多播放网络流的示例。

如果您必须坚持使用这种方法,那么我不确定512字节是否适合缓冲区大小,因此您可以尝试增加该大小。 vlcj的默认缓冲区大小为10k,但是即使这样,这种方法也不是很理想。