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

在开发视频播放功能时遇到MediaPlayer错误:Error (1,-2147483648)。问题可能源于库的兼容性,通过切换到原生VideoView测试,并分析MediaPlayer的生命周期,发现可能是播放引擎内核不兼容。解决方案是采用不同的播放引擎,如ExoPlayer,从而成功实现视频的多次播放。" 112681924,10547421,Cocos2d游戏项目集成Webpack与微前端实践,"['游戏开发', 'Cocos2d', 'Webpack', '模块化', '微前端']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MediaPlayer: Error (1,-2147483648)

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

原作链接: jiaoziVideoPlayer

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

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

查看官方文档得知mediaplayer的生命周期:
https://developer.android.com/images/mediaplayer_state_diagram.gif
也就是直接从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也是不支持的,这是最简便的方案就是换播放引擎了;

<think>好的,用户遇到了Android日志中出现&#39;VideoScene: audio stop&#39;后视频卡住的问题,需要找到原因和解决方法。首先,我要根据提供的引用资料和相关知识来分析可能的原因。 首先,引用[1]提到dumpsys audio可以获取音频系统的状态,比如音量、设备、策略等,这可能帮助诊断音频问题。用户的问题中涉及音频停止,可能需要检查音频设备的状态或音频焦点是否被抢占,导致视频卡住。例如,音频焦点丢失可能导致视频暂停或停止播放,但这里用户的情况是视频卡住,可能需要进一步分析。 引用[2]关于tombstone日志分析,通常用于native层的崩溃,但视频卡住不一定是崩溃,可能更多是逻辑问题或资源冲突。不过如果视频卡住伴随底层库崩溃,可能需要检查tombstone日志。但用户的问题中暂时没有提到崩溃,所以可能先不考虑这个方向。 引用[3]是关于依赖库的问题,这里似乎不相关,但需要考虑是否有第三方库(比如视频处理库)版本不兼容导致的问题,但用户的问题中没有提到编译或依赖错误,所以暂时排除。 引用[4]提到保存log到本地,用户可能需要长时间记录log来捕捉问题发生时的日志,尤其是在疲劳测试时。建议用户使用adb logcat导出完整日志,过滤VideoScene相关条目,查看上下文是否有错误信息。 接下来分析可能的原因:音频服务异常停止导致视频播放器进入错误状态,音频设备异常或配置错误,音频焦点被其他应用抢占,解码器或音视频同步问题,第三方库或系统服务的兼容性问题。 解决方法方面,首先检查音频焦点管理,确保正确处理焦点丢失的情况。使用dumpsys audio检查音频设备状态,确认输出设备正常。检查MediaCodec或ExoPlayer的解码状态,是否有解码错误导致视频卡住。查看是否有ANR日志或主线程阻塞,使用systrace分析性能。更新或回滚音视频库版本,排除兼容性问题。最后,提供问题复现方法,帮助定位具体原因。 需要确保用户按照步骤逐步排查,结合日志和工具进行分析。同时,引用相关的参考资料,如dumpsys audio的使用和日志保存方法,来支持解决方案的可行性。</think>### Android日志中"VideoScene: audio stop"导致视频卡住的排查指南 #### 一、可能原因分析 1. **音频焦点冲突** 当其他应用抢占音频焦点时,系统可能触发$audio\ stop$事件,若播放器未正确处理焦点丢失事件,会导致视频播放状态异常[^1]。典型表现为音频停止后视频画面卡在最后一帧。 2. **音频设备异常** 蓝牙耳机断开/USB音频设备异常时,可能触发音频管线重建失败。可通过`adb shell dumpsys audio`检查输出设备状态: ```bash adb shell dumpsys audio | grep "Devices:" ``` 3. **解码器状态不同步** 出现$VideoScene: audio\ stop$日志后,视频解码器可能因缓冲区不足进入等待状态,造成音视频时钟不同步。可通过MediaCodec的`getOutputFormat()`检查解码状态。 #### 二、详细排查步骤 1. **获取完整日志** ```bash adb logcat -v threadtime -b main -b system -b crash > videobug.log ``` 使用`grep "VideoScene\|AudioTrack" videobug.log`过滤关键事件链(建议结合引用[4]的方法持久化日志) 2. **检查音频焦点堆栈** ```bash adb shell dumpsys audio | grep -A 15 "Focus stack:" ``` 观察焦点持有者是否为当前视频应用,若出现`uid=xxxx (NOT current)`说明焦点被抢占 3. **验证音频管线状态** ```java // 在播放器回调中添加状态检查 mediaPlayer.setOnErrorListener((mp, what, extra) -> { Log.e("Player", "ErrorCode:"+what+" Extra:"+extra); return true; }); ``` 4. **硬件加速诊断** 在开发者选项中关闭"硬件加速渲染",观察软件解码是否正常。若问题消失,需检查: ```bash adb shell dumpsys media.codec # 查看OMX组件状态 ``` #### 三、典型解决方案 1. **增加焦点监听恢复机制** ```java audioManager.requestAudioFocus(focusRequest, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); // 焦点丢失处理 onAudioFocusChangeListener = (focusChange) -> { if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { mediaPlayer.pause(); } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { if(!mediaPlayer.isPlaying()) mediaPlayer.start(); } }; ``` 2. **修复解码器同步问题** 当音频流意外终止时,需重置视频时钟: ```c // Native层示例(如使用FFmpeg) avcodec_flush_buffers(video_codec_ctx); video_clock = audio_clock; // 强制同步时钟 ``` 3. **设备兼容性处理** 在`AudioTrack`初始化时添加设备变化监听: ```java audioManager.registerAudioDeviceCallback(new AudioDeviceCallback() { @Override public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { // 重新初始化音频管线 } }, null); ``` : Android音频焦点管理规范要求应用在失去焦点时应暂停播放,但部分播放器实现可能未正确处理该事件 [^4]: 持续日志记录有助于捕捉偶现问题,建议结合logcat环形缓冲区保存崩溃前日志
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值