SGPlayer在iPhoneXR机型上某个全景直播源黑屏,无法渲染,无法正常播放问题分析
问题描述:
最近在用SGPlayer 播放全景直播的时候遇到 某个视频源在8p上可以正常播放 ,但是在iPhoneXR上无法正常播放问题, iPhoneXR上除啦这个视频源 ,别的视频源是可以正常播放的。断点跑的时候未出现报错;
猜想1:可能是后台给的这个数据源有问题,毕竟iPhoneXR上别的视频是可以正常播放的,就只有这个视频不可以播放; 基于以上分析,于是我要求产品那边重新把这个源 作为一个新源 从开始 ,到转码 都重新做一遍,确保其播放参数和别的保持一致;但是遗憾的是,他们重新制作后,视频并不能正常播放;
猜想2:既然源可能没有问题 ,那有可能是播放器版本较低,于是更新了最新的SGPlayer 以及内部的SGFFmpeg ,遗憾的是 更换后还是不行
既然猜想的方法无法解决问题,那就老实跟代码,进行调试,查看
- SGPlayer的播放很简单 ,直接创见播放器, 给播放链接 开始播放就可以了 ,这个地方显然没有什么问题
[_playerSG replaceWithURL:[NSURL URLWithString:你的播放链接地址]];
SGDisplayMode playMode = SGDisplayModeVR ;
[_playerSG.videoRenderer setDisplayMode:playMode];
[self.playerSG play];
-
我找到视频解码的地方 SGVideoDecoder.m 在这个页面打了几个断点,发现数据在轮询的时候,每次是可以进到SGVideoDecoder.m 来解码 调用- (NSArray< __kindof SGFrame *> *)decode:(SGPacket *)packet方法的,但是这个方法在调用 [self processPacket:packet] 这个方法的时候,回去调用图2 [self->_codecContext decode:packet]
图1
图2
3. SGCodecContext.m 这个类的 decode 内部代码是这样的
```
- (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet
{
if (!self->_codecContext) {
return nil;
}
int result = avcodec_send_packet(self->_codecContext, packet ? packet.core : NULL);
if (result < 0) {
return nil;
}
NSMutableArray *array = [NSMutableArray array];
while (result != AVERROR(EAGAIN)) {
__kindof SGFrame *frame = [[SGObjectPool sharedPool] objectWithClass:self->_frameClass reuseName:self->_frameReuseName];
result = avcodec_receive_frame(self->_codecContext, frame.core);
if (result < 0) {
[frame unlock];
break;
} else {
[array addObject:frame];
}
}
return array;
}
```
-
于是我在这个地方添加了些打印
- (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet { NSLog(@"解码开始----frameClass:%@ ,frameReuseName:%@",self->_frameClass,self->_frameReuseName); NSMutableArray *array = [NSMutableArray array]; if (!self->_codecContext) { return nil; } int result = avcodec_send_packet(self->_codecContext, packet ? packet.core : NULL); if ([self->_frameReuseName isEqualToString:@"SGVideoFrame"]) { NSLog(@"循环前的result :frameClass:%@ , -- :%d",self->_frameClass,result); } if (result != 0) { return nil; } while (result != AVERROR(EAGAIN)) { NSLog(@"-while里的--frameClass:%@ ,:%@",self->_frameClass,self->_frameReuseName); __kindof SGFrame *frame = [[SGObjectPool sharedPool] objectWithClass:self->_frameClass reuseName:self->_frameReuseName]; if ([self->_frameReuseName isEqualToString:@"SGVideoFrame"]) { NSLog(@"----frameClass:%@ ,frameReuseName:%@",self->_frameClass,self->_frameReuseName); } result = avcodec_receive_frame(self->_codecContext, frame.core); NSLog(@"result:%d frameClass:%@",result,self->_frameClass); if (result < 0) { [frame unlock]; break; } else { [array addObject:frame]; } } return array; } -
通过打印数据 我进行了对比,正常播放的视频 while内部 SGVideoFrame 会打印很多,但是异常视频只会打印6次 之后便再也没有数据了,期初我一直以为的avcodec_receive_frame 这个地方有问题,但是 avcodec_receive_frame 这个方法已经是FFmpeg 内部的方法,那这样,出问题的地方,要么是avctx 要么是frame
基于上面的分析,我又看到解码开始时候 SGVideoFrame打印次数是比较多的 基本正常,但是 为什么 while 后面只打印六次 后面就没有数据了呢, 后面我又打印了 这个结果值,发现只有前6次是返回的0 (返回0 是发送正常) 后面都是 -1332244 异常 ,这个时候很明显 自己打印已经看不出问题所在了,于是我 查看了很多博客,有人说可以打开FFmpeg的日志 ,我简单搜了一下没有,后面无意间看到了这个代码 猜想可能是,于是打开后 ,果然打印了很多资料
```
NSString * message = [[NSString alloc] initWithFormat:[NSString stringWithUTF8String:format] arguments:args];
NSLog(@"SGFFLog : %@", message);
```
5. 其中异常源的log, 很明显 vt decoder cb: output 和hardware accelerator failed to decode picture 这是导致没有正常播放的主要原因
```
2021-12-29 10:14:46.086910+0800 PanoramicLive[320:7195] SGFFLog : vt decoder cb: output image buffer is null
2021-12-29 10:14:46.087355+0800 PanoramicLive[320:7242] SGFFLog : hardware accelerator failed to decode picture
2021-12-29 10:14:46.088060+0800 PanoramicLive[320:7243] SGFFLog : nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 1
2021-12-29 10:14:46.088721+0800 PanoramicLive[320:7243] SGFFLog : VideoToolbox decoder needs reconfig, restarting..
2021-12-29 10:14:46.155362+0800 PanoramicLive[320:7195] SGFFLog : vt decoder cb: output image buffer is null
2021-12-29 10:14:46.155803+0800 PanoramicLive[320:7243] SGFFLog : hardware accelerator failed to decode picture
2021-12-29 10:14:46.156408+0800 PanoramicLive[320:7244] SGFFLog : nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 1
2021-12-29 10:14:46.157045+0800 PanoramicLive[320:7244] SGFFLog : VideoToolbox decoder needs reconfig, restarting..
2021-12-29 10:14:46.225749+0800 PanoramicLive[320:7195] SGFFLog : vt decoder cb: output image buffer is null
2021-12-29 10:14:46.226230+0800 PanoramicLive[320:7244] SGFFLog : hardware accelerator failed to decode picture
2021-12-29 10:14:46.226830+0800 PanoramicLive[320:7245] SGFFLog : nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 1
2021-12-29 10:14:46.227452+0800 PanoramicLive[320:7245] SGFFLog : VideoToolbox decoder needs reconfig, restarting..
2021-12-29 10:14:46.292660+0800 PanoramicLive[320:7194] SGFFLog : vt decoder cb: output image buffer is null
```
6. 于是我又搜索了很多博客 一些关于 [Video Toolbox]
<https://www.cnblogs.com/isItOk/p/5964639.html>
有些说 VideoToolbox 不兼容的 <https://segmentfault.com/a/1190000038377679>
一些FFmpeg源码的 <https://blog.csdn.net/zhoubotong2012/article/details/79340722>
问题跟我的很类似的 视频在iOS部分机型黑屏原因分析 <https://www.codenong.com/cs105739757/>
很感谢上面的博主还有很多类似相关的文章,后面看到这,我一想 不行,现在因为视频流的数据我这边没法看到,能做对比的只有打印, 而打印的就是vt无法解析 也没有拿到解码的图片,所以第一要务是 拿到视频流的数据源 ,看看原始数据是怎么样的
7. 于是ffprobe 出厂FFmpeg命令行工具学习(一):查看媒体文件头信息工具ffprobe 我这
-
安装 ffprobe www.npmjs.com/package/ffp… $ npm install ffprobe
-
我主要使用了 查看视频的帧信息 的指令
#-show_frames:视频帧信息
**ffprobe -v quiet -print_format json -show_frames** 跟上rtmp:// 视频流链接
11. 基本可以确定是确定了 color range ,这个问题可以看到 无法 给到色彩框架的标准,其实我们手机视频解析的地方就不知道用哪个标准去解析的 color range 相关资料 blog.csdn.net/yue_huang/a…
色彩空间标准 <https://support.huaweicloud.com/usermanual-MindStudioC76_C30/atlasms_02_0340.html>