基于安卓平台,客户端视频监控的实现(二)
来源:互联网 发布:yy免费头像源码和制作 编辑:程序博客网 时间:2024/05/17 09:21
关于如何编译在官方有介绍,网上也有很多教程,不做赘述。
目前博主水平有限,目前主要是分析java部分代码和如何使用解码库。
先看下目录结构:
LibVLC是load解码库和so库的,提供调用的方法。
/* Load library before object instantiation */ static { try { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) System.loadLibrary("iomx-gingerbread"); else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2) System.loadLibrary("iomx-hc"); else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) System.loadLibrary("iomx-ics"); } catch (Throwable t) { Log.w(TAG, "Unable to load the iomx library: " + t); } try { System.loadLibrary("vlcjni"); } catch (UnsatisfiedLinkError ule) { Log.e(TAG, "Can't load vlcjni library: " + ule); /// FIXME Alert user System.exit(1); } catch (SecurityException se) { Log.e(TAG, "Encountered a security issue when loading vlcjni library: " + se); /// FIXME Alert user System.exit(1); } }//调用所有libvlc的方法之前必须进行init操作 /** * Initialize the libVLC class. * * This function must be called before using any libVLC functions. * * @throws LibVlcException */ public void init(Context context) throws LibVlcException { Log.v(TAG, "Initializing LibVLC"); mDebugLogBuffer = new StringBuffer(); if (!mIsInitialized) { if(!LibVlcUtil.hasCompatibleCPU(context)) { Log.e(TAG, LibVlcUtil.getErrorMsg()); throw new LibVlcException(); } nativeInit(); mMediaList = mPrimaryList = new MediaList(this); setEventHandler(EventHandler.getInstance()); mIsInitialized = true; } }
播放实时视频,只需调用如下方法,传入一个rtps的url
/** * Play an MRL directly. * * @param mrl MRL of the media to play. */ public void playMyMRL(String mrl) { // index=-1 will return options from libvlc instance without relying on MediaList String[] options = new String[0]; mInternalMediaPlayerIndex = 0; playMRL(mLibVlcInstance, mrl, options); }
LibVlcUtil 主要是对设备CPU的检查。ABI,CPU_ABI是我们经常都会碰见的,例如我们在Android工程里面的libs库下面就有armeabi-v7a类型的库。这里的ABI是指Application Binary Interface。
ABI描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低层接口。ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,然而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。
ABI掩盖了各种细节,例如:调用约定(控制着函数的参数如何传送以及如何接受返回值);系统调用的编码和一个应用如何向操作系统进行系统调用;以及在一个完整的操作系统ABI中,对象文件的二进制格式、程序库等等。一个完整的ABI,像Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行。其他的 ABI 标准化细节包括 C++ name decoration 和同一个平台上的编译器之间的调用约定,但是不包括跨平台的兼容性。
简单的说,ABI规范了应用程序对寄存器的使用方法,Call procedure,以及如何进入trap。符合某一平台ABI规范的应用程序就可以在这一平台上运行。这一规范是针对binary,而不是source的。所以同样的高级语言代码,使用不同的toolchain,可以得到符合不同ABI规范的binary。关于这部分,还不明白的,自行Google(我也不是很清楚,免得误人子弟)。
VLCApplication做的事情不多,简单来说,做了两件事。第一个是一个本地配置的初始化,主要是Locale的配置,而且都是针对中文做特别处理,另外就是当系统内存不多的时候,回收一些bitmap的内存。剩下的就是保存一个全局的静态对象供其他类使用。下面给出系统内存低的时候,回收bitmap缓存。代码如下:
// Are we using advanced debugging - locale? SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); String p = pref.getString("set_locale", ""); if (p != null && !p.equals("")) { Locale locale; // workaround due to region code if(p.equals("zh-TW")) { locale = Locale.TRADITIONAL_CHINESE; } else if(p.startsWith("zh")) { locale = Locale.CHINA; } else if(p.equals("pt-BR")) { locale = new Locale("pt", "BR"); } else if(p.equals("bn-IN") || p.startsWith("bn")) { locale = new Locale("bn", "IN"); } else { /** * Avoid a crash of * java.lang.AssertionError: couldn't initialize LocaleData for locale * if the user enters nonsensical region codes. */ if(p.contains("-")) p = p.substring(0, p.indexOf('-')); locale = new Locale(p); } Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); }低内存的时候 /** * Called when the overall system is running low on memory */ @Override public void onLowMemory() { super.onLowMemory(); Log.w(TAG, "System is running low on memory"); BitmapCache.getInstance().clear(); }
具体的调用:
try { EventHandler em = EventHandler.getInstance(); em.addHandler(handler); mLoadingDialog = DialogUtil.createLoadingDialog(MainActivity.this,"正在获取信息,请稍后..."); mLoadingDialog.show(); mLibVLC = Util.getLibVlcInstance(); mLibVLC.init(getApplicationContext()); if (mLibVLC != null) { String pathUri = "rtsp://192.168.103.39:10554/654321.sdp";// String pathUri = "http://vod.cntv.lxdns.com/flash/mp4video50/TMS/2016/04/19/f1db9354900946a19a7fefc3bf040593_h264200000nero_aac16.mp4";// String pathUri = "/storage/emulated/0/DCIM/Camera/VID_20170511_103045.mp4"; mLibVLC.playMyMRL(pathUri); } } catch (LibVlcException e) { e.printStackTrace(); }
初始化handler,libvlc初始化的时候,往下一层层调用,最后handler将信息返回,调用play播放方法的时候,我也没有搞清楚为什么那么慢,可能和网络有关,还是和服务器那边推流的速度,关于这一点仍然在研究,目前给的措施就是loading加载。
当接收到handler传来的信息,对此进行相应的操作:
Handler handler = new Handler() { public void handleMessage(Message msg) { Log.d(TAG, "Event = " + msg.getData().getInt("event")); switch (msg.getData().getInt("event")) { case EventHandler.MediaPlayerPlaying: break; case EventHandler.MediaPlayerPaused: break; case EventHandler.MediaPlayerStopped: break; case EventHandler.MediaPlayerEndReached: break; case EventHandler.MediaPlayerVout: if (mLoadingDialog != null) { mLoadingDialog.dismiss(); mLoadingDialog = null; } if (msg.getData().getInt("data") > 0) { Intent intent = new Intent(); intent.setClass(getApplicationContext(),VideoPlayerActivity.class); startActivity(intent); MainActivity.this.finish(); } break; case EventHandler.MediaPlayerPositionChanged: break; case EventHandler.MediaPlayerEncounteredError: AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) .setTitle("提示信息") .setMessage("无法连接到摄像头,请检查设备是否已经连接到摄像头所在的wifi热点") .setNegativeButton("知道了", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MainActivity.this.finish(); } }).create(); dialog.setCanceledOnTouchOutside(false); dialog.show(); break; default: Log.d(TAG, "Event not handled "); break; } } };
EventHandler类里面定义很多常量,根据项目的需求选择:
/* * Be sure to subscribe to events you need in the JNI too. */ //public static final int MediaMetaChanged = 0; //public static final int MediaSubItemAdded = 1; //public static final int MediaDurationChanged = 2; //public static final int MediaParsedChanged = 3; //public static final int MediaFreed = 4; //public static final int MediaStateChanged = 5; //public static final int MediaPlayerMediaChanged = 0x100; //public static final int MediaPlayerNothingSpecial = 0x101; //public static final int MediaPlayerOpening = 0x102; //public static final int MediaPlayerBuffering = 0x103; public static final int MediaPlayerPlaying = 0x104; public static final int MediaPlayerPaused = 0x105; public static final int MediaPlayerStopped = 0x106; //public static final int MediaPlayerForward = 0x107; //public static final int MediaPlayerBackward = 0x108; public static final int MediaPlayerEndReached = 0x109; public static final int MediaPlayerEncounteredError = 0x10a; //public static final int MediaPlayerTimeChanged = 0x10b; public static final int MediaPlayerPositionChanged = 0x10c; //public static final int MediaPlayerSeekableChanged = 0x10d; //public static final int MediaPlayerPausableChanged = 0x10e; //public static final int MediaPlayerTitleChanged = 0x10f; //public static final int MediaPlayerSnapshotTaken = 0x110; //public static final int MediaPlayerLengthChanged = 0x111; public static final int MediaPlayerVout = 0x112; //public static final int MediaListItemAdded = 0x200; //public static final int MediaListWillAddItem = 0x201; //public static final int MediaListItemDeleted = 0x202; //public static final int MediaListWillDeleteItem = 0x203; //public static final int MediaListViewItemAdded = 0x300; //public static final int MediaListViewWillAddItem = 0x301; //public static final int MediaListViewItemDeleted = 0x302; //public static final int MediaListViewWillDeleteItem = 0x303; //public static final int MediaListPlayerPlayed = 0x400; //public static final int MediaListPlayerNextItemSet = 0x401; //public static final int MediaListPlayerStopped = 0x402; //public static final int MediaDiscovererStarted = 0x500; //public static final int MediaDiscovererEnded = 0x501; //public static final int VlmMediaAdded = 0x600; //public static final int VlmMediaRemoved = 0x601; //public static final int VlmMediaChanged = 0x602; //public static final int VlmMediaInstanceStarted = 0x603; //public static final int VlmMediaInstanceStopped = 0x604; //public static final int VlmMediaInstanceStatusInit = 0x605; //public static final int VlmMediaInstanceStatusOpening = 0x606; //public static final int VlmMediaInstanceStatusPlaying = 0x607; //public static final int VlmMediaInstanceStatusPause = 0x608; //public static final int VlmMediaInstanceStatusEnd = 0x609; //public static final int VlmMediaInstanceStatusError = 0x60a; public static final int CustomMediaListExpanding = 0x2000; public static final int CustomMediaListExpandingEnd = 0x2001; public static final int CustomMediaListItemAdded = 0x2002; public static final int CustomMediaListItemDeleted = 0x2003;
但是必须确保jni中存在。其余就是添加移除handler的方法:
public void addHandler(Handler handler) { if (!mEventHandler.contains(handler)) mEventHandler.add(handler); } public void removeHandler(Handler handler) { mEventHandler.remove(handler); } /** This method is called by a native thread **/ public void callback(int event, Bundle b) { b.putInt("event", event); for (int i = 0; i < mEventHandler.size(); i++) { Message msg = Message.obtain(); msg.setData(b); mEventHandler.get(i).sendMessage(msg); } }
最后就是VideoPlayerActivity,视频播放的页面。其实我也不太会写博客,总想记录一些,学习一些,也知道自己写的不好,基本都是复制粘贴,只是遇到的一些坑能够写出来,让大家少走弯路,还是希望大神可以指点指点。不喜勿喷。
- 基于安卓平台,客户端视频监控的实现(二)
- 基于安卓平台,客户端视频监控的实现(一)
- 基于安卓平台,客户端视频监控的实现(三)
- 基于QT的多线程视频监控的实现(二)
- 视频监控安防平台-基于log4cplus的log日志封装(linux版本)
- 基于MFC的视频监控系统客户端实现 ---项目经验
- 安卓视频监控实现
- 基于树莓派和安卓客户端的移动监控系统
- 基于EasyPlayer和EasyPusher实现安卓平台的双向视频对讲
- [转]基于EasyPlayer和EasyPusher实现安卓平台的双向视频对讲
- 安卓视频播放器的实现(基于vitamio)
- 基于QT的多线程视频监控的实现(一)
- 基于雷达的安防视频监控系统软件设计
- 基于ARM平台的远程视频监控系统的研究
- 基于达芬奇平台的视频监控系统的设计
- 基于iOS平台的视频监控应用程序的架构图
- 基于达芬奇平台的微波视频监控系统
- 【CSDN开源夏令营】 基于Web的SSH客户端,实现跨平台的云服务管理(二)环境搭配
- linux 从电脑拷贝文件到手机
- cjson
- HashMap与TreeMap按照key和value排序
- 内核栈和用户栈
- chromium编译缺少LASTCHANGE.blink
- 基于安卓平台,客户端视频监控的实现(二)
- android dumpsys命令使用
- Pyunit源码笔记之十一 pyunit运行方式之二:testsuit方式
- 机器学习通俗入门-Softmax 求解多类分类问题
- EM算法学习
- JS退出操作
- IDEA为git项目开启git支持
- Oracle备份命令、增量备份命令:exp/imp 的用法
- TP 路由重写--伪静态设置