1、使用videoToolBox解码空间视频
第一步: 创建解码会话
1、创建解码器方法介绍
VTDecompressionSessionCreate (
CFAllocatorRef allocator,
CMVideoFormatDescriptionRef videoFormatDescription,
CFDictionaryRef videoDecoderSpecification,
CFDictionaryRef destinationImageBufferAttributes,
const VTDecompressionOutputCallbackRecord * CM_NULLABLE outputCallback,
VTDecompressionSessionRef * CM_NONNULL decompressionSessionOut) API_AVAILABLE ( macosx ( 10.8 ) , ios ( 8.0 ) , tvos ( 10.2 ) ) ;
allocator(分配器): - 类型:CM_NULLABLE CFAllocatorRef - 描述:指定用于分配解压缩会话及其相关数据结构的内存分配器。可以传入 NULL,表示使用默认的内存分配器。
videoFormatDescription(视频格式描述): - 类型:CM_NONNULL CMVideoFormatDescriptionRef - 描述:包含有关视频数据格式的信息的CoreMedia对象,通常由视频流的元数据提供。此参数用于描述待解压缩的视频数据的格式。
videoDecoderSpecification(视频解码器规格): - 类型:CM_NULLABLE CFDictionaryRef - 描述:可选参数,允许您指定用于解码视频的特定解码器。传入 NULL 表示使用默认的解码器。
destinationImageBufferAttributes(目标图像缓冲区属性): - 类型:CM_NULLABLE CFDictionaryRef - 描述:可选参数,允许您指定输出图像缓冲区的属性。例如,可以指定图像的像素格式等信息。
outputCallback(输出回调): - 类型:const VTDecompressionOutputCallbackRecord * CM_NULLABLE - 描述:可选参数,如果不为 NULL,则在解压缩每帧后调用此回调函数以处理输出。可以为 NULL,表示不需要输出回调。
decompressionSessionOut(解压缩会话输出): - 类型:CM_RETURNS_RETAINED_PARAMETER CM_NULLABLE VTDecompressionSessionRef * CM_NONNULL - 描述:指向将由此函数创建的解压缩会话的指针的指针。如果函数成功,则此指针将包含对新创建的解压缩会话的引用。需要调用者负责释放这个引用。
2、创建解码器需要的参数-CMFormatDescriptionRef
- ( CMFormatDescriptionRef) getVideoFormatDescriptionFromURL: ( NSURL * ) videoURL {
AVURLAsset * videoAsset = [ AVURLAsset assetWithURL: videoURL] ;
AVAssetTrack * videoTrack = [ [ videoAsset tracksWithMediaType: AVMediaTypeVideo] firstObject] ;
if ( ! videoTrack) {
NSLog ( @"Video track not found in the asset." ) ;
return NULL ;
}
CMFormatDescriptionRef formatDescription = ( __bridge CMFormatDescriptionRef) videoTrack. formatDescriptions. firstObject;
if ( ! formatDescription) {
NSLog ( @"Format description not found for the video track." ) ;
return NULL ;
}
return formatDescription;
}
3、创建解码器需要的参数-CFDictionaryRef
- ( NSDictionary * ) createDecoderSpecification {
NSDictionary * decoderSpecification = @ {
( __bridge NSString * ) kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder : @ YES,
( __bridge NSString * ) kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder : @ YES,
} ;
return decoderSpecification;
}
4、创建解码器
- ( VTDecompressionSessionRef) createDecompressionSessionWithFormatDescription: ( CMFormatDescriptionRef) videoFormatDescription {
if ( ! videoFormatDescription) {
NSLog ( @"Invalid video format description." ) ;
return NULL ;
}
NSDictionary * decoderSpecification = [ self createDecoderSpecification] ;
VTDecompressionSessionRef decompressionSession;
OSStatus status = VTDecompressionSessionCreate ( NULL ,
videoFormatDescription,
( __bridge CFDictionaryRef) decoderSpecification,
NULL ,
NULL ,
& decompressionSession) ;
NSLog ( @"status: %d" , status) ;
if ( status != noErr) {
NSLog ( @"Failed to create decompression session" ) ;
return NULL ;
}
return decompressionSession;
}
第二步:设置解码器属性
NSArray * requestedLayerIDs = @ [ @ 0 , @ 1 ] ;
OSStatus status = VTSessionSetProperty ( sessionRef, kVTDecompressionPropertyKey_RequestedMVHEVCVideoLayerIDs, ( __bridge CFArrayRef) requestedLayerIDs) ;
if ( status != noErr) {
NSLog ( @"设置 kVTDecompressionPropertyKey_RequestedMVHEVCVideoLayerIDs 属性失败,错误代码:%d" , ( int ) status) ;
} else {
NSLog ( @"成功设置 kVTDecompressionPropertyKey_RequestedMVHEVCVideoLayerIDs 属性" ) ;
}
第三步:解析视频
- ( void ) processVideoWithURLV2: ( NSURL * ) url {
AVAsset * asset = [ AVAsset assetWithURL: url] ;
NSError * error = nil;
AVAssetReader * assetReader = [ [ AVAssetReader alloc] initWithAsset: asset error: & error] ;
if ( error) {
NSLog ( @"Error creating asset reader: %@" , [ error localizedDescription] ) ;
return ;
}
AVAssetTrack * videoTrack = [ [ asset tracksWithMediaType: AVMediaTypeVideo] firstObject] ;
AVAssetReaderTrackOutput * output = [ [ AVAssetReaderTrackOutput alloc] initWithTrack: videoTrack outputSettings: nil] ;
[ assetReader addOutput: output] ;
[ assetReader startRea