【VLC-Android】vlc-android简例

前言

  继续折腾vlc,做这个例子并不顺利,卡在只有声音没有图像这个问题好久,网上的例子有些API已经对不上,继续分享,,,

 

声明
欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com

 

正文

  截图

    

  项目

    

  代码

public class VlcVideoActivity extends Activity implements SurfaceHolder.Callback, IVideoPlayer {

    private final static String TAG = "[VlcVideoActivity]";

    private SurfaceView mSurfaceView;
    private LibVLC mMediaPlayer;
    private SurfaceHolder mSurfaceHolder;

    private View mLoadingView;

    private int mVideoHeight;
    private int mVideoWidth;
    private int mVideoVisibleHeight;
    private int mVideoVisibleWidth;
    private int mSarNum;
    private int mSarDen;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_vlc);

        mSurfaceView = (SurfaceView) findViewById(R.id.video);
        mLoadingView = findViewById(R.id.video_loading);
        try {
            mMediaPlayer = VLCInstance.getLibVlcInstance();
        } catch (LibVlcException e) {
            e.printStackTrace();
        }

        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.setFormat(PixelFormat.RGBX_8888);
        mSurfaceHolder.addCallback(this);

        mMediaPlayer.eventVideoPlayerActivityCreated(true);

        EventHandler em = EventHandler.getInstance();
        em.addHandler(mVlcHandler);

        this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        mSurfaceView.setKeepScreenOn(true);
        //        mMediaPlayer.setMediaList();
        //        mMediaPlayer.getMediaList().add(new Media(mMediaPlayer, "http://live.3gv.ifeng.com/zixun.m3u8"), false);
        //        mMediaPlayer.playIndex(0);
        mMediaPlayer.playMRL("http://live.3gv.ifeng.com/zixun.m3u8");
    }

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

        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mSurfaceView.setKeepScreenOn(false);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMediaPlayer != null) {
            mMediaPlayer.eventVideoPlayerActivityCreated(false);

            EventHandler em = EventHandler.getInstance();
            em.removeHandler(mVlcHandler);
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        setSurfaceSize(mVideoWidth, mVideoHeight, mVideoVisibleWidth, mVideoVisibleHeight, mSarNum, mSarDen);
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (mMediaPlayer != null) {
            mSurfaceHolder = holder;
            mMediaPlayer.attachSurface(holder.getSurface(), this);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mSurfaceHolder = holder;
        if (mMediaPlayer != null) {
            mMediaPlayer.attachSurface(holder.getSurface(), this);//, width, height
        }
        if (width > 0) {
            mVideoHeight = height;
            mVideoWidth = width;
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mMediaPlayer != null) {
            mMediaPlayer.detachSurface();
        }
    }

    @Override
    public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
        mVideoHeight = height;
        mVideoWidth = width;
        mVideoVisibleHeight = visible_height;
        mVideoVisibleWidth = visible_width;
        mSarNum = sar_num;
        mSarDen = sar_den;
        mHandler.removeMessages(HANDLER_SURFACE_SIZE);
        mHandler.sendEmptyMessage(HANDLER_SURFACE_SIZE);
    }

    private static final int HANDLER_BUFFER_START = 1;
    private static final int HANDLER_BUFFER_END = 2;
    private static final int HANDLER_SURFACE_SIZE = 3;

    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;

    private Handler mVlcHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg == null || msg.getData() == null)
                return;

            switch (msg.getData().getInt("event")) {
            case EventHandler.MediaPlayerTimeChanged:
                break;
            case EventHandler.MediaPlayerPositionChanged:
                break;
            case EventHandler.MediaPlayerPlaying:
                mHandler.removeMessages(HANDLER_BUFFER_END);
                mHandler.sendEmptyMessage(HANDLER_BUFFER_END);
                break;
            case EventHandler.MediaPlayerBuffering:
                break;
            case EventHandler.MediaPlayerLengthChanged:
                break;
            case EventHandler.MediaPlayerEndReached:
                //播放完成
                break;
            }

        }
    };

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case HANDLER_BUFFER_START:
                showLoading();
                break;
            case HANDLER_BUFFER_END:
                hideLoading();
                break;
            case HANDLER_SURFACE_SIZE:
                changeSurfaceSize();
                break;
            }
        }
    };

    private void showLoading() {
        mLoadingView.setVisibility(View.VISIBLE);
    }

    private void hideLoading() {
        mLoadingView.setVisibility(View.GONE);
    }

    private void changeSurfaceSize() {
        // get screen size
        int dw = getWindowManager().getDefaultDisplay().getWidth();
        int dh = getWindowManager().getDefaultDisplay().getHeight();

        // calculate aspect ratio
        double ar = (double) mVideoWidth / (double) mVideoHeight;
        // calculate 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 = mVideoHeight;
            dw = mVideoWidth;
            break;
        }

        mSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
        ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
        lp.width = dw;
        lp.height = dh;
        mSurfaceView.setLayoutParams(lp);
        mSurfaceView.invalidate();
    }
}

    代码说明 

      1、vlc-android的版本为2.2.0-pre1 Weatherwax

      2、拷贝vlc-android官网例子下面org.videolan.libvlc所有的类,以及VLCInstance、Preferences。只有声音没有画面就出在VLCInstance这个问题上,少了一些配置,参考VLCInstance.updateLibVlcSettings。

      3、playMRL不要用Uri来转,否则打不开

      4、提供的代码已经编译好了so,也修改源码打开了EventHandler.MediaPlayerBuffering(也修改了libvlcjni.c),但是还是没有缓冲进度的值,还有待进一步探索。

      5、实际发现如果只在surfaceChanged中attachSurface,setSurfaceSize回调不会触发,需要同时在surfaceCreated中设置。

      6、本文不讨论Handler非静态可能引发内存泄露的问题,大家写的时候自己注意一下 :) 

 

  下载

    https://github.com/over140/vlc-android-demo (注意工程是Android Studio的工程)

 

  文章

    1、vlc-android 中调用用libvlcjni.so实现流媒体播放 

    2、[Github]vlc-android-macbuild

    3、vlc android的编译及截图,录制视频等功能

    4、vlc-android源码编译过程记录

    5、vlc-android 获取MediaPlayerEncounteredError,MediaPlayerBuffering等各种事件的响应

    6、Vlc-for-android源码分析

 

结束

   文章2的GitHub项目是对vlc进行封装,也挺不错了,值得参考。vlc-android的例子写的比较复杂,而且api可能老变,大家看文章的时候注意一下版本问题。

转载:http://www.cnblogs.com/over140/p/3932784.html

时间: 2024-12-23 18:47:57

【VLC-Android】vlc-android简例的相关文章

Android 开发仿简书登录框可删除内容或显示密码框的内容_Android

简书App 是我很喜欢的一款软件.今天就模仿了一下他的登录框.先上图: 好了下面上代码,自定义ImgEditText 继承与EditText.重写一些方法. package lyf.myimgedittextdemo; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.Editable; impor

android:descendantFocusability用法简析

android:descendantFocusability用法简析     开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点.原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类

Android OKHTTP的单例和再封装的实例

Android OKHTTP的单例和再封装的实例 /** * Created by zm on 16-2-1 * okhttp的再封装,对于2.x版本,3.x版本将原有对okhttpclient配置 * 改成了builder模式配 * 置,对于超时.代理.dns,okhttp已经做好了配置, * 若不需要特殊配置,可以跳过 */ public class OkHttpUtil { private static OkHttpClient singleton; //非常有必要,要不此类还是可以被ne

【Android】 Android 事件处理

Android 事件处理 --学习笔记2 目的:通过全面的分析Android的鼠标和键盘事件.了解Android中如何接收和处理键盘和鼠标事件,以及如何用代码来产生事件. 主要学习内容: 1. 接收并处理鼠标事件:按下.弹起.移动.双击.长按.滑动.滚动 2. 接收并处理按键事件:按下.弹起 3. 模拟鼠标/按键事件 1. Android事件 现代的用户界面,都是以事件来驱动的来实现人机交换的,而Android上的一套UI控件,无非就是派发鼠标和键盘事件,然后每个控件收到相应的事件之后,做相应的

【Android】 Android中适配器简介

1. BaseAdapter的使用实例 BaseAdapter baseAdapter = new BaseAdapter() { @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(GridViewActivity.this); imag

[Android 泥水匠] Android基础 之一:浅谈Android架构到HelloWorld案例的剖析

1.1前言   泥瓦匠又和大家见面了,在移动平台干过原生态开发,也干过hybrid应用.可以看看相关的文章 Android UI .所以多多少少在这块还是有点了解.现在很多高级语言可以开发app程序,包括Android,到我觉得目前Java语言开发Android程序还是很火,很重要的.自然,Java的底子不可少.可以看看泥瓦匠写的不少基础 Java Basic .   我们生活在一个通讯的时代,我经历过得2.5G时代,也就是GPRS等的时代,前面还有2G(GSM等).1G,后面则大家熟悉的3G

android studio android:text=&amp;amp;quot;@string/button_send&amp;amp;quot;

问题描述 android studio android:text="@string/button_send" android studio新建button这句话不懂:android:text="@string/button_send" 请教个问题:android studio里面新建button里面有一句:android:text="@string/button_send".在string.xml里面有一句:Send 能不能这样理解:button

【Android】Android动态代理为SurfaceHolder添加Hook

本博客将会介绍动态代理在Android应用中的一种使用场景 代理模式 代理模式的作用是为其它对象提供一种代理以控制对这个对象的访问.比如用户调用了一个"吃饭"的方法,如果不依靠代理,用户可能自己拿碗饭吃就行,而如果通过代理的话,可能连碗都不需要用户自己拿,用户只需要张开嘴,代理来喂就行了,需要注意的是,这里代理除了负责拿碗和喂饭外还可以做其他的任何事情,比如说帮你把饭吹凉一些,或者担心你的体重而偷偷帮你倒掉了一半的饭,又或者是往饭里加点什么奇奇怪怪的东西,谁知道呢,这就是代理干的活.实

【Android】Android自定义带board的圆角控件

介绍 圆角控件常用于头像,按钮,图标等,用途十分广泛,而且常常配合board使用. 在IOS中,UIVIew的CALayer层已经提供了圆角和board的方法,所以圆角控件的制作非常简单,只需要类似以下简单代码即可实现: view.layer.cornerRadius = 20; view.layer.borderColor = [UIColor yellowColor].CGColor; view.layer.borderWidth = 10; view.clipsToBounds = YES

Android异常处理Android异常处理

问题描述 Android异常处理Android异常处理 比如说出现空指针 我不弹框 直接结束掉出错的actvity 解决方案 而Java提供了一套比较优秀的异常处理机制:?? ? 1.使开发人员不必编写特殊代码来测试返回值就能发现问题,?? ? 2.在语法结构就把正常的代码和异常处理的代码清晰的分开来,?? ? 3.允许我们使用相同的异常处理代码来处理一定范围内的所有异常.?以期产生一......答案就在这里:android异常处理 解决方案二: 加入你不拦截的话,空指针错误直接崩溃,哪有弹框