IOS硬解码流程笔记
IOS硬解码:
流程步骤:
1初始化:CMVideoFormatDescriptionCreateFromH264ParameterSets
注意SPS。PPS不要携带冗余,携带冗余可能导致无法某些手机无法正常解码
size_t ParameterSetSizes[2] = {(size_t)FrameInfo->nSpsLen, (size_t)FrameInfo->nPpsLen};
const uint8_t* const ParameterSetPointers[2] = {( uint8_t*)FrameInfo->pSpsStart, ( uint8_t*)FrameInfo->pPpsStart};
CMVideoFormatDescriptionCreateFromH264ParameterSets(NULL, 2, ParameterSetPointers, ParameterSetSizes, 4, &FormatDesc); |
size_t ParameterSetSizes[3] = {(size_t)FrameInfo->nVpsLen, (size_t)FrameInfo->nSpsLen, (size_t)FrameInfo->nPpsLen};
uint8_t* const nParameterSetPointers[3] = {(const uint8_t*)FrameInfo->pVpsStart, (const uint8_t*)FrameInfo->pSpsStart, (const uint8_t*)FrameInfo->pPpsStart};
#ifdef __IPHONE_11_0 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11.0) { nStatus = CMVideoFormatDescriptionCreateFromHEVCParameterSets(NULL, 3, ParameterSetPointers, ParameterSetSizes, 4, NULL, &FormatDesc); } #endif |
2 设置pixelbuffer属性
CFMutableDictionaryRef PixelBufferAttributes =
CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
3设置解码参数:这里设置的宽高可以让硬解码按照你设置的分辨率解码。
SInt32 nPixelType = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange; CFDictionarySetValue(PixelBufferAttributes, kCVPixelBufferPixelFormatTypeKey, CFNumberCreate(NULL, kCFNumberSInt32Type, &PixelType)); CFDictionarySetValue(PixelBufferAttributes, kCVPixelBufferWidthKey, CFNumberCreate(NULL, kCFNumberSInt32Type, &Width)); CFDictionarySetValue(PixelBufferAttributes, kCVPixelBufferHeightKey, CFNumberCreate(NULL, kCFNumberSInt32Type, &Height)); CFMutableDictionaryRef pDecoderParameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); |
4设置解码回调(异步的时候需要设置,同步的时候不需要设置)
const VTDecompressionOutputCallbackRecord stCallBack = {HWDecompressionOutputCallback, this}; nStatus = VTDecompressionSessionCreate(NULL, FormatDesc, NULL, PixelBufferAttributes, &stCallBack, &DecSession); |
5 初始化结束后进行属性的释放
CFRelease(PixelBufferAttributes); CFRelease(DecParameters); |
6 输入的解码数据转换成CMBlockBufferRef
CMBlockBufferCreateWithMemoryBlock(NULL, Data, Len, kCFAllocatorNull, NULL, 0, Len, 0, &BlockBufferRefobj); |
7 blockbuf转成CMSampleBufferRef
CMSampleBufferCreate(NULL, BlockBufferRefobj, true, 0, 0, FormatDesc, 1, 0, NULL, 0, NULL, &SampleBufferRef); |
8 硬解码;之后释放samplebufref 和 blockbufferref
VTDecompressionSessionDecodeFrame(DecSession, SampleBufferRef, 0, pDecodeInfo, 0); |
9 回调函数中拿YUV
CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly) YUV处理 CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库