关于 android 上的自定义代码 vlc:android 上的自定义代码 vlc – 没有视频

custom code vlc on android - no video

我几乎得到了一个成功运行的安卓 vlc 代码示例。
我一直以 VideoPlayerActivity 为例。

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

yuv_rgb_neon: 无法获取视频图片。

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

谁能指出我正确的方向?

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

1
2
3
4
5
6
7
8
9
10
11
 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());

完整代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
 /* 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;
            }
        }
    }

 }

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

VLC for Android VideoLAN 论坛

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 中使用以下内容,而不是自己编译和添加 vlc 库:

1
compile"de.mrmaffen:vlc-android-sdk:1.0.3"