Custom VLC app on android - no video

VLC for Android and Chrome OS specific usage questions
bramm
New Cone
New Cone
Posts: 5
Joined: 09 Oct 2013 17:33

Custom VLC app on android - no video

Postby bramm » 09 Oct 2013 17:46

I've almost got a successfully working code sample of vlc for android.
I've been using the VideoPlayerActivity as an example.

Currently I have the surface displayed through the surfacehandler and I see a black video image background box (SurfaceView). I also have working audio.
However for some reason I cannot get any video.
Logcat says the following continuously:

yuv_rgb_neon: can't get video picture.

I think it's a very small issue in my code. I've tried virtually anything I can think of but I can't get it to work.

Can anyone point me in the right direction perhaps?

this is the core libvlc code i use: I think something is wrong with the init context parameter, but I can't seem to find out what it is.
(I have the same surface handler as the original VideoPlayerActivity located in org.videloan.vlc.gui.video)

Code: Select all

mLibVLC = LibVLC.getInstance(); mLibVLC.setIomx(false); mLibVLC.setSubtitlesEncoding(""); mLibVLC.setTimeStretching(false); mLibVLC.setFrameSkip(true); mLibVLC.setChroma("RV16"); mLibVLC.setVerboseMode(true); mLibVLC.setAout(-1); mLibVLC.setDeblocking(0); mLibVLC.setNetworkCaching(0); mLibVLC.init(this.getApplicationContext());
Thanks in advance.

Bram

edwardw
Big Cone-huna
Big Cone-huna
Posts: 2346
Joined: 24 Jun 2012 23:36
VLC version: 3.0.0-git

Re: Custom VLC app on android - no video

Postby edwardw » 10 Oct 2013 04:17

You did not setSurface() anywhere?

bramm
New Cone
New Cone
Posts: 5
Joined: 09 Oct 2013 17:33

Re: Custom VLC app on android - no video

Postby bramm » 10 Oct 2013 08:17

Hi,

i didn't want to blow up my post but here's the code I use:
I've used the same setSurface as in the original VideoPlayerActivity.

I noticed that the original VLC get's the same warning initially
yuv_rgb_neon filter: can't get videopicture. (when I use Iomx, it says the same thing but then for swscaler)
Then when the surfacechanged log notification for the pixelFormat comes, the original VLC stops giving the warning and it shows the video.

Furthermore:

I changed the manifest according to the original VLC code
I've used a stripped player.xml with only the surfaceview in the original layout
the libraries are in the original location: org.videolan.libvlc

Code: Select all

