上半部分为错误记录,下半部分为代码。
目前存在的问题(19/010/28)(平台:Android 5.1.1——内存:1G,存储:8G,CPU:RK3188,GPU:Mali400):
问题一:视频掉帧与触摸卡死
- TextureView为硬解,使用的是GPU,同时界面加载也使用的GPU,需要考虑mali400算力。
- VideoView(surfaceView)为软解,使用的是CPU。
- 爆满的CPU与GPU占用会导致触摸程序卡死,导致触摸屏失效。例如播放视频的同时, 快速连续点击屏幕或在屏幕上拖动等。(可能是这家厂商的问题,不一定是3188的锅,但无论是谁,为什么触摸程序卡死重启的机制都没有!!!)
解决:
- 优化布局和升级CPU。(上3288吧,哭,实际运行流畅度提升30%-40%)
- 相比较GPU,CPU播放要流畅不少,使用
AndroidVideoCache
与VideoView
播放进行规避,注意:网络下载的时候也是很占CPU的,所以视频的清晰度和码率要控制好。(传送门) - 双视频一个
Videoview
软解,一个TextureView
硬解,降低负载。(有想法没做过,因为这时的我已经升级为3288了,稽)
问题二:解码报错
- 加载某些网络视频会报如下错误,且视频卡死,可添加监听处理
- 卡死后疯狂弹出log:E/H264_DEBUG( 478): OutputPicture# no pictures to be displayed
- 解码器报错与码率无关,播放另一份40M,1080p,1900kps的视频没有出现700报错
解决:
- 报错不可怕,让他报去,加载完之后就不卡了,预计也是CPU的原因,处理好播放器Error后的处理。
问题三:createGraphicBuffer failed与EGL_BAD_ALLOC——之前出现过一段时间,目前未再出现,可忽略待定
- 情景再现:两份上述40M的视频同时播放,其中一个视频黑屏未播放,另一份正常无报错。
- 黑屏视频加载时报错
E/BufferQueueProducer: [unnamed-1849-1] dequeueBuffer: createGraphicBuffer failed
- 关闭视频后报错
E/libEGL: eglMakeCurrent:786 error 3003 (EGL_BAD_ALLOC)
A/OpenGLRenderer: Failed to make current on surface 0x42763da0, error=EGL_BAD_ALLOC
public class TextureMedia implements TextureView.SurfaceTextureListener, MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {
String url;
Surface surface;
TextureView textureView;
MediaPlayer mediaPlayer;
public TextureMedia(TextureView textureView, MediaPlayer mediaPlayer,String url) {
this.textureView = textureView;
this.mediaPlayer = mediaPlayer;
this.url = url;
creat();
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
surface = new Surface(surfaceTexture);
}
public void creat(){
textureView.setSurfaceTextureListener(this);
mediaPlayer.setLooping(true);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setScreenOnWhilePlaying(true);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
new PlayerVideoThread().start();
}
private class PlayerVideoThread extends Thread{
@Override
public void run() {
try {
mediaPlayer.setDataSource(url);
mediaPlayer.setVideoScalingMode(VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
mediaPlayer.prepareAsync();
} catch (IllegalStateException ie){
ie.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onPrepared(MediaPlayer mp) {
mp.setSurface(surface);
mp.start();
}
@Override
public void onCompletion(MediaPlayer mp) {
mp.start();
}
public void restar(){
try {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
restar();
return true;
}
public void start(){
mediaPlayer.start();
}
public void pause(){
mediaPlayer.pause();
}
public void stop(){
mediaPlayer.stop();
}
public void release(){
if (mediaPlayer!=null){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer=null;
}
}
public void setVolume(int volume){
mediaPlayer.setVolume(volume,volume);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}
主线程调用
mediaPlayer1 = new MediaPlayer();
mediaPlayer2 = new MediaPlayer();
textureMedia1 = new TextureMedia(textureView1,mediaPlayer1,mp4url1);
textureMedia2 = new TextureMedia(textureView2,mediaPlayer2,mp4url2);