MediaPlayer: Error (1,-2147483648)
最近在开发视频播放相关内容,使用一个集成很好的库,饺子播放器
原作链接: jiaoziVideoPlayer
问题描述: 在播放视频的时候,部分手机完全正常,部分手机播放部分视频完全正常,部分手机播放部分视频只能安装时播放一次后面就一直mediaplayer error 1
主观判断是不是库不兼容了,查看一堆issue后,感觉可能是因为播放引擎内核不兼容;
于是改用原生videoview测试,测试结果如图:
MEDIA_ERROR_UNKNOWN
查看官方文档得知mediaplayer的生命周期:
也就是直接从setDataSource
后直接进入到 onErrorListener.onError
中,并且文档中注明:
- 当一个mediaplayer 被new 或者 reset()调用后,此时处于Idle空闲状态; 在release()方法被调用后,此时处于End结束状态,在这两个状态之间就是mediaplayer的生命周期;
- 通过mediaplayer的构造器和reset()方法调用之间使用一些不同; 在空闲状态下调用诸如
getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(android.media.AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() or prepareAsync()
这类方法是一个编程错误; 如果在mediaplayer被创建后 其中一个方法被正确调用后,用户提供onErrorListener.onError
的回调不会被内部播放引擎调用并且对象状态维持不变; 但是如果那些方法是在reset()
方法调用后调用,用户提供的onErrorListener.onError
回调将会被播放引擎调用并且对象状态将会被转变为End
状态; - 推荐一旦mediaplayer对象不再被使用,立即调用
release()
方法为了使和内部播放引擎相联系的mediaplayer的资源可以立即被回收; 其中,资源可能包含单例资源如硬件加速组件,而release()
的调用失败可能造成随后的mediaplayer对象回退到使用软件实现或者全部失败; 一旦mediaplayer对象处于End
状态,就不能再使用了并且没有方法使之转变为其他状态; - 此外,使用
new
创建的mediaplayer 对象处于Idle状态,而用create
的重载方法之一创建的对象不是处于Idle状态; 实际上,成功使用create
方法创建的对象处于Prepared状态;
- 通过mediaplayer的构造器和reset()方法调用之间使用一些不同; 在空闲状态下调用诸如
- 一般来说,由于多种原因一些回放控制操作可能失败,如不支持的音视频格式,不良交错的音视频,分辨率太高,流超时等等; 因此,在这种情况下错误报告和发现是一个很重要的关注点;有时,因为编程错误,在一个无效的状态调用回放控制操作也可能导致错误; 在所有错误的条件下,如果一个OnErrorListener 已经预先通过
setOnErrorListener(OnErrorListener)
提供了,那么内部的播放引擎会调用此回调;- 重要的要注意,一旦错误发生,mediaplayer对象会进入Error状态(上述情况除外),即时error 监听没有被应用程序注册;
- 为了重用 处于Error 状态的mediaplayer 对象且从错误中恢复,调用
reset()
恢复对象至Idle 状态; - 让你的应用程序注册 OnErrorListener 监听 错误内部播放引擎的提示信息是一个好的编程实践;
IllegalStateException
异常由错误的调用prepare(), prepareAsync()
抛出,或者由在一个无效状态下的setDataSource其中一个重载方法抛出;
- 调用
setDataSource(java.io.FileDescriptor), or setDataSource(java.lang.String), or setDataSource(android.content.Context, android.net.Uri), or setDataSource(java.io.FileDescriptor, long, long), or setDataSource(android.media.MediaDataSource)
将一个mediaplayer 对象从 Idle状态转变为 Initialized状态;IllegalStateException
异常由 在其他状态下调用setDataSource()方法抛出;- 总是捕获
IllegalArgumentException and IOException
异常 在调用setDataSource方法时是一个好的编程实践;
- 在开始重放之前,mediaplayer对象必须首先进入prepare状态;
- 有两种方法进入Prepared状态(同步或异步): 要么 调用
prepare() 同步
一旦方法调用返回后转变为Prepared状态,要么调用prepareAsync() 异步
在调用返回后(几乎立即返回)首先转变为Preparing状态,而内部播放引擎持续做一些其余的准备工作直到准备工作完成; 当准备工作完成或者prepare()
调用返回,如果预先通过setOnPreparedListener
方法注册OnPreparedListener,内部播放引擎会调用用户提供的回调方法,OnPreparedListener接口的onPrepared 方法, - 重要的要注意Preparing是一个瞬态状态,当mediaplayer对象处于preparing状态时,调用任何具有副作用的方法的行为都是未定义的;
IllegalStateException
可由prepare() 或者prepareAsync()
抛出;- 当处于Prepared状态时,调用诸如
音视频 volume,screenonwhilePlaying,looping
的set方法都是可以调整的;
- 有两种方法进入Prepared状态(同步或异步): 要么 调用
- 为了开始播放,
start()
方法必须调用,在start()返回成功后,mediaplayer 对象处于Started 状态,isPlaying()
可以被调用测试 mediaplayer 对象是否处于 Started 状态;- 当处于Started状态时,内部播放引擎可回调用户提供的
OnBufferingUpdateListener
(setOnBufferingUpdateListener),这个调用允许应用程序当流媒体播放时保持跟踪缓存状态; - 对已处于Started状态的Mediaplayer调用start无效;
- 当处于Started状态时,内部播放引擎可回调用户提供的
- 通过调用
paused
方法可以暂停播放,进入 Paused状态;需要注意的是,无论Started状态转变为Paused状态还是相反的转变,在播放引擎中都是异步进行的; 在状态更新之前调用isPlaying()
可能需要一些时间,在一些流内容中需要秒数;\- 对处于Paused状态的mediaplayer 调用pause 无效;
- 调用
stop()
停止播放 可使 处于Started,Paused,Prepared or PlaybackCompleted
状态都进入到Stopped 状态;- 一旦进入Stopped状态,直到
prepare() or prepareAsync()
方法调用再次设置mediaplayer 对象 为Prepared 状态后,播放才能开始; - 对处于Stopped状态的mediaplayer调用stop无效;
- 一旦进入Stopped状态,直到
- 调用
seekTo(long,int)
可以调整播放位置- 虽然异步的
seekTo(long,int)
调用会立即返回,实际的seek操作还是需要一会儿去完成,特别对于流媒体; 在实际的seek操作完成时,内部播放引擎会调用OnSeekComplete.onSeekComplete方法; - 当在其他状态调用seekTo,如果流有video并且请求的位置是有效的会显示video帧;
- 此外,实际当前播放位置能调用
getCurrentPosition()
检索;
- 虽然异步的
- 当播放到达流的末尾,播放完成;
- 如果
setLooping(boolean)
为true,mediaplayer 对象 会维持在 Started状态; - looping设置为false,播放引擎会调用用户提供的回调OnCompletion.onCompletion方法;标志着对象处于PlaybackCompleated 状态;
- 当处于PlaybackCompleated状态,调用start()能重新开始播放音视频资源;
- 如果
无法播放视频信息为:
概要 | |||
完整名称 : | E:\temp_dm\temp-video\error.mp4 | ||
格式 : | MPEG-4 | ||
格式概况 : | Base Media / Version 2 | ||
编解码器ID : | mp42 (isom/iso2/avc1/mp41) | ||
文件大小 : | 7.96 MiB | ||
持续时间 : | 1 分 8 秒 | ||
混合码率模式 : | 动态(VBR) | ||
平均混合码率 : | 968 kb/s | ||
编码日期 : | UTC 2016-09-29 09:01:54 | ||
标记日期 : | UTC 2016-09-29 09:01:54 | ||
编码程序 : | HandBrake 0.10.5 2016021100 |
视频 | |||
ID : | 1 | ||
格式 : | AVC | ||
格式/信息 : | Advanced Video Codec | ||
格式概况 : | Main@L4 | ||
格式设置 : | CABAC / 4 Ref Frames | ||
格式设置, CABAC : | 是 | ||
格式设置, 参考帧 : | 4 帧 | ||
编解码器ID : | avc1 | ||
编解码器ID/信息 : | Advanced Video Coding | ||
持续时间 : | 1 分 8 秒 | ||
码率 : | 790 kb/s | ||
宽度 : | 720 像素 | ||
高度 : | 406 像素 | ||
画面比例 : | 16:9 | ||
原始画面比例 : | 16:9 | ||
帧率模式 : | 恒定 | ||
帧率 : | 24.000 帧/秒 | ||
色彩空间 : | YUV | ||
色度抽样 : | 4:2:0 | ||
位深 : | 8 位 | ||
扫描方式 : | 逐行扫描 | ||
数据密度【码率/(像素×帧率)】 : | 0.113 | ||
流大小 : | 6.49 MiB (81%) | ||
编码函数库 : | x264 core 142 r2479 dd79a61 | ||
编码设置 : | cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=2 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=0 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=0 / threads=6 / lookahead_threads=2 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=1 / keyint=240 / keyint_min=24 / scenecut=40 / intra_refresh=0 / rc_lookahead=10 / rc=crf / mbtree=1 / crf=20.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=20000 / vbv_bufsize=25000 / crf_max=0.0 / nal_hrd=none / filler=0 / ip_ratio=1.40 / aq=1:1.00 | ||
编码日期 : | UTC 2016-09-29 09:01:54 | ||
标记日期 : | UTC 2016-09-29 09:01:54 | ||
色彩范围 : | Limited | ||
基色 : | BT.709 | ||
传输特质 : | BT.709 | ||
矩阵系数 : | BT.709 | ||
Codec configuration box : | avcC |
音频 | |||
ID : | 2 | ||
格式 : | AAC LC | ||
格式/信息 : | Advanced Audio Codec Low Complexity | ||
编解码器ID : | mp4a-40-2 | ||
持续时间 : | 1 分 8 秒 | ||
码率模式 : | 动态(VBR) | ||
码率 : | 173 kb/s | ||
声道 : | 2 声道 | ||
ChannelLayout : | L R | ||
采样率 : | 48.0 kHz | ||
帧率 : | 46.875 帧/秒 (1024 SPF) | ||
压缩模式 : | 有损压缩 | ||
流大小 : | 1.42 MiB (18%) | ||
标题 : | Stereo / Stereo | ||
语言 : | 英语 (English) | ||
Default : | 是 | ||
备用组 : | 1 | ||
编码日期 : | UTC 2016-09-29 09:01:54 | ||
标记日期 : | UTC 2016-09-29 09:01:54 |
到此,并没有找到有价值的信息,因为是通过三方饺子播放器播放,代码层次new mediaplayer() 或者 release的该有的都有,应该是没有问题的;
最后判断 可能因为系统mediaplayer不支持, 然后通过饺子播放器的exoplayer策略换为exoplayer 替代mediaplayer
,成功实现了多次播放;
原生的播放引擎内核有些MP4也是不支持的,这是最简便的方案就是换播放引擎了;