Android应用中的VLC寻找文件而不是http流

时间:2016-12-20 23:30:26

标签: android http vlc

我正在尝试使用Android应用中附加到树莓派的相机创建实时流。

以下是活动的代码:

public class Stream extends AppCompatActivity implements IVLCVout.Callback, LibVLC.OnNativeCrashListener {
public final static String TAG = "LibVLCAndroid/Stream";

//public final static String LOCATION = "com.compdigitec.libvlcandroidsample.VideoActivity.location";

private String mFilePath;

// display surface
private SurfaceView mSurface;
private SurfaceHolder holder;

// media player
private LibVLC libvlc;
private MediaPlayer mMediaPlayer = null;
private int mVideoWidth;
private int mVideoHeight;
private final static int VideoSizeChanged = -1;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_stream);

    // Receive path to play from intent
    Intent intent = getIntent();
    mFilePath = "http://70.122.174.124:691";

    Log.d(TAG, "Playing back " + mFilePath);

    mSurface = (SurfaceView) findViewById(R.id.surface);
    holder = mSurface.getHolder();
    //holder.addCallback(this);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setSize(mVideoWidth, mVideoHeight);
}

@Override
protected void onResume() {
    super.onResume();
    createPlayer(mFilePath);
}

@Override
protected void onPause() {
    super.onPause();
    releasePlayer();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    releasePlayer();
}

private void setSize(int width, int height) {
    mVideoWidth = width;
    mVideoHeight = height;
    if (mVideoWidth * mVideoHeight <= 1)
        return;

    if(holder == null || mSurface == null)
        return;

    // get screen size
    int w = getWindow().getDecorView().getWidth();
    int h = getWindow().getDecorView().getHeight();

    // getWindow().getDecorView() doesn't always take orientation into
    // account, we have to correct the values
    boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
    if (w > h && isPortrait || w < h && !isPortrait) {
        int i = w;
        w = h;
        h = i;
    }

    float videoAR = (float) mVideoWidth / (float) mVideoHeight;
    float screenAR = (float) w / (float) h;

    if (screenAR < videoAR)
        h = (int) (w / videoAR);
    else
        w = (int) (h * videoAR);

    // force surface buffer size
    holder.setFixedSize(mVideoWidth, mVideoHeight);

    // set display size
    LayoutParams lp = mSurface.getLayoutParams();
    lp.width = w;
    lp.height = h;
    mSurface.setLayoutParams(lp);
    mSurface.invalidate();
}

private void createPlayer(String media) {
    releasePlayer();
    try {
        if (media.length() > 0) {
            Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
            toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
                    0);
            toast.show();
        }

        // Create LibVLC
        // TODO: make this more robust, and sync with audio demo
        ArrayList<String> options = new ArrayList<>();
        //options.add("--subsdec-encoding <encoding>");
        options.add("-vvv"); // verbosity
        libvlc = new LibVLC(options);
        libvlc.setOnNativeCrashListener(this);
        holder.setKeepScreenOn(true);

        // Create media player
        mMediaPlayer = new MediaPlayer(libvlc);
        mMediaPlayer.setEventListener(mPlayerListener);

        // Set up video output
        final IVLCVout vout = mMediaPlayer.getVLCVout();
        vout.setVideoView(mSurface);
        //vout.setSubtitlesView(mSurfaceSubtitles);
        vout.addCallback(this);
        vout.attachViews();

        Media m = new Media(libvlc, media);
        mMediaPlayer.setMedia(m);
        mMediaPlayer.play();
    } catch (Exception e) {
        Toast.makeText(this, "Error creating player!", Toast.LENGTH_LONG).show();
    }
}

// TODO: handle this cleaner
private void releasePlayer() {
    if (libvlc == null)
        return;
    mMediaPlayer.stop();
    final IVLCVout vout = mMediaPlayer.getVLCVout();
    vout.removeCallback(this);
    vout.detachViews();
    holder = null;
    libvlc.release();
    libvlc = null;

    mVideoWidth = 0;
    mVideoHeight = 0;
}

