概述
最近在做安卓视频模块,背景如下:
视频竖屏播放时,SurfaceView不能对视频进行翻转,采用安卓4.0后的TextureView新控件又会容易受到硬件性能影响(包括TextureView在内试过好几个OpenGL实现的视频播放控件,其性能都更容易收到性能影响,比如播放帧率较大的视频时或者有多个图片资源不断切换时会造成卡顿和丢帧),采用Vitamio后可以解决竖屏播放问题,但其性能还是有待优化。
先奉上Vitamio官方帮助文档地址:Vitamio Android 开发建议
在近一周的修改后,解决了Vitamio视频框架中以下问题
Vitamio播放逻辑修改
官方给予的Demo其播放逻辑并不强大,但视频的切换做的很流畅基本不会出现中间黑屏,看了一下,是对MediaPlayer做了处理,在视频将要播放completion的时候(一般是结束前1秒)会发出一个提醒,应该是在so库中封装的吧。为了不每次setDatasource的时候都释放资源并重新初始化为VideoView.java中做了以下修改:
1.添加了stop()用于停止播放。
public void stop() {
if (mMediaPlayer != null) {
if (isInPlaybackState()) {
if (mMediaPlayer.isPlaying() || mMediaPlayer.getCurrentPosition()>0) {
mMediaPlayer.stop();
mCurrentState = STATE_IDLE;
}
}
mMediaPlayer.reset();
mTargetState = STATE_IDLE;
}
}
...
因为在官网提供的MediaPlayer中release()函数如下:
public void release() {
stayAwake(false);
updateSurfaceScreenOn();
mOnPreparedListener = null;
mOnBufferingUpdateListener = null;
mOnCompletionListener = null;
mOnSeekCompleteListener = null;
mOnErrorListener = null;
mOnInfoListener = null;
mOnVideoSizeChangedListener = null;
mOnCachingUpdateListener = null;
mOnHWRenderFailedListener = null;
if (mEventHandler != null)
mEventHandler.release();
//mEventHandler = null;
_release();
closeFD();
mInBuffering = false;
mNeedResume = false;
}
在设置资源的时候就可以这样进行调用了,可以保证其不会总是创建和释放对象。
/**
* 设置播放资源,设置播放事件
*/
private void videoHandles() {
filePath = this.videos_A.get(curVideoIndex);
try {
synchronized ((ADPageActivity) mContext) {
if(filePath.indexOf("http:")>-1){
mUIParser.sfv.setBufferSize(1536 * 1024);
}else if(filePath.indexOf("/")==0){
mUIParser.sfv.setBufferSize(0);
}
if(onPreparedListener == null){
onPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
// optional need Vitamio 4.0
mediaPlayer.setPlaybackSpeed(1.0f);
}
};
mUIParser.sfv.setOnPreparedListener(onPreparedListener);
}
if(onCompletionListener == null){
onCompletionListener = new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer arg0) {
Log.i(Tag, "MMediaPlayer onCompletion");
playNextVideo();
}
};
mUIParser.sfv.setOnCompletionListener(onCompletionListener);
}
if(onErrorListener == null){
onErrorListener = new OnErrorListener() {
@Override
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
Log.e(Tag, "MMediaPlayer onError !!");
playNextVideo();
return true;//返回true,这个回调函数才会起作用,以下为官方解释:
//True if the method handled the error, false if it didn't. Returning false, or not having an OnErrorListener at all, will cause the OnCompletionListener to be called.
}
};
mUIParser.sfv.setOnErrorListener(onErrorListener);
}
if(filePath.indexOf("http:")>-1){
mUIParser.sfv.setVideoURI(Uri.parse(filePath));
}else if(filePath.indexOf("/")==0){
mUIParser.sfv.setVideoPath(filePath);
}
//
if(mMediaController==null){
//
mMediaController = new MediaController(mContext);//实例化控制器
//
mMediaController.show(2000);//控制器显示2s后自动隐藏
//
mUIParser.sfv.setMediaController(mMediaController);//绑定控制器
//
}
mUIParser.sfv.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);//设置播放画质 高画质
mUIParser.sfv.requestFocus();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void playNextVideo() {
Log.i(Tag, "curVideoIndex : " + curVideoIndex);
// 网络播放模式时,播完一条视频上传记录至服务器
if (sourceMode == 0)
uploadPlayData(curVideoIndex);
if (videos_A != null && videos_A.size() > 0) {
curVideoIndex++;
if (curVideoIndex >= this.videos_A.size()) {
curVideoIndex = 0;
// initAdPlayer();
}
filePath = this.videos_A.get(curVideoIndex);
Log.i(Tag, "filePath : " + filePath);
if(filePath.indexOf("http:")>-1){
mUIParser.sfv.setVideoURI(Uri.parse(filePath));
}else if(filePath.indexOf("/")==0){
mUIParser.sfv.setVideoPath(filePath);
}
}
}
Vitamio播放界面自动匹配视频大小修改为固定视频控件大小
不论你xml或者设置的播放控件多大,其播放画面大小会根据视频实际进行匹配,与以下代码有关:
setVideoLayout(mVideoLayout, mAspectRatio);
...
public void setVideoLayout(int layout, float aspectRatio) {
LayoutParams lp = getLayoutParams();
Pair<Integer, Integer> res = ScreenResolution.getResolution(mContext);
int windowWidth = res.first.intValue(), windowHeight = res.second
.intValue();
float windowRatio = windowWidth / (float) windowHeight;
float videoRatio = aspectRatio <= 0.01f ? mVideoAspectRatio
: aspectRatio;
mSurfaceHeight = mVideoHeight;
mSurfaceWidth = mVideoWidth;
if (VIDEO_LAYOUT_ORIGIN == layout && mSurfaceWidth < windowWidth
&& mSurfaceHeight < windowHeight) {
lp.width = (int) (mSurfaceHeight * videoRatio);
lp.height = mSurfaceHeight;
} else if (layout == VIDEO_LAYOUT_ZOOM) {
lp.width = windowRatio > videoRatio ? windowWidth
: (int) (videoRatio * windowHeight);
lp.height = windowRatio < videoRatio ? windowHeight
: (int) (windowWidth / videoRatio);
} else if (layout == VIDEO_LAYOUT_FIT_PARENT) {
ViewGroup parent = (ViewGroup) getParent();
float parentRatio = ((float) parent.getWidth())
/ ((float) parent.getHeight());
lp.width = (parentRatio < videoRatio) ? parent.getWidth() : Math
.round(((float) parent.getHeight()) * videoRatio);
lp.height = (parentRatio > videoRatio) ? parent.getHeight() : Math
.round(((float) parent.getWidth()) / videoRatio);
} else {
boolean full = layout == VIDEO_LAYOUT_STRETCH;
lp.width = (full || windowRatio < videoRatio) ? windowWidth
: (int) (videoRatio * windowHeight);
lp.height = (full || windowRatio > videoRatio) ? windowHeight
: (int) (windowWidth / videoRatio);
}
setLayoutParams(lp);
getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight);
Log.d("VIDEO: %dx%dx%f, Surface: %dx%d, LP: %dx%d, Window: %dx%dx%f",
mVideoWidth, mVideoHeight, mVideoAspectRatio, mSurfaceWidth,
mSurfaceHeight, lp.width, lp.height, windowWidth, windowHeight,
windowRatio);
mVideoLayout = layout;
mAspectRatio = aspectRatio;
}
还有一些修改,我做了个Demo,供大家参考。目前还有个问题是:
在硬件环境不够强大的情况下
1.尽管在public void surfaceCreated(SurfaceHolder holder)中设置了mSurfaceHolder.setFormat(PixelFormat.RGBX_8888),但在个别机型上,播放一些视频还是会有很明显的花屏现象。应该跟Vitamio的底层so库有关系。
2.播放帧率较大视频还是会丢帧,卡顿。
以下是在我修改的基础上,省去了一些重要修改的Demo
http://download.csdn.net/detail/mengjiangyue/9577932
最后
以上就是开朗大叔为你收集整理的Vitamio的小修改及花屏问题的探讨的全部内容,希望文章能够帮你解决Vitamio的小修改及花屏问题的探讨所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复