IJKPlayer播放视频在iOS部分机型黑屏原因分析

一.背景

1.问题视频在iphone7p等机型上:视频无法正常播放(黑屏),音频正常播放。

2.问题视频在iphone XR机型上:音视频均能正常播放。

二.断点分析

1.问题视频在iphone7p上创建VideoToolBox解码器成功,解码失败(解码中失败IJKPlayer不能自动切换FFmpeg软解码),视频画面无法正常播放。

解码失败错误码:kVTVideoDecoderBadDataErr = -12909

2.问题视频在iphone XR上创建VideoToolBox解码器失败,IJKPlayer自动切换FFmpeg软解码,软解码成功,视频画面正常播放。

解码器创建失败错误码:kVTVideoDecoderMalfunctionErr = -12911

3.以上现象说明此视频无法使用VideoToolBox硬解码。

VideoToolBox为苹果官方提供的编解码库,使用GPU硬编解码。官方文档对错误码未提供更详细的信息。

三.格式分析

1.使用ffprobe分析问题视频的码流格式,包完整性等均未发现问题。

2.使用ffprobe分析问题视频与正常视频格式,对比发现,正常视频为帧编码,扫描方式为逐行扫描。问题视频为场编码,扫描方式为隔行扫描。

逐行扫描视频的表示方法为:720p,1080p,p是progressive“逐行”的缩写。

隔行扫描视频的表示方法为:720i,1080i,i是interlace“交错”的缩写。

四.验证VideoToolBox是否支持场编码

1.测试一:将帧编码视频转码为场编码格式视频(逐行转隔行)。
测试二:将问题视频转码为帧编码视频(隔行转逐行)。

使用FFmpeg命令行:
逐行转隔行:
ffmpeg -i input.mp4 -aspect 16:9 -c:v h264 -b:v 4000k -minrate 4000k -maxrate 4000k -bufsize 2000k -dc 9 -flags +ilme+ildct -alternate_scan 1 -top 0 output.mp4

隔行转逐行:
ffmpeg -i input.mp4 -aspect 16:9 -c:v h264 -b:v 4000k -minrate 1000k -maxrate 2000k -bufsize 2000k -dc 9 -deinterlace output.mp4

2.转码后使用MediaInfo工具检查是否转码成功。

逐行视频在“扫描方式”处显示“逐行扫描”或“progressive”。

隔行视频在“扫描方式”处显示“MBAFF”或“interlace”等。“扫描顺序”为“奇数场优先”等(逐行扫描无奇偶场概念)。

3.导入IJKPlayer验证,帧编码(逐行扫描)视频硬解码成功。场编码(隔行扫描)视频解码失败。

(后续会增加测试视频样本量,确保验证的可靠性)

五.解决方案

1.iOS端解决方案:在VideoToolBox解码器创建前判断视频为场编码还是帧编码,若为场编码,则直接走硬解码器创建失败流程,切换为FFmpeg软解码,避免出现硬解码创建成功而解码失败的问题。

判断方法:提取H264中的SPS序列参数集信息。根据SPS的句法,通过frame_mbs_only_flagmb_adaptive_frame_field_flagfield_pic_flag三个字段判断。

2.服务端解决方案:将场编码视频转码为帧编码。

实际上,如果是会议或培训等画面内容变动不大的视频,使用帧编码更为合适,可有效去除空间冗余,画面更清晰。

你可能感兴趣的:(IJKPlayer播放视频在iOS部分机型黑屏原因分析)