private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);

@Override
public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
    if (width * height == 0)
        return;

    // store video size
    mVideoWidth = width;
    mVideoHeight = height;
    setSize(mVideoWidth, mVideoHeight);
}

@Override
public void onHardwareAccelerationError(IVLCVout vlcVout) {
    // Handle errors with hardware acceleration
    Log.e(TAG, "Error with hardware acceleration");
    this.releasePlayer();
    Toast.makeText(this, "Error with hardware acceleration", Toast.LENGTH_LONG).show();
}

@Override
public void onSurfacesCreated(IVLCVout vout) {

}

@Override
public void onSurfacesDestroyed(IVLCVout vout) {

}

private static class MyPlayerListener implements MediaPlayer.EventListener {
    private WeakReference<Stream> mOwner;

    public MyPlayerListener(Stream owner) {
        mOwner = new WeakReference<>(owner);
    }

    @Override
    public void onEvent(MediaPlayer.Event event) {
        Stream player = mOwner.get();

        switch(event.type) {
            case MediaPlayer.Event.EndReached:
                Log.d(TAG, "MediaPlayerEndReached");
                player.releasePlayer();
                break;
            case MediaPlayer.Event.Playing:
            case MediaPlayer.Event.Paused:
            case MediaPlayer.Event.Stopped:
            default:
                break;
        }
    }
}

@Override
public void onNativeCrash() {
    // Handle errors with hardware acceleration
    Log.e(TAG, "Native Crash");
    this.releasePlayer();
    Toast.makeText(this, "Native Crash", Toast.LENGTH_LONG).show();
}

}

和XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="vertical"
tools:context="rpi.rpicam.Stream" >

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <SurfaceView
        android:id="@+id/surface"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center" />
</FrameLayout>

</LinearLayout>

但是,当我运行应用程序时,我在日志中遇到以下错误:

    12-20 14:23:03.790 7775-1067/rpi.rpicam E/VLC: [0000007f4a5df0b8] filesystem access: cannot open file //http://70.122.174.124:691 (No such file or directory)
12-20 14:23:03.790 7775-1067/rpi.rpicam E/VLC: [0000007f4a5df0b8] core access: File reading failed
12-20 14:23:03.790 7775-1067/rpi.rpicam E/VLC: [0000007f4a5df0b8] core access: VLC could not open the file "//http://70.122.174.124:691" (No such file or directory).
12-20 14:23:03.790 7775-1067/rpi.rpicam D/VLC: [0000007f4a5df0b8] core access: no access modules matched
12-20 14:23:03.790 7775-1067/rpi.rpicam E/VLC: [0000007f7bf759b8] core input source: cannot access file:////http%3A//70.122.174.124%3A691
12-20 14:23:03.790 7775-1067/rpi.rpicam E/VLC: [0000007f70a3f4b8] core input: Your input can't be opened
12-20 14:23:03.790 7775-1067/rpi.rpicam E/VLC: [0000007f70a3f4b8] core input: VLC is unable to open the MRL 'file:////http%3A//70.122.174.124%3A691'. Check the log for details.

我很清楚,问题是VLC认为我正在尝试访问存储在设备上的文件,而不是从http流式传输视频。

我试过搜索堆栈溢出和VLC文档,但似乎没有太多文档,我无法弄清楚如何让VLC识别出这是一个http流。

其他细节: 我已经通过我的Ubuntu桌面上的VLC和官方VLC Android应用程序测试了流正在工作

当我开始对应上面代码的活动时,我看到的只是一个黑屏

1 个答案:

答案 0 :(得分:0)

有一些Media构造函数。将String作为第二个参数的文档记录为期望该参数为本地文件路径。

(恕我直言,这不是一个很棒的API设计 - 使用File个对象)

还有另一个Media构造函数,它将Uri作为参数;这可能适用于其他类型的方案,例如https