一.问题描述
1.现象
a.多段视频组合,有转场变速等操作,预览(黑屏)或导出失败.
b.AVPlayerItem收到AVPlayerItemStatusFailed的KVO
c.app收到AVAudioSessionMediaServicesWereResetNotification通知
d.不同设备表现也不相同有的预览失败有的导出失败
e.iOS8的touch复现率极高
2.视频合并预览或导出过程失败 日志
Incident Identifier: 3423F244-30C8-4BF6-8B17-973A484A56D9
CrashReporter Key: df68ba962d120b617cde7167c3ce094db3dcaa19
Hardware Model: iPhone10,1
Process: mediaserverd [26]
Path: /usr/sbin/mediaserverd
Identifier: mediaserverd
Version: ???
Code Type: ARM-64 (Native)
Role: Unspecified
Parent Process: launchd [1]
Coalition: com.apple.mediaserverd [15]
Date/Time: 2019-06-10 18:23:34.8714 +0800
Launch Time: 2019-06-03 09:52:03.1229 +0800
OS Version: iPhone OS 12.3.1 (16F203)
Baseband Version: 3.60.01
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000011d6d4000
VM Region Info: 0x11d6d4000 is not in any region. Bytes after previous region: 1474561 Bytes before following region: 25378816
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
MALLOC_LARGE 000000011d544000-000000011d56c000 [ 160K] rw-/rwx SM=PRV
---> GAP OF 0x199c000 BYTES
MALLOC_LARGE 000000011ef08000-000000011f008000 [ 1024K] rw-/rwx SM=PRV
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [26]
Triggered by Thread: 15
.
.
.
.
Thread 15 name: Dispatch queue: com.apple.coremedia.basicvideocompositor.layerprocessing
Thread 15 Crashed:
0 MediaToolbox 0x0000000201e2e3c8 bvc_SimpleMixingOpaque_420v_420v_420v_arm + 312
1 MediaToolbox 0x0000000201cfe9fc __bvc_mixBuffers_block_invoke + 732
2 libdispatch.dylib 0x00000001fcc95814 _dispatch_client_callout2 + 16
3 libdispatch.dylib 0x00000001fcc7aeb4 _dispatch_apply_serial + 116
4 libdispatch.dylib 0x00000001fcc957d4 _dispatch_client_callout + 16
5 libdispatch.dylib 0x00000001fcc76bf4 _dispatch_sync_invoke_and_complete + 56
6 libdispatch.dylib 0x00000001fcc7ad98 dispatch_apply_f$VARIANT$armv81 + 852
7 MediaToolbox 0x0000000201cfcd58 bvc_mixBuffers + 1296
8 MediaToolbox 0x0000000201cfc318 __basicVideoCompositor_RenderFrame_block_invoke_4 + 2300
9 libdispatch.dylib 0x00000001fcc94a38 _dispatch_call_block_and_release + 24
10 libdispatch.dylib 0x00000001fcc957d4 _dispatch_client_callout + 16
11 libdispatch.dylib 0x00000001fcc70dec _dispatch_lane_serial_drain$VARIANT$armv81 + 548
12 libdispatch.dylib 0x00000001fcc7192c _dispatch_lane_invoke$VARIANT$armv81 + 408
13 libdispatch.dylib 0x00000001fcc79e08 _dispatch_workloop_worker_thread + 584
14 libsystem_pthread.dylib 0x00000001fce75114 _pthread_wqthread + 304
15 libsystem_pthread.dylib 0x00000001fce77cd4 start_wqthread + 4
3.复现过程
必现步骤1
a.多段视频编辑,选择4端视频 ABCD顺序
b.A 变速为极快 B变速为快 C变速为极快 D变速为极快
c.全部选择上下转场方式
以上任意条件不满足,都不能复现,iPhoneXR导出失败 iPhone8预览失败
其他出现的情况,没有必现的步骤
必现步骤2
a.多段视频编辑,选择4端视频 ABCD顺序
b.A 变速为极快 其他不变速,全部选择上下转场方式
c.预览一遍整体视频,之后导出视频
进一步缩小条件范围
a.多段视频编辑,选择2段视频 AB
b.A(宽) 变速为极快后2s 其他不变速,全部选择上下转场方式
c.导出视频失败 iPhoneXR iPhone8都是预览没问题,导出失败
a.两段 A(宽)视频4s的视频 变为快速后为2S
b.上下转场方式
c.导出失败
二.问题定位过程 (已知必现必现步骤的情况)
1.发现transform中的a与d出现 -1.2246467991473537e-16值,怀疑是tranform错误引起的
a.用这些值配置Transform,处理独立的layer,没有MediaToolbox crash问题,只是内容无法正常展示
2.transform过程导出失败
a.只把上下转场工程的视频片段导出到本地,未发生异常MediaToolbox crash?
3.单个视频正常播放过程导出
a.只把变速后的视频片段导出,未发生异常MediaToolbox crash?
三.确认是AVFoundation
3.苹果技术人员没有明确的避免这个crash的方法
四.自己查找避免办法
1.通过不断的注释掉相关代码尝试最终确认为 toStartLayerTransform引起的
2.垂直转场中 startToLayerTranshform 与 startFromLayerTransfrom特殊值引起
3.在垂直转场过程中加上avoidMediaCrashOffset之后未复现过
4.强制上下转场过程不是从视频最底部开始,而是有一定的偏移量,人眼无感知.但代码很奇怪...
+ (CGAffineTransform)getTransformWithDegree:(NSUInteger)rotationAngle
origTransform:(CGAffineTransform)origTransform
transType:(AHSVVideoTransformType)transType
targetVideoSize:(CGSize)targetVideoSize
isFrom:(BOOL)isFromOrTo {
CGFloat videoWidth = targetVideoSize.width;
CGFloat videoHeight = targetVideoSize.height;
CGAffineTransform transform = CGAffineTransformIdentity;
rotationAngle = rotationAngle % 360;
//为避免mediaserverd crash 添加的位移偏移量
NSUInteger avoidMediaCrashOffset = 5.0;
if (transType == AHSVVideoTransformTypeHor) {
if (isFromOrTo) { //from的 动画结束transform
//注意:由于origTransform包含缩放 要缩放后位移 否则缩放会缩放位移距离
transform = CGAffineTransformConcat(origTransform, CGAffineTransformMakeTranslation(-videoWidth + avoidMediaCrashOffset, 0));
} else { //to的 开始动画transform
transform = CGAffineTransformConcat(origTransform, CGAffineTransformMakeTranslation(videoWidth - avoidMediaCrashOffset, 0));
}
} else if (transType == AHSVVideoTransformTypeVer) {
if (isFromOrTo) { //from的 动画结束transform
//注意:由于origTransform包含缩放 要缩放后位移 否则缩放会缩放位移距离
transform = CGAffineTransformConcat(origTransform, CGAffineTransformMakeTranslation(0, -videoHeight + avoidMediaCrashOffset));
} else { //to的 开始动画transform
transform = CGAffineTransformConcat(origTransform, CGAffineTransformMakeTranslation(0, videoHeight - avoidMediaCrashOffset));
}
}
return transform;
}