Rockchip机顶盒ExoPlayer播放4K视频遇内存不足问题求助
Rockchip机顶盒ExoPlayer播放特定4K视频内存不足(OOM)问题排查与解决
问题场景
- 在Rockchip机顶盒设备上使用ExoPlayer播放本地4K视频,全高清视频及多数4K视频播放正常,但少数4K视频会出现严重卡顿,最终播放冻结并抛出内存不足错误
- ExoPlayer官方演示应用可正常播放该问题视频,但自身应用因需同时处理视频下载、WebSocket长连接等任务,内存占用比演示应用高,但理论上仍应支持播放
- 转码问题视频后可正常播放
错误日志
GC及内存限制日志
D/EventLogger: videoSize [eventTime=1.49, mediaPos=0.00, window=0, period=0, 3840, 2160] 2022-11-11 11:21:32.323 13639-13639/com.example.package D/EventLogger: renderedFirstFrame [eventTime=1.49, mediaPos=0.00, window=0, period=0, Surface(name=null)/@0x1dcfafd] 2022-11-11 11:21:32.341 13639-13639/com.example.package D/EventLogger: state [eventTime=1.51, mediaPos=0.05, window=0, period=0, READY] 2022-11-11 11:21:32.341 13639-13639/com.example.package I/VideoFragment: onPlayerStateChanged: 3 2022-11-11 11:21:32.342 13639-13639/com.example.package D/EventLogger: isPlaying [eventTime=1.51, mediaPos=0.05, window=0, period=0, true] 2022-11-11 11:21:32.610 13639-13650/com.example.package I/art: Clamp target GC heap from 203MB to 192MB 2022-11-11 11:21:32.636 13639-13714/com.example.package I/art: Waiting for a blocking GC Alloc 2022-11-11 11:21:32.644 13639-13714/com.example.package I/art: WaitForGcToComplete blocked for 7.544ms for cause Alloc 2022-11-11 11:21:32.644 13639-13714/com.example.package I/art: Starting a blocking GC Alloc 2022-11-11 11:21:32.644 13639-13714/com.example.package I/art: Starting a blocking GC Alloc
(后续存在大量blocking GC Alloc日志)
OOM错误堆栈
2022-11-11 11:10:51.403 13452-13535/com.example.package E/LoadTask: OutOfMemory error loading stream java.lang.OutOfMemoryError: Failed to allocate a 65548 byte allocation with 53032 free bytes and 51KB until OOM at com.google.android.exoplayer2.upstream.DefaultAllocator.allocate(DefaultAllocator.java:102) at com.google.android.exoplayer2.source.SampleDataQueue.preAppend(SampleDataQueue.java:233) at com.google.android.exoplayer2.source.SampleDataQueue.sampleData(SampleDataQueue.java:176) at com.google.android.exoplayer2.source.SampleQueue.sampleData(SampleQueue.java:590) at com.google.android.exoplayer2.extractor.TrackOutput.sampleData(TrackOutput.java:157) at com.google.android.exoplayer2.extractor.mp4.Mp4Extractor.readSample(Mp4Extractor.java:652) at com.google.android.exoplayer2.extractor.mp4.Mp4Extractor.read(Mp4Extractor.java:259) at com.google.android.exoplayer2.source.BundledExtractorsAdapter.read(BundledExtractorsAdapter.java:127) at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1039) at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:761)
解决措施
1. 限制ExoPlayer内存分配
针对DefaultAllocator设置最大分配内存,避免样本数据占用过多内存:
// 初始化Allocator,设置单个分配块大小及最大总分配内存 DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE); allocator.setMaxAllocationBytes(10 * 1024 * 1024); // 可根据设备性能调整,例如10MB // 将配置好的Allocator传入媒体源工厂 ProgressiveMediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory( new DefaultDataSourceFactory(context, Util.getUserAgent(context, "YourAppName")), new DefaultExtractorsFactory()) .setAllocator(allocator);
2. 优化应用自身内存占用
因应用同时运行下载、WebSocket等任务,需主动释放闲置资源:
- 视频播放期间,暂停下载任务的非必要线程,播放结束后恢复
- WebSocket连接复用实例,避免冗余创建;闲置时清理未使用的缓存数据
- 实现
ComponentCallbacks2接口,在onTrimMemory回调中主动释放非必要资源(如缓存图片、闲置对象)
3. 强制硬件解码减少内存开销
问题视频可能因软件解码占用过多内存,可强制ExoPlayer使用硬件解码:
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(context) .setEnableDecoderFallback(false) // 禁用软件解码降级 .setPreferredVideoRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER); SimpleExoPlayer player = new SimpleExoPlayer.Builder(context, renderersFactory).build();
4. 调整应用堆内存限制
从日志看出应用堆内存被限制在192MB,可在AndroidManifest.xml中启用大堆模式(仅作为临时缓解,优先优化内存使用):
<application ... android:largeHeap="true"> </application>
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