/***************************************************************************** * VideoPlayerActivity.java ***************************************************************************** * Copyright © 2011-2013 VLC authors and VideoLAN * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ package com.example.mp2; import java.lang.reflect.Method; import org.videolan.libvlc.EventHandler; import org.videolan.libvlc.IVideoPlayer; import org.videolan.libvlc.LibVLC; import org.videolan.libvlc.LibVlcException; import org.videolan.vlc.Util; import org.videolan.vlc.WeakHandler; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.ImageFormat; import android.graphics.PixelFormat; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.Display; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View.OnSystemUiVisibilityChangeListener; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.widget.FrameLayout; public class VideoPlayerActivity extends Activity implements IVideoPlayer { public final static String TAG = "VLC/VideoPlayerActivity"; // Internal intent identifier to distinguish between internal launch and // external intent. private SurfaceView mSurface; private SurfaceHolder mSurfaceHolder; private FrameLayout mSurfaceFrame; private LibVLC mLibVLC; private String mLocation; private static final int SURFACE_BEST_FIT = 0; private static final int SURFACE_FIT_HORIZONTAL = 1; private static final int SURFACE_FIT_VERTICAL = 2; private static final int SURFACE_FILL = 3; private static final int SURFACE_16_9 = 4; private static final int SURFACE_4_3 = 5; private static final int SURFACE_ORIGINAL = 6; private int mCurrentSize = SURFACE_BEST_FIT; /** Overlay */ private static final int SURFACE_SIZE = 3; // size of the video private int mVideoHeight; private int mVideoWidth; private int mVideoVisibleHeight; private int mVideoVisibleWidth; private int mSarNum; private int mSarDen; private static VideoPlayerActivity context; public static VideoPlayerActivity getContext() { return context; } /** * Used to store a selected subtitle; see onActivityResult. It is possible * to have multiple custom subs in one session (just like desktop VLC allows * you as well.) */ @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.player); if (Util.isICSOrLater()) getWindow().getDecorView().findViewById(android.R.id.content).setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { setSurfaceSize(mVideoWidth, mVideoHeight, mVideoVisibleWidth, mVideoVisibleHeight, mSarNum, mSarDen); } }); mSurface = (SurfaceView) findViewById(R.id.player_surface); mSurfaceHolder = mSurface.getHolder(); mSurfaceFrame = (FrameLayout) findViewById(R.id.player_surface_frame); String chroma = "RV16"; context = this; if (Util.isGingerbreadOrLater() && chroma.equals("YV12")) { mSurfaceHolder.setFormat(ImageFormat.YV12); } else if (chroma.equals("RV16")) { mSurfaceHolder.setFormat(PixelFormat.RGB_565); } else { mSurfaceHolder.setFormat(PixelFormat.RGBX_8888); } mSurfaceHolder.addCallback(mSurfaceCallback); try { mLibVLC = LibVLC.getInstance(); mLibVLC.setIomx(false); mLibVLC.setSubtitlesEncoding(""); mLibVLC.setTimeStretching(false); mLibVLC.setFrameSkip(true); mLibVLC.setChroma("RV16"); mLibVLC.setVerboseMode(true); mLibVLC.setAout(-1); mLibVLC.setDeblocking(0); mLibVLC.setNetworkCaching(0); mLibVLC.init(this.getApplicationContext()); } catch (LibVlcException e) { // TODO Auto-generated catch block e.printStackTrace(); } EventHandler em = EventHandler.getInstance(); em.addHandler(eventHandler); } @Override protected void onStart() { super.onStart(); } @Override protected void onPause() { super.onPause(); mLibVLC.stop(); mSurface.setKeepScreenOn(false); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { super.onDestroy(); if (mLibVLC != null) { mLibVLC.stop(); } } @Override protected void onResume() { super.onResume(); load(); } private final Handler eventHandler = new VideoPlayerEventHandler(this); private static class VideoPlayerEventHandler extends WeakHandler<VideoPlayerActivity> { public VideoPlayerEventHandler(VideoPlayerActivity owner) { super(owner); } @Override public void handleMessage(Message msg) { VideoPlayerActivity activity = getOwner(); if (activity == null) return; switch (msg.getData().getInt("event")) { case EventHandler.MediaPlayerPlaying: Log.i(TAG, "MediaPlayerPlaying"); // activity.setESTracks(); // activity.setESTracks(); break; case EventHandler.MediaPlayerPaused: Log.i(TAG, "MediaPlayerPaused"); break; case EventHandler.MediaPlayerStopped: Log.i(TAG, "MediaPlayerStopped"); break; case EventHandler.MediaPlayerEndReached: Log.i(TAG, "MediaPlayerEndReached"); // activity.endReached(); break; case EventHandler.MediaPlayerVout: // activity.handleVout(msg); break; case EventHandler.MediaPlayerPositionChanged: // don't spam the logs break; case EventHandler.MediaPlayerEncounteredError: Log.i(TAG, "MediaPlayerEncounteredError"); // activity.encounteredError(); break; default: Log.e(TAG, String.format("Event not handled (0x%x)", msg.getData().getInt("event"))); break; } // activity.updateOverlayPausePlay(); } }; private final Handler mHandler = new VideoPlayerHandler(this); private static class VideoPlayerHandler extends WeakHandler<VideoPlayerActivity> { public VideoPlayerHandler(VideoPlayerActivity owner) { super(owner); } @Override public void handleMessage(Message msg) { VideoPlayerActivity activity = getOwner(); if (activity == null) // WeakReference could be GC'ed early return; switch (msg.what) { case SURFACE_SIZE: activity.changeSurfaceSize(); break; } } }; @Override public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) { if (width * height == 0) return; // store video size mVideoHeight = height; mVideoWidth = width; mVideoVisibleHeight = visible_height; mVideoVisibleWidth = visible_width; mSarNum = sar_num; mSarDen = sar_den; Message msg = mHandler.obtainMessage(SURFACE_SIZE); mHandler.sendMessage(msg); } private void changeSurfaceSize() { // get screen size int dw = getWindow().getDecorView().getWidth(); int dh = 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 (dw > dh && isPortrait || dw < dh && !isPortrait) { int d = dw; dw = dh; dh = d; } // sanity check if (dw * dh == 0 || mVideoWidth * mVideoHeight == 0) { Log.e(TAG, "Invalid surface size"); return; } // compute the aspect ratio double ar, vw; double density = (double) mSarNum / (double) mSarDen; if (density == 1.0) { /* No indication about the density, assuming 1:1 */ vw = mVideoVisibleWidth; ar = (double) mVideoVisibleWidth / (double) mVideoVisibleHeight; } else { /* Use the specified aspect ratio */ vw = mVideoVisibleWidth * density; ar = vw / mVideoVisibleHeight; } // compute the display aspect ratio double dar = (double) dw / (double) dh; switch (mCurrentSize) { case SURFACE_BEST_FIT: if (dar < ar) dh = (int) (dw / ar); else dw = (int) (dh * ar); break; case SURFACE_FIT_HORIZONTAL: dh = (int) (dw / ar); break; case SURFACE_FIT_VERTICAL: dw = (int) (dh * ar); break; case SURFACE_FILL: break; case SURFACE_16_9: ar = 16.0 / 9.0; if (dar < ar) dh = (int) (dw / ar); else dw = (int) (dh * ar); break; case SURFACE_4_3: ar = 4.0 / 3.0; if (dar < ar) dh = (int) (dw / ar); else dw = (int) (dh * ar); break; case SURFACE_ORIGINAL: dh = mVideoVisibleHeight; dw = (int) vw; break; } // force surface buffer size // mSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight); // set display size LayoutParams lp = mSurface.getLayoutParams(); lp.width = dw * mVideoWidth / mVideoVisibleWidth; lp.height = dh * mVideoHeight / mVideoVisibleHeight; mSurface.setLayoutParams(lp); // set frame size (crop if necessary) lp = mSurfaceFrame.getLayoutParams(); lp.width = dw; lp.height = dh; mSurfaceFrame.setLayoutParams(lp); mSurface.invalidate(); } private final SurfaceHolder.Callback mSurfaceCallback = new Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (format == PixelFormat.RGBX_8888) Log.d(TAG, "Pixel format is RGBX_8888"); else if (format == PixelFormat.RGB_565) Log.d(TAG, "Pixel format is RGB_565"); else if (format == ImageFormat.YV12) Log.d(TAG, "Pixel format is YV12"); else Log.d(TAG, "Pixel format is other/unknown"); mLibVLC.attachSurface(holder.getSurface(), VideoPlayerActivity.this, width, height); } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mLibVLC.detachSurface(); } }; /** * External extras: - position (long) - position of the video to start with * (in ms) */ private void load() { // mLocation = "rtsp://rpi:rpi@mocca.victorem.com/test.sdp"; mLocation = "file:///sdcard/fam.mp4"; mSurface.setKeepScreenOn(true); // MediaList mediaList = new MediaList(mLibVLC); // mLibVLC.setMediaList(); mLibVLC.readMedia(mLocation, false); mLibVLC.setTime(0); mLibVLC.play(); } @SuppressWarnings("deprecation") private int getScreenRotation() { WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO /* * Android 2.2 * has * getRotation */) { try { Method m = display.getClass().getDeclaredMethod("getRotation"); return (Integer) m.invoke(display); } catch (Exception e) { return Surface.ROTATION_0; } } else { return display.getOrientation(); } } @TargetApi(Build.VERSION_CODES.GINGERBREAD) private int getScreenOrientation() { WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); int rot = getScreenRotation(); /* * Since getRotation() returns the screen's "natural" orientation, which * is not guaranteed to be SCREEN_ORIENTATION_PORTRAIT, we have to * invert the SCREEN_ORIENTATION value if it is "naturally" landscape. */ @SuppressWarnings("deprecation") boolean defaultWide = display.getWidth() > display.getHeight(); if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) defaultWide = !defaultWide; if (defaultWide) { switch (rot) { case Surface.ROTATION_0: return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; case Surface.ROTATION_90: return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; case Surface.ROTATION_180: // SCREEN_ORIENTATION_REVERSE_PORTRAIT only available since API // Level 9+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); case Surface.ROTATION_270: // SCREEN_ORIENTATION_REVERSE_LANDSCAPE only available since API // Level 9+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); default: return 0; } } else { switch (rot) { case Surface.ROTATION_0: return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; case Surface.ROTATION_90: return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; case Surface.ROTATION_180: // SCREEN_ORIENTATION_REVERSE_PORTRAIT only available since API // Level 9+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); case Surface.ROTATION_270: // SCREEN_ORIENTATION_REVERSE_LANDSCAPE only available since API // Level 9+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); default: return 0; } } } }

XilasZ
Developer
Developer
Posts: 189
Joined: 16 Jun 2009 20:35

Re: Custom VLC app on android - no video

Postby XilasZ » 11 Oct 2013 10:35

If you have "yuv_rgb_neon: can't get video picture", it means one thing : the surface buffer doesn't have the correct size.

At each frame, the vout checks that the surface buffer and the frame have the same size.
If not, it calls setSurfaceSize(...) to request a resize of the surface buffer (that's why this method is mandatory).

But you commented the line which change the surface buffer size :

Code: Select all

// mSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
Uncomment it, it should work.

Also be sure to maintain the same layout for the surface view, especially the double FrameLayout, it doesn't behave well without this.

PS: It's normal if "yuv_rgb_neon: can't get video picture" appears once on first frame to set the correct size.

bramm
New Cone
New Cone
Posts: 5
Joined: 09 Oct 2013 17:33

Re: Custom VLC app on android - no video

Postby bramm » 11 Oct 2013 20:45

hi,

thx a lot, you're a lifesaver. That did the trick. Can't explain why I've missed it.

Gr,

Bram


Return to “VLC for Android and Chrome OS”

Who is online

Users browsing this forum: No registered users and 12 guests