android libvlc multiple surface problems
Asked Answered
S

2

43

I would like to know if is possible to use two Surface views in the same layout and view the content of both of them at the same time. In future, I would make use of a Grid-view of video-view, where each video-view uses VLC.

I modified this sample (android-vlc-sample) using a Fragment.

The result is that I see only one video. How can I solve this?

From log-cat I do not see any major error, but I think there are rendering problems for android UIThread

Java Coding

public class MultipleVideoPlayFragmentActivity extends FragmentActivity {

public final static String LOCATION = "com.compdigitec.libvlcandroidsample.MultipleVideoPlayFragmentActivity.location";
private static final String TAG = "MediaPlayer";
public String mFilePatha;

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.activity_multiple_video_play_fragment);
    Intent intent = getIntent();
    mFilePatha = intent.getExtras().getString(LOCATION);
}

public static class VideoFragment extends Fragment implements
        SurfaceHolder.Callback, IVideoPlayer {
    public final static String TAG = "LibVLCAndroidSample/VideoActivity";

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

    private String mFilePath;

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

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

    /*************
     * Activity
     *************/

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.sample, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Receive path to play from intent

        Log.d(TAG, "Playing back " + mFilePath);
        mFilePath = ((MultipleVideoPlayFragmentActivity) getActivity()).mFilePatha;
        // mFilePath="rtsp://192.168.4.125:554/0";
        // mFilePath="android.resource://it.nexera.visiamobile/raw/sample_mpeg4";
        mSurface = (SurfaceView) getView().findViewById(R.id.surface);
        holder = mSurface.getHolder();
        holder.addCallback(this);
    }

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

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

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

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

    /*************
     * Surface
     *************/

    public void surfaceCreated(SurfaceHolder holder) {
    }

    public void surfaceChanged(SurfaceHolder surfaceholder, int format,
            int width, int height) {
        if (libvlc != null)
            libvlc.attachSurface(holder.getSurface(), this);
    }

    public void surfaceDestroyed(SurfaceHolder surfaceholder) {
    }

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

        // get screen size
        int w = getActivity().getWindow().getDecorView().getWidth();
        int h = getActivity().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();
    }

    @Override
    public void setSurfaceSize(int width, int height, int visible_width,
            int visible_height, int sar_num, int sar_den) {
        Message msg = Message.obtain(mHandler, VideoSizeChanged, width,
                height);
        msg.sendToTarget();
    }

    /*************
     * Player
     *************/

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

            // Create a new media player
            libvlc = LibVLC.getInstance();
            libvlc.setHardwareAcceleration(LibVLC.HW_ACCELERATION_DISABLED);
            libvlc.setSubtitlesEncoding("");
            libvlc.setAout(LibVLC.AOUT_OPENSLES);
            libvlc.setTimeStretching(true);
            libvlc.setChroma("RV32");
            libvlc.setVerboseMode(true);
            // LibVLC.restart(this.getActivity());
            EventHandler.getInstance().addHandler(mHandler);
            holder.setFormat(PixelFormat.RGBX_8888);
            holder.setKeepScreenOn(true);
            MediaList list = libvlc.getMediaList();
            list.clear();
            list.add(new Media(libvlc, LibVLC.PathToURI(media)), false);
            libvlc.playIndex(0);
        } catch (Exception e) {
            Toast.makeText(this.getActivity(), "Error creating player!",
                    Toast.LENGTH_LONG).show();
        }
    }

    private void releasePlayer() {
        if (libvlc == null)
            return;
        EventHandler.getInstance().removeHandler(mHandler);
        libvlc.stop();
        libvlc.detachSurface();
        holder = null;
        libvlc.closeAout();
        libvlc.destroy();
        libvlc = null;

        mVideoWidth = 0;
        mVideoHeight = 0;
    }

    /*************
     * Events
     *************/

    private Handler mHandler = new MyHandler(this);

    private static class MyHandler extends Handler {
        private WeakReference<VideoFragment> mOwner;

        public MyHandler(VideoFragment owner) {
            mOwner = new WeakReference<VideoFragment>(owner);
        }

        @Override
        public void handleMessage(Message msg) {
            VideoFragment player = mOwner.get();

            // SamplePlayer events
            if (msg.what == VideoSizeChanged) {
                player.setSize(msg.arg1, msg.arg2);
                return;
            }

            // Libvlc events
            Bundle b = msg.getData();
            switch (b.getInt("event")) {
            case EventHandler.MediaPlayerEndReached:
                player.releasePlayer();
                break;
            case EventHandler.MediaPlayerPlaying:
            case EventHandler.MediaPlayerPaused:
            case EventHandler.MediaPlayerStopped:
            default:
                break;
            }
        }
    }
}

}

