问题记录: 关于视频播放 mediaplayer errorcode 1

MediaPlayer: Error (1,-2147483648)

最近在开发视频播放相关内容,使用一个集成很好的库,饺子播放器

原作链接: jiaoziVideoPlayer

问题描述: 在播放视频的时候,部分手机完全正常,部分手机播放部分视频完全正常,部分手机播放部分视频只能安装时播放一次后面就一直mediaplayer error 1

主观判断是不是库不兼容了,查看一堆issue后,感觉可能是因为播放引擎内核不兼容;
于是改用原生videoview测试,测试结果如图:
在这里插入图片描述
MEDIA_ERROR_UNKNOWN

查看官方文档得知mediaplayer的生命周期:
问题记录: 关于视频播放 mediaplayer errorcode 1_第1张图片
也就是直接从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状态;
  • 一般来说,由于多种原因一些回放控制操作可能失败,如不支持的音视频格式,不良交错的音视频,分辨率太高,流超时等等; 因此,在这种情况下错误报告和发现是一个很重要的关注点;有时,因为编程错误,在一个无效的状态调用回放控制操作也可能导致错误; 在所有错误的条件下,如果一个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方法都是可以调整的;
  • 为了开始播放,start()方法必须调用,在start()返回成功后,mediaplayer 对象处于Started 状态,isPlaying()可以被调用测试 mediaplayer 对象是否处于 Started 状态;
    • 当处于Started状态时,内部播放引擎可回调用户提供的OnBufferingUpdateListener(setOnBufferingUpdateListener),这个调用允许应用程序当流媒体播放时保持跟踪缓存状态;
    • 对已处于Started状态的Mediaplayer调用start无效;
  • 通过调用paused方法可以暂停播放,进入 Paused状态;需要注意的是,无论Started状态转变为Paused状态还是相反的转变,在播放引擎中都是异步进行的; 在状态更新之前调用 isPlaying() 可能需要一些时间,在一些流内容中需要秒数;\
    • 对处于Paused状态的mediaplayer 调用pause 无效;
  • 调用 stop()停止播放 可使 处于Started,Paused,Prepared or PlaybackCompleted状态都进入到Stopped 状态;
    • 一旦进入Stopped状态,直到prepare() or prepareAsync()方法调用再次设置mediaplayer 对象 为Prepared 状态后,播放才能开始;
    • 对处于Stopped状态的mediaplayer调用stop无效;
  • 调用 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也是不支持的,这是最简便的方案就是换播放引擎了;

你可能感兴趣的:(开发问题记录)