0

我几乎有一个成功运行的 vlc for android 代码示例。我一直以 VideoPlayerActivity 为例。

目前我通过surfacehandler显示了表面,我看到了一个黑色的视频图像背景框(SurfaceView)。我也有工作音频。但是由于某种原因,我无法获得任何视频。Logcat 连续说以下内容:

yuv_rgb_neon:无法获取视频图片。

我认为这是我的代码中的一个非常小的问题。我几乎尝试了我能想到的任何东西,但我无法让它发挥作用。

谁能指出我正确的方向?

这是我使用的核心 libvlc 代码:我认为 init 上下文参数有问题,但我似乎无法找出它是什么。(我与位于 org.videloan.vlc.gui.video 中的原始 VideoPlayerActivity 具有相同的表面处理程序)


 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());

完整的代码片段:

 /* VideoPlayerActivity.java */

 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 = "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;
            }
        }
    }

 }
4

1 回答 1

2

在对 VLC for Android 进行故障排除时,您会在他们的论坛中找到很多有用的信息:

VLC for Android VideoLAN 论坛

在初始化 mLibVLC 之前,您缺少两个选项。他们是:

mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL); mLibVLC.eventVideoPlayerActivityCreated(Boolean.TRUE);

没有这些,您的视频将不会显示,或者您将在 SurfaceView 中显示绿屏。因此,在您的 VLC 活动的 onCreate 中,要正确显示视频,您可以使用以下内容(假设您的 SurfaceView 设置为正确的大小):

mSurfaceView = (SurfaceView) findViewById(R.id.player_surface);
mSurfaceHolder = mSurfaceView.getHolder();

mSurfaceFrame = (FrameLayout) findViewById(R.id.player_surface_frame);
mMediaUrl = getIntent().getExtras().getString("videoUrl");

try {
    mLibVLC = LibVLC.getInstance();
    mLibVLC.setAout(mLibVLC.AOUT_AUDIOTRACK);
    mLibVLC.setVout(mLibVLC.VOUT_ANDROID_SURFACE);
    mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL);
    mLibVLC.eventVideoPlayerActivityCreated(Boolean.TRUE);

    mLibVLC.init(getApplicationContext());
} catch (LibVlcException e){
    Log.e(TAG, e.toString());
}

mSurfaceHolder.addCallback(mSurfaceCallback);
mSurface = mSurfaceHolder.getSurface();

mLibVLC.attachSurface(mSurface, VideoVLCActivity.this);
mLibVLC.playMRL(mMediaUrl);

旁注,任何人都可以在他们的 build.gradle 中使用以下内容,而不是自己编译和 inc vlc 库:

compile "de.mrmaffen:vlc-android-sdk:1.0.3"
于 2015-03-21T16:02:28.627 回答