XML Coding

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <fragment
        android:id="@+id/video_1_fragment"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:layout_weight="1"
        class="com.compdigitec.libvlcandroidsample.MultipleVideoPlayFragmentActivity$VideoFragment" />

    <fragment
        android:id="@+id/video_2_fragment"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:layout_weight="1"
        class="com.compdigitec.libvlcandroidsample.MultipleVideoPlayFragmentActivity$VideoFragment" />

</LinearLayout>

**Single Fragment Layout**

    <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=".SampleActivity" >

    <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>
Soporific answered 28/2, 2014 at 12:6 Comment(3)
I have a same problem in a background service, I tried run multiple instances of LibVLC but this not work, only played the last streaming. You resolved your problem with multiple fragments?Sprinkle
no, Vlc for android did not support multiple instance, but I know that vlc staff were working on this. Check official vlc developer forum.Soporific
Hi @tulkas85:-I am facing same issue.i am trying with this link -Android VLC player with multiple instance it works fine with android 5.0 but for 6.0 there is rendering issue.means stream not get properly.some flicker over there.Spirogyra
C
1

Please try this one:

--- libvlc = LibVLC.getInstance();
+++ libvlc = new LibVLC();

P.S. What version of LibVLC-android you are using?

P.P.S. example

Cinquecento answered 28/10, 2017 at 6:34 Comment(0)
E
1

I had same problem. What I did was to follow VLC's own example (https://code.videolan.org/videolan/libvlc-android-samples) and make same build.gradle etc.

My code is below:

MainActivity.java

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import tools.nubicam.com.rtsptest.R;


public class MainActivity extends Activity {

    public final static String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {


        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button startButton = (Button)findViewById(R.id.buttonStart);
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent(MainActivity.this, VideoActivity.class);
                EditText textRTSP = (EditText)findViewById(R.id.textRTSPUrl);
                intent.putExtra(VideoActivity.RTSP_URL, textRTSP.getText().toString());
                startActivity(intent);
            }
        });

    }

}

VideoActivity.java

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

import org.videolan.libvlc.IVLCVout;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.media.VideoView;


import java.lang.ref.WeakReference;
import java.util.ArrayList;

import tools.nubicam.com.rtsptest.R;

public class VideoActivity<USE_TEXTURE_VIEW, ENABLE_SUBTITLES, False> extends Activity implements IVLCVout.Callback    {
    public final static String TAG = "VideoActivity";

    public static final String RTSP_URL = "rtspurl";

    // 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;


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

    private String rtspUrl;

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

        // Get URL
        Intent intent = getIntent();
        rtspUrl = intent.getExtras().getString(RTSP_URL);
        Log.d(TAG, "Playing back " + rtspUrl);

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

    }


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

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

            ArrayList<String> options = new ArrayList<String>();
            options.add("-vvv"); // verbosity
            //options.add("--aout=opensles");
            //options.add("--audio-time-stretch"); // time stretching
            //options.add("--avcodec-codec=h264");
            //options.add("--file-logging");
            //options.add("--logfile=vlc-log.txt");

            options.add("--network-caching=150");
            options.add("--clock-jitter=0");
            options.add("--clock-synchro=0");

            //options.add("--http-reconnect");
            //options.add("--network-caching="+6*1000);

            libvlc = new LibVLC(this, options);
            ///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, Uri.parse(rtspUrl));

            mMediaPlayer.setMedia(m);
            mMediaPlayer.play();

//            m.setHWDecoderEnabled(true, false);
//            m.addOption(":network-caching=150");
//            m.addOption(":clock-jitter=0");
//            m.addOption(":clock-synchro=0");


        } catch (Exception e) {
            Toast.makeText(this, "Error creating player!", Toast.LENGTH_LONG).show();
        }

    }

    @Override
    protected void onStart() {
        super.onStart();
        int cnt = 0;
        cnt += 1;
        Toast.makeText(this, cnt + "", Toast.LENGTH_SHORT).show();
    }

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

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


    @Override
    public void onSurfacesCreated(IVLCVout vlcVout) {
        int cnt = 30;
        cnt += 1;
        Toast.makeText(this, cnt + "", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onSurfacesDestroyed(IVLCVout vlcVout) {
        int cnt = 20;
        cnt += 1;
        Toast.makeText(this, cnt + "", Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {
        int cnt = 10;
        cnt += 1;
        Toast.makeText(this, cnt + "", Toast.LENGTH_SHORT).show();
    }


    public 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 static class MyPlayerListener implements MediaPlayer.EventListener {
        private WeakReference<VideoActivity> mOwner;

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

        @Override
        public void onEvent(org.videolan.libvlc.MediaPlayer.Event event) {
            VideoActivity player = mOwner.get();

            switch(event.type) {
                case MediaPlayer.Event.EndReached:
                    Log.d(TAG, "MediaPlayerEndReached");
                    Toast.makeText(player.getApplicationContext(), "Event EndReached", Toast.LENGTH_SHORT).show();
                    player.releasePlayer();
                    break;
                case MediaPlayer.Event.Opening:
                    Toast.makeText(player.getApplicationContext(), "Event Opening", Toast.LENGTH_SHORT).show();
                    break;
                case MediaPlayer.Event.Buffering:
                    Toast.makeText(player.getApplicationContext(), "Event Buffering", Toast.LENGTH_SHORT).show();
                    break;
                case MediaPlayer.Event.Playing:
                    Toast.makeText(player.getApplicationContext(), "Event Playing", Toast.LENGTH_SHORT).show();
                    break;
                case MediaPlayer.Event.Paused:
                    Toast.makeText(player.getApplicationContext(), "Event Paused", Toast.LENGTH_SHORT).show();
                    break;
                case MediaPlayer.Event.Stopped:
                    Toast.makeText(player.getApplicationContext(), "Event Stopped", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    }

}

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.nubicam.tools.rtsptest.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="RTSPTest"
            android:textStyle="bold"
            android:visibility="visible" />

        <EditText
            android:id="@+id/textRTSPUrl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="rtsp://{user}:{pass}@host:554/{videosource}"
            android:inputType="textPersonName"
            android:text="rtsp://admin:[email protected]:554/1" />

        <Button
            android:id="@+id/buttonStart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Play stream!"
            tools:layout_editor_absoluteX="151dp"
            tools:layout_editor_absoluteY="120dp" />

    </LinearLayout>

</RelativeLayout>

sample.xml

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@android:color/background_dark"
    android:keepScreenOn="true"
    tools:context="com.nubicam.tools.rtsptest.VideoActivity" >

    <SurfaceView
        android:id="@+id/surface"
        android:layout_width="fill_parent"
        android:layout_height="365dp" />


    <org.videolan.libvlc.util.VLCVideoLayout
        android:id="@+id/video_layout"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_marginTop="365dp"
        android:fitsSystemWindows="false" />



</FrameLayout>

build.gradle(:app)

    apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "tools.nubicam.com.rtsptest"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'org.videolan.android:libvlc-all:3.1.12'


}

build.gradle(vlc..)

    // Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.1'
        //classpath 'com.android.tools.build:gradle:3.4.2'
        

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        //maven {
        //    url 'https://jitpack.io'
        //}

        ///maven {
        ///   url "https://dl.bintray.com/videolan/Android"
        ///}
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

gradle.properties

org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=true

gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
Estafette answered 6/12, 2020 at 15:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.