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>