前言

  继续折腾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可能老变,大家看文章的时候注意一下版本问题。

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

  1. 【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)

    作者 : 韩曙亮  博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...

  2. Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)

    今天讲一下对VLC播放器音频播放功能进行二次开发,讲解如何改造音乐播放相关功能.最近一直在忙着优化视频解码部分代码,因为我的视频播放器需要在一台主频比较低的机器上跑(800M主频),所以视频解码能力受 ...

  3. Android VLC播放器二次开发2——CPU类型检查+界面初始化

    上一篇讲了VLC整个程序的模块划分和界面主要使用的技术,今天分析一下VLC程序初始化过程,主要是初始化界面.加载解码库的操作.今天主要分析一下org.videolan.vlc.gui.MainActi ...

  4. 命令行运行Android Robotium自动化用例或单元测试用例

    本文目录 1.运行所有的测试用例 2.运行单个测试类或某个TestSuite 3.运行某个测试类里面的某个测试方法 4.运行两个不同的测试类或类中的方法 命令行运行Android Robotium自动 ...

  5. 【Android】15.5 例15-3—Notification的各种属性演示

    分类:C#.Android.VS2015: 创建日期:2016-02-29 一.简介 利用这个例子,可测试通知的各种属性以及这些不同属性选项呈现的效果. 另外,在这个例子中,还演示了如何读写SD中的图 ...

  6. 【Android】15.4 例15-2--Notification基本用法

    分类:C#.Android.VS2015: 创建日期:2016-02-29 一.简介 上一节介绍了通知(Notification)相关的基本内容.这一节先用一个简单示例演示创建和发布本地通知的基本用法 ...

  7. 【Android】Android开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...

  8. [Android Pro] Android 4.3 NotificationListenerService使用详解

    reference to : http://blog.csdn.net/yihongyuelan/article/details/40977323 概况 Android在4.3的版本中(即API 18 ...

  9. 【Android】 Android实现录音、播音、录制视频功能

    智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...

  10. 4412开发板Android教程——Android平台简介

    本文转自迅为开发板论坛:http://www.topeetboard.com Android和IOS Android的历史 Android公司 2005年Google收购成立22个月的Android公 ...

随机推荐

  1. python生成随机密码

    有时候我们会想生成一个随机密码,这样我们通过Python中的一些随机方法,就可生成我们任意长度和复杂度的密码,代码如下: # -*- coding=utf-8 -*- import random im ...

  2. 【转载】各浏览器CSS兼容问题

    CSS对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理方法并 整理了一下.对于web2.0的过度,请尽量用xhtml ...

  3. ASP.NET Core实现OAuth2.0的ResourceOwnerPassword和ClientCredentials模式

    前言 开发授权服务框架一般使用OAuth2.0授权框架,而开发Webapi的授权更应该使用OAuth2.0授权标准,OAuth2.0授权框架文档说明参考:https://tools.ietf.org/ ...

  4. 驱动开发利器Microsoft Windows Driver Kit 7.1.0下载

    在Windows 2000 与Windows XP 系统采用是WINDDK来开发WINDOWS驱动程序,我手头也有WINDDK,可是从Windows Vista开始之后,一般采用Microsoft W ...

  5. 实现Android包的批量删除

    由于手机内存有限,有时需要一次删除很多个包,这时就需要一个实现Android包批量删除的应用. 首先是布局文件: <?xml version="1.0" encoding=& ...

  6. windows下用eclipse+goclipse插件+gdb搭建go语言开发调试环境

    windows下用eclipse+goclipse插件+gdb搭建go语言开发调试环境   http://rongmayisheng.com/post/windows%E4%B8%8B%E7%94%A ...

  7. vim快捷键整理(转载)

    一.移动光标 1.左移h.右移l.下移j.上移k2.向下翻页ctrl + f,向上翻页ctrl + b3.向下翻半页ctrl + d,向上翻半页ctrl + u4.移动到行尾$,移动到行首0(数字), ...

  8. Node.JS事件驱动机制

    1.事件驱动程序绑定事件及事件的处理程序 eventEmitter.on('eventName', eventHandler); 我们可以通过程序触发事件 // 触发事件 eventEmitter.e ...

  9. 在Hyper-V上安装配置Windows负载均衡NLB

    搭建过程 Hyper-V 是自Windows Server2008 以来提供的虚拟机管理软件,它操作简便,功能也不错,可以方便的在它里面安装各种操作系统,如图所示: 现在,想利用这几台虚拟服务器搭建一 ...

  10. ImageLightbox.js – 响应式的图片 Lightbox 插件

    ImageLightbox.js 是一款很简洁的用于显示图片灯箱效果(Lightbox)的插件,没有字幕,导航按钮或默认背景.如果默认功能不够用的话,你可以很容易地自定义 JavaScript 函数扩 ...