Android播放器开发基础(一)
来源:互联网 发布:手机浏览器不加载js 编辑:程序博客网 时间:2024/06/11 11:59
Android播放器开发基础(一)
- MediaPlayer
- Android原生VideoView
- SurfaceView基础
- 播发器示例及列表播放器
Android中播放器的开发主要是在原生的MediaPayer组件或者第三方SDK的基础上进行功能和界面的开发。而第三方的SDK的方法基本和原生MediaPlayer一致,因为会考虑的和原生的使用一致。MediaPlayer组件上对解码、状态、响应做了处理,内部也基本是使用了主流的播放器的内核,如FFmpeg解码器,通过内核解码不同的视音频格式的媒体转换为图像、音频流,图像再通过如SurfaceView这样的控件显示绘制出来,用户通过在例如VideoView这样的控件上操作控制播放过程。
1.MediaPlayer的状态
1.1 MediaPlayer中使用了状态机模式,包括10种状态,以及一系列操作,每个操作都可能影响到当前的状态。
实际开发过程中,只需要知道使用MediaPlayer播放器就可以了,如果还要开发视频则还需要了解VideoView甚至SurfaceView。MediaPlayer使用了状态机设计模式,操作以后MediaPlayer或到达一个状态,这个状态也限制了下一步的操作方式,所以要使用MediaPlayer首先需了解其10个基本状态,以及对应的操作方法,如果在不同的状态使用了一些不支持的操作则会造成MediaPlayer异常。
视频获取第一帧预览图
private Bitmap createVideoThumbnail2(String url, int width, int height) { Bitmap bitmap = null; // MediaMetadataRetriever获取帧的管理类 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); int kind = MediaStore.Video.Thumbnails.MINI_KIND; try { if (Build.VERSION.SDK_INT >= 14) { // 设置数据源 retriever.setDataSource(url, new HashMap<String, String>()); } else { retriever.setDataSource(url); } // 获取帧 bitmap = retriever.getFrameAtTime(); } catch (IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { // Assume this is a corrupt video file. } finally { try { retriever.release(); } catch (RuntimeException ex) { // Ignore failures while cleaning up. } } if (kind == Images.Thumbnails.MICRO_KIND && bitmap != null) { bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); } return bitmap; }
2. Android原生VideoView
播放器开发分为视频播放器和音频播放器,前者是需要同时绘制画面到屏幕上,后者则只是进行音频播放。视频播放中,Android通过SurfaceView来绘制画面。SurfaceView作为一个特殊的View,其内部内嵌了使用异步刷新的Surface来绘制画面,所以SurefaceView 是不会阻塞UI线程的,有时在绘制复杂的界面时也会通过SurfaceView绘制,以防止出现ANR,提高用户体验。在Android中提供了一个通用的控件VideoView,其继承了SurfaceView并封装了对MediaPlayer的操作,简单播放器开发就可以直接使用VideoView。
VideoView仅支持Android原生的MediaPlayer,而在很多情况下MediaPlayer的支持的媒体类型或媒体格式版本不能满足实际开发需求,如不支持Rtmp实时流,这样一来需要使用第三方解码器,而且还需要自定义一个VideoView来兼容当前解码器
2.1 VideoView的结构
VideoView继承了SurfaceView,所以它是一个可以进行图像绘制的控件,实现了MediaPlayerControl接口——一个MediaContoller的内部接口,而VideoView中包含MediaController,这样一来用户在操作MediaController的时候可以传递到VideoView中,再进一步通过MediaPlayer处理。
实际上VideoView既是一个显示控件,也是一个处理交互的控制器,同时为了进一步视图和控制器分离,将进度条、控制按钮都放到MedaiContoller中,通过MediaPlayerController接口来回调SurfaceView,形成了一个MVC的模式
(引用其他的博客)
3. SurfaceView基础
SurfaceView 是继承View的,但是其内部封装了一个Surface异步显示控件,Surface可以绘制图像,绘制的同时也不占用UI线程。
主要类:
- SurfaceView
内部包含了SurfaceHolder以及Surface,SurfaceView控制这个Surface在屏幕中绘制的位置
- SurfaceHolder
一个用于控制Surface的接口,用于控制Surface的尺寸位置,监听Surface变化以及改变Surface的像素
- Surface
Surface是原始图像缓冲区的一个句柄,而原始图像缓冲区是屏幕图像合成器管理的,S>urface内部封装了Canvas画布,可以通过这个画布得到当前绘制的图案
- Canvas
// 获取surfaceHolder SurfaceHolder surfaceHolder = SurfaceView.getHolder(); // surface 获取到SurfaceView中的Surface Surface surface = surfaceHolder.getSurface(); // Canvas Rect rect = new Rect(100,50,400,350); Canvas canvas = surface.lockCanvas(rect); surfaceHolder.unlockCanvasAndPost(canvas);
SurfaceView是用来显示和控制Surface的,而SurfaceHolder是暴露给用户操作Surface的,在视频开发中使用MediaPlayer解码通过Surface显示视频内容,MediaPlayer绑定Surface可以通MediaPlayer.setDisplay(SurfaceHolder或者MediaPlayer.setSurface(Surface),前者是SurfaceView中获取SurfaceHolder间接设置Surface的方式,后者是直接设置,所以视频播放中更换Surface就可以切换视频播放的位置而不用重新实例化一个MediaPlayer
mediaPlayer.setDisplay(big_surface_view.getHolder());
代码示例:(借用别人实现的代码)
下面的代码实现了一个自定义的SurfaceView,当SurfaceView创建时,通过设置监听SurfaceHolder.Callback,监听到内部Surface创建后开启一个线程获取到Surface上的Canvas,改变Canvas上的绘制信息,然后让surface重新绘制,得到最新的显示
/* * author: conowen * e-mail: conowen@hotmail.com * date : 2012.8.4 */ package com.conowen.SurfaceViewDemo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private String TAG = "conowen"; private SurfaceHolder sfh; private boolean ThreadFlag; private int counter; private Canvas canvas; private Thread mThread = new Thread(new Runnable() { @Override public void run() { while (ThreadFlag) { // 锁定画布,得到Canvas对象 canvas = sfh.lockCanvas(); // 设定Canvas对象的背景颜色 canvas.drawColor(Color.GREEN); // 创建画笔 Paint p = new Paint(); // 设置画笔颜色 p.setColor(Color.RED); // 设置文字大小 p.setTextSize(40); // 创建一个Rect对象rect // public Rect (int left, int top, int right, int bottom) Rect rect = new Rect(100, 50, 400, 350); // 在canvas上绘制rect canvas.drawRect(rect, p); // 在canvas上显示时间 // public void drawText (String text, float x, float y, Paint // paint) canvas.drawText("时间 = " + (counter++) + " 秒", 500, 200, p); if (canvas != null) { // 解除锁定,并提交修改内容,更新屏幕 sfh.unlockCanvasAndPost(canvas); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); public MySurfaceView(Context context) { super(context); // 通过SurfaceView获得SurfaceHolder对象 sfh = this.getHolder(); // 为SurfaceHolder添加回调结构SurfaceHolder.Callback sfh.addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.i(TAG, "surfaceChanged"); } @Override public void surfaceCreated(SurfaceHolder holder) { Log.i(TAG, "surfaceCreated"); counter = 0; ThreadFlag = true; mThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.i(TAG, "surfaceDestroyed"); ThreadFlag = false; } }
下节内容:
4. 播发器示例及列表播放器
5. 播放器开发小技巧
- Android播放器开发基础(一)
- Android播放器开发基础(二)
- android音乐播放器开发(一)
- Android音乐播放器(一)基础界面
- Android开发之音乐播放器(一)
- Android 调用ffmpeg 播放器开发(一)
- android开发视频播放器-----视频播放 Vitamio框架的使用(一)
- android基础学习笔记--MP3播放器开发
- Android基础(一)--Android开发开始
- Android音频开发(3):如何播放一帧音频
- Android音频开发(3):如何播放一帧音频
- android 播放器开发
- android 播放器开发
- Android 播放器开发
- android 在线mp3播放器(一)
- android 音乐播放器(一)
- VR Android播放器实现(一)
- Android应用开发--MP3音乐播放器代码实现(一)
- html和css基础(五)盒子模型
- DLL的Hello world
- 同步 异步 阻塞 非阻塞 (转载)
- SELECT模型
- 网络字节序与主机字节序
- Android播放器开发基础(一)
- 服务器端编程部分概念理解(转载)
- iOS 关于NSDate的一些记录
- CreateIoCompletionPort和完成端口
- 直接通过ADO操作Access数据库(转载…
- 用C++访问SQL Server 2000
- HDU---1004 Let the Balloon Rise【vector应用】
- Does Windows have a limit of 200…
- 几个数据库基础名词解释