LibVLC library allows showing RTSP stream from IP camera on Android application. There might be a case where we have multiple IP cameras and want to display a RTSP stream from a specific camera when the user selects it from the dropdown.
This tutorial provides example how to dynamically change RTSP URL of IP camera in VLC player on Android application.
At first, add the LibVLC library in the module's build.gradle
file.
dependencies {
// Other dependencies
// ...
implementation 'org.videolan.android:libvlc-all:3.4.4'
}
Request the INTERNET
permission in the manifest file because application requires Internet access.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.INTERNET" />
<application>
...
</application>
</manifest>
In the layout XML file, add Spinner
which will used to show a dropdown list of IP cameras. You also need to add VLCVideoLayout
for displaying RTSP stream from chosen camera.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context=".MainActivity">
<Spinner
android:id="@+id/cameraDropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<org.videolan.libvlc.util.VLCVideoLayout
android:id="@+id/videoLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/cameraDropdown"/>
</RelativeLayout>
We created a new VideoStreamPlayer
class which responsible to display stream from IP camera by given RTSP URL.
package com.example.app;
import android.content.Context;
import android.net.Uri;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.util.VLCVideoLayout;
public class VideoStreamPlayer
{
private final LibVLC libVlc;
private final MediaPlayer mediaPlayer;
private final VLCVideoLayout videoLayout;
public VideoStreamPlayer(Context context, VLCVideoLayout videoLayout)
{
libVlc = new LibVLC(context);
mediaPlayer = new MediaPlayer(libVlc);
this.videoLayout = videoLayout;
}
public void start(String url)
{
mediaPlayer.attachViews(videoLayout, null, false, false);
Media media = new Media(libVlc, Uri.parse(url));
media.setHWDecoderEnabled(true, false);
media.addOption(":network-caching=600");
mediaPlayer.setMedia(media);
media.release();
mediaPlayer.play();
}
public void stop()
{
mediaPlayer.stop();
mediaPlayer.detachViews();
}
public void release()
{
mediaPlayer.release();
libVlc.release();
}
}
package com.example.app
import android.content.Context
import android.net.Uri
import org.videolan.libvlc.LibVLC
import org.videolan.libvlc.Media
import org.videolan.libvlc.MediaPlayer
import org.videolan.libvlc.util.VLCVideoLayout
class VideoStreamPlayer(context: Context, private var videoLayout: VLCVideoLayout)
{
private var libVlc: LibVLC = LibVLC(context)
private var mediaPlayer: MediaPlayer = MediaPlayer(libVlc)
fun start(url: String)
{
mediaPlayer.attachViews(videoLayout, null, false, false)
val media = Media(libVlc, Uri.parse(url))
media.setHWDecoderEnabled(true, false)
media.addOption(":network-caching=600")
mediaPlayer.media = media
media.release()
mediaPlayer.play()
}
fun stop()
{
mediaPlayer.stop()
mediaPlayer.detachViews()
}
fun release()
{
mediaPlayer.release()
libVlc.release()
}
}
In the MainActivity
class, we defined two arrays to store RTSP addresses and names of cameras which will used to show in dropdown. Don't forget to adjust values depending on what IP cameras you have. We used two Reolink E1 Pro cameras for testing.
We attach an array adapter with names of cameras to Spinner
and register a callback which invoked when user selects a camera from the dropdown. When IP camera is selected, previously captured stream is stopped and new stream from selected camera is starting to show.
package com.example.app;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import androidx.appcompat.app.AppCompatActivity;
import org.videolan.libvlc.util.VLCVideoLayout;
public class MainActivity extends AppCompatActivity
{
private static final String[] urlList = {
"rtsp://user:pass@192.168.0.8:554/h264Preview_01_main",
"rtsp://user:pass@192.168.0.9:554/h264Preview_01_main"
};
private static final String[] cameraList = {
"Camera 1",
"Camera 2"
};
private VideoStreamPlayer streamPlayer;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VLCVideoLayout videoLayout = findViewById(R.id.videoLayout);
streamPlayer = new VideoStreamPlayer(this, videoLayout);
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this,
android.R.layout.simple_spinner_dropdown_item,
cameraList
);
Spinner dropdown = findViewById(R.id.cameraDropdown);
dropdown.setAdapter(adapter);
dropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View v, int pos, long id)
{
streamPlayer.stop();
streamPlayer.start(urlList[pos]);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
@Override
protected void onStop()
{
super.onStop();
streamPlayer.stop();
}
@Override
protected void onDestroy()
{
super.onDestroy();
streamPlayer.release();
}
}
package com.example.app
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import org.videolan.libvlc.util.VLCVideoLayout
class MainActivity : AppCompatActivity()
{
private var urlList: Array<String> = arrayOf(
"rtsp://user:pass@192.168.0.8:554/h264Preview_01_main",
"rtsp://user:pass@192.168.0.9:554/h264Preview_01_main"
)
private var cameraList: Array<String> = arrayOf(
"Camera 1",
"Camera 2"
)
private lateinit var streamPlayer: VideoStreamPlayer
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val videoLayout: VLCVideoLayout = findViewById(R.id.videoLayout)
streamPlayer = VideoStreamPlayer(this, videoLayout)
val adapter: ArrayAdapter<String> = ArrayAdapter<String>(
this,
android.R.layout.simple_spinner_dropdown_item,
cameraList
)
val dropdown: Spinner = findViewById(R.id.cameraDropdown)
dropdown.adapter = adapter
dropdown.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, v: View, pos: Int, id: Long)
{
streamPlayer.stop()
streamPlayer.start(urlList[pos])
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}
override fun onStop()
{
super.onStop()
streamPlayer.stop()
}
override fun onDestroy()
{
super.onDestroy()
streamPlayer.release()
}
}
The 1 Comment Found
Excellent Post!!
Leave a Comment
Cancel reply