VideoToolBox解码时,VTDecompressionSessionDecodeFrame
返回错误12902,kVTParameterErr = -12902
即参数错误,然后在VTDecompressionSessionInvalidate
的时候,就发现线程卡死挂起了
同样操作VTDecompressionSessionWaitForAsynchronousFrames
也是一样的,VTDecompressionSessionInvalidate
里面也操作了VTDecompressionSessionWaitForAsynchronousFrames
CMItemCount count = CMSampleBufferGetNumSamples(sampleBuffer);
if (count > 0) {
//解码
//向视频解码器提示使用低功耗模式是可以的
uint32_t decoder_flags = 0;
decoder_flags |= kVTDecodeFrame_EnableAsynchronousDecompression;
decoder_flags |= kVTDecodeFrame_1xRealTimePlayback;
//异步解码
VTDecodeInfoFlags flagOut = kVTDecodeInfo_Asynchronous;
NSDate* currentTime = [NSDate date];
status = VTDecompressionSessionDecodeFrame(_decompressionSession, sampleBuffer, decoder_flags,
(void*)CFBridgingRetain(currentTime), &flagOut);
if (status == kVTInvalidSessionErr) {
GSLog(@"Video hard decode InvalidSessionErr status = %d ,nalutype : %d", (int)status,nalu_type);
} else if (status == kVTVideoDecoderBadDataErr) {
GSLog(@"Video hard decode BadData status = %d ,nalutype : %d", (int)status,nalu_type);
} else if (status != noErr) {
GSLog(@"Video hard decode failed status = %d , nalutype : %d", (int)status,nalu_type);
}
CFBridgingRelease((__bridge CFTypeRef _Nullable)(currentTime));
}else {
GSLog(@"sampleBuffer items == 0");
}
然后释放的时候就卡死了
VTDecompressionSessionInvalidate(oldsession);
CFRelease(oldsession);
这里附上IJKPlayer
的写法
if (context->vt_session) {
VTDecompressionSessionWaitForAsynchronousFrames(context->vt_session);
VTDecompressionSessionInvalidate(context->vt_session);
CFRelease(context->vt_session);
context->vt_session = NULL;
}
这里防止卡死我把它放在另一个线程去做了
if (self->_decompressionSession) {
VTDecompressionSessionRef oldsession = self->_decompressionSession;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//为防止sesssion在invalidate卡死线程的casem,我们在另外一个线程去执行,就算卡死也不会影响我们的解码线程或者主线程
NSLog(@"Video Decompression Invalidate session BEGIN");
VTDecompressionSessionInvalidate(oldsession);
CFRelease(oldsession);
NSLog(@"Video Decompression Invalidate session DONE");
});
self->_decompressionSession = NULL;
}
这是相关的堆栈,拷贝的别人的
Apple could fix the bug of VTDecompressionSessionInvalidate API. Here is the stack:
0 libsystem_kernel.dylib 0x0000000184905150 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x0000000184a1ad40 _pthread_cond_wait$VARIANT$mp + 640
2 CoreMedia 0x0000000187ec44f8 WaitOnCondition + 16
3 CoreMedia 0x0000000187ec4440 FigSemaphoreWaitRelative + 168
4 ************ 0x000000018840b0d8 VTDecompressionSessionRemote_WaitForAsynchronousFrames + 120
5 ************ 0x000000018840aeb8 VTDecompressionSessionRemote_Invalidate + 88
6 ************ 0x00000001883b1e44 VTDecompressionSessionInvalidate + 52
7 XXXXX 0x0000000102a21094 -[hw264decoder releasedecoder] + 3641492 (XXXXXX.m:221)
追根溯源发现收到的naluType
类型为31
,31: Unspecified (non-VCL)
是不是还没用的类型吗,我也不知道怎么会收到这个,还是数据源错误,打包成CMSampleBuffer
给VideoToolBox
也就出问题了,在接收到nalutype
的时候,过滤掉了31
类型,解决了这个bug,如果你也有遇到这种问题,看看是不是nalutype的问题吧,或者数据源不对。
发现使用AVSampleBufferDisplayerlayer
的时候,也有同样的现象
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
// Error codes
#if COREMEDIA_USE_DERIVED_ENUMS_FOR_CONSTANTS
enum : OSStatus
#else
enum
#endif // COREMEDIA_USE_DERIVED_ENUMS_FOR_CONSTANTS
{
kVTPropertyNotSupportedErr = -12900,
kVTPropertyReadOnlyErr = -12901,
kVTParameterErr = -12902,
kVTInvalidSessionErr = -12903,
kVTAllocationFailedErr = -12904,
kVTPixelTransferNotSupportedErr = -12905, // c.f. -8961
kVTCouldNotFindVideoDecoderErr = -12906,
kVTCouldNotCreateInstanceErr = -12907,
kVTCouldNotFindVideoEncoderErr = -12908,
kVTVideoDecoderBadDataErr = -12909, // c.f. -8969
kVTVideoDecoderUnsupportedDataFormatErr = -12910, // c.f. -8970
kVTVideoDecoderMalfunctionErr = -12911, // c.f. -8960
kVTVideoEncoderMalfunctionErr = -12912,
kVTVideoDecoderNotAvailableNowErr = -12913,
kVTImageRotationNotSupportedErr = -12914,
kVTVideoEncoderNotAvailableNowErr = -12915,
kVTFormatDescriptionChangeNotSupportedErr = -12916,
kVTInsufficientSourceColorDataErr = -12917,
kVTCouldNotCreateColorCorrectionDataErr = -12918,
kVTColorSyncTransformConvertFailedErr = -12919,
kVTVideoDecoderAuthorizationErr = -12210,
kVTVideoEncoderAuthorizationErr = -12211,
kVTColorCorrectionPixelTransferFailedErr = -12212,
kVTMultiPassStorageIdentifierMismatchErr = -12213,
kVTMultiPassStorageInvalidErr = -12214,
kVTFrameSiloInvalidTimeStampErr = -12215,
kVTFrameSiloInvalidTimeRangeErr = -12216,
kVTCouldNotFindTemporalFilterErr = -12217,
kVTPixelTransferNotPermittedErr = -12218,
kVTColorCorrectionImageRotationFailedErr = -12219,
kVTVideoDecoderRemovedErr = -17690,
};
相关文章:
CMItemCount count = CMSampleBufferGetNumSamples(sampleBuffer);
的代码学习不断,有错误请指出,如果对你有帮助,请点个赞