BFVideoDecoder.mm 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. //
  2. // BFVideoDecoder.m
  3. // BFFFmpeglib_Example
  4. //
  5. // Created by ak on 2022/1/5.
  6. // Copyright © 2022 287971051@qq.com. All rights reserved.
  7. //
  8. #import "BFVideoDecoder.h"
  9. #import <VideoToolbox/VideoToolbox.h>
  10. #import <pthread.h>
  11. #include "BFMediaLog.h"
  12. typedef struct {
  13. CVPixelBufferRef outputPixelbuffer;
  14. int rotate;
  15. Float64 pts;
  16. int fps;
  17. int source_index;
  18. } BFDecodeVideoInfo;
  19. typedef struct {
  20. uint8_t *vps;
  21. uint8_t *sps;
  22. // H265有前后两个pps
  23. uint8_t *f_pps;
  24. uint8_t *r_pps;
  25. int vps_size;
  26. int sps_size;
  27. int f_pps_size;
  28. int r_pps_size;
  29. Float64 last_decode_pts;
  30. } BFDecoderInfo;
  31. @interface BFVideoDecoder ()
  32. {
  33. VTDecompressionSessionRef _decoderSession;
  34. CMVideoFormatDescriptionRef _decoderFormatDescription;
  35. BFDecoderInfo _decoderInfo;
  36. pthread_mutex_t _decoder_lock;
  37. uint8_t *_lastExtraData;
  38. int _lastExtraDataSize;
  39. BOOL _isFirstFrame;
  40. }
  41. @end
  42. @implementation BFVideoDecoder
  43. #pragma mark - 解码后回调
  44. /// @param decompressionOutputRefCon 回调引用
  45. /// @param sourceFrameRefCon 帧引用
  46. /// @param status 状态标识
  47. /// @param infoFlags 同步还是异步解码
  48. /// @param pixelBuffer 实际的图像缓存
  49. /// @param presentationTimeStamp 图像出现的时间戳
  50. /// @param presentationDuration 图像的持续时间
  51. static void VideoDecoderCallback(void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef pixelBuffer, CMTime presentationTimeStamp, CMTime presentationDuration) {
  52. BFDecodeVideoInfo *sourceRef = (BFDecodeVideoInfo *)sourceFrameRefCon;
  53. NSLog(@"2827解码pts=%f 完成时间为: %f",sourceRef->pts,[[NSDate date] timeIntervalSince1970]);
  54. if (pixelBuffer == NULL || status != noErr) {
  55. NSLog(@" pixelbuffer is NULL status = %d",status);
  56. if (sourceRef) {
  57. free(sourceRef);
  58. }
  59. return;
  60. }
  61. //取到 OC 本类对象
  62. BFVideoDecoder *decoder = (__bridge BFVideoDecoder *)decompressionOutputRefCon;
  63. CMSampleTimingInfo sampleTime = {
  64. .presentationTimeStamp = presentationTimeStamp,
  65. .decodeTimeStamp = presentationTimeStamp
  66. };
  67. //pixelbuffer to samplerbuffer
  68. CMSampleBufferRef samplebuffer = [decoder createSampleBufferFromPixelbuffer:pixelBuffer
  69. videoRotate:sourceRef->rotate
  70. timingInfo:sampleTime];
  71. if (samplebuffer) {
  72. if ([decoder.delegate respondsToSelector:@selector(getVideoDecodeDataCallback:isFirstFrame:)]) {
  73. [decoder.delegate getVideoDecodeDataCallback:samplebuffer isFirstFrame:decoder->_isFirstFrame];
  74. if (decoder->_isFirstFrame) {
  75. decoder->_isFirstFrame = NO;
  76. }
  77. }
  78. CFRelease(samplebuffer);
  79. }
  80. if (sourceRef) {
  81. free(sourceRef);
  82. }
  83. }
  84. #pragma mark - life cycle
  85. - (instancetype)init {
  86. if (self = [super init]) {
  87. _decoderInfo = {
  88. .vps = NULL, .sps = NULL, .f_pps = NULL, .r_pps = NULL,
  89. .vps_size = 0, .sps_size = 0, .f_pps_size = 0, .r_pps_size = 0, .last_decode_pts = 0,
  90. };
  91. _isFirstFrame = YES;
  92. pthread_mutex_init(&_decoder_lock, NULL);
  93. }
  94. return self;
  95. }
  96. - (void)dealloc {
  97. _delegate = nil;
  98. [self destoryDecoder];
  99. }
  100. #pragma mark - Public
  101. - (void)startDecodeVideoData:(BFParseVideoDataInfo *)videoInfo {
  102. // get extra data
  103. if (videoInfo->extraData && videoInfo->extraDataSize) {
  104. uint8_t *extraData = videoInfo->extraData;
  105. int size = videoInfo->extraDataSize;
  106. BOOL isNeedUpdate = [self isNeedUpdateExtraDataWithNewExtraData:extraData
  107. newSize:size
  108. lastData:&_lastExtraData
  109. lastSize:&_lastExtraDataSize];
  110. if (isNeedUpdate) {
  111. NSLog(@" update extra data");
  112. [self getNALUInfoWithVideoFormat:videoInfo->videoFormat
  113. extraData:extraData
  114. extraDataSize:size
  115. decoderInfo:&_decoderInfo];
  116. }
  117. }
  118. // 创建解码器
  119. if (!_decoderSession) {
  120. _decoderSession = [self createDecoderWithVideoInfo:videoInfo
  121. videoDescRef:&_decoderFormatDescription
  122. videoFormat:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
  123. lock:_decoder_lock
  124. callback:VideoDecoderCallback
  125. decoderInfo:_decoderInfo];
  126. }
  127. pthread_mutex_lock(&_decoder_lock);
  128. if (!_decoderSession) {
  129. pthread_mutex_unlock(&_decoder_lock);
  130. return;
  131. }
  132. /* If open B frame, the code will not be used.
  133. if(_decoderInfo.last_decode_pts != 0 && videoInfo->pts <= _decoderInfo.last_decode_pts){
  134. log4cplus_error(kModuleName, "decode timestamp error ! current:%f, last:%f",videoInfo->pts, _decoderInfo.last_decode_pts);
  135. pthread_mutex_unlock(&_decoder_lock);
  136. return;
  137. }
  138. */
  139. _decoderInfo.last_decode_pts = videoInfo->pts;
  140. pthread_mutex_unlock(&_decoder_lock);
  141. // start decode
  142. [self startDecode:videoInfo
  143. session:_decoderSession
  144. lock:_decoder_lock];
  145. }
  146. - (void)stopDecoder {
  147. [self destoryDecoder];
  148. }
  149. #pragma mark - private methods
  150. #pragma mark Create / Destory decoder
  151. - (VTDecompressionSessionRef)createDecoderWithVideoInfo:(BFParseVideoDataInfo *)videoInfo videoDescRef:(CMVideoFormatDescriptionRef *)videoDescRef videoFormat:(OSType)videoFormat lock:(pthread_mutex_t)lock callback:(VTDecompressionOutputCallback)callback decoderInfo:(BFDecoderInfo)decoderInfo {
  152. pthread_mutex_lock(&lock);
  153. // 1.根据 sps,pps 设置解码参数 区分264 265
  154. OSStatus status;
  155. // H264 格式
  156. if (videoInfo->videoFormat == BFH264EncodeFormat) {
  157. // 存放 sps 和 pps 信息的数组
  158. const uint8_t *const parameterSetPointers[2] = {decoderInfo.sps, decoderInfo.f_pps};
  159. const size_t parameterSetSizes[2] = {static_cast<size_t>(decoderInfo.sps_size), static_cast<size_t>(decoderInfo.f_pps_size)};
  160. /*
  161. 参数 1: allocator 内存分配器, 使用默认的 KCFAllocatorDefault
  162. 参数 2: parameterSetCount 解码参数的个数 2 (分别为 sps, pps)
  163. 参数 3: parameterSetPointers 参数集的地址
  164. 参数 4: parameterSetSizes 参数集的大小
  165. 参数 5: NALUnitHeaderLength 流数据起始位的长度 大端模式的起始位的长度固定为 4
  166. 参数 6: formatDescriptionOut 解码器的描述
  167. */
  168. status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
  169. 2,
  170. parameterSetPointers,
  171. parameterSetSizes,
  172. 4,
  173. videoDescRef);
  174. // H265 格式
  175. }else if (videoInfo->videoFormat == BFH265EncodeFormat) {
  176. //有 PPS
  177. if (decoderInfo.r_pps_size == 0) {
  178. const uint8_t *const parameterSetPointers[3] = {decoderInfo.vps, decoderInfo.sps, decoderInfo.f_pps};
  179. const size_t parameterSetSizes[3] = {static_cast<size_t>(decoderInfo.vps_size), static_cast<size_t>(decoderInfo.sps_size), static_cast<size_t>(decoderInfo.f_pps_size)};
  180. if (@available(iOS 11.0, *)) {
  181. status = CMVideoFormatDescriptionCreateFromHEVCParameterSets(kCFAllocatorDefault,
  182. 3,
  183. parameterSetPointers,
  184. parameterSetSizes,
  185. 4,
  186. NULL,
  187. videoDescRef);
  188. } else {
  189. status = -1;
  190. NSLog(@" System version is too low!");
  191. }
  192. } else {
  193. const uint8_t *const parameterSetPointers[4] = {decoderInfo.vps, decoderInfo.sps, decoderInfo.f_pps, decoderInfo.r_pps};
  194. const size_t parameterSetSizes[4] = {static_cast<size_t>(decoderInfo.vps_size), static_cast<size_t>(decoderInfo.sps_size), static_cast<size_t>(decoderInfo.f_pps_size), static_cast<size_t>(decoderInfo.r_pps_size)};
  195. if (@available(iOS 11.0, *)) {
  196. status = CMVideoFormatDescriptionCreateFromHEVCParameterSets(kCFAllocatorDefault,
  197. 4,
  198. parameterSetPointers,
  199. parameterSetSizes,
  200. 4,
  201. NULL,
  202. videoDescRef);
  203. } else {
  204. status = -1;
  205. NSLog(@" System version is too low!");
  206. }
  207. }
  208. }else {
  209. status = -1;
  210. }
  211. if (status != noErr) {
  212. NSLog(@" NALU header error !");
  213. pthread_mutex_unlock(&lock);
  214. [self destoryDecoder];
  215. return NULL;
  216. }
  217. // 2.解码参数
  218. uint32_t pixelFormatType = videoFormat;
  219. const void *keys[] = {kCVPixelBufferPixelFormatTypeKey};
  220. const void *values[] = {CFNumberCreate(NULL, kCFNumberSInt32Type, &pixelFormatType)};
  221. CFDictionaryRef attrs = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
  222. //解码完成后的回调
  223. VTDecompressionOutputCallbackRecord callBackRecord;
  224. callBackRecord.decompressionOutputCallback = callback;
  225. callBackRecord.decompressionOutputRefCon = (__bridge void *)self;
  226. //3,创建 session
  227. VTDecompressionSessionRef session;
  228. /*
  229. 参数 1: allocator 内存分配器, 使用默认的 kCFAllocatorDefault
  230. 参数 2: videoFormatDescription 描述源视频帧的视频格式 _decodeDesc
  231. 参数 3: videoDecoderSpecification 是否需要特定的视频解码器, 不需要给 NULL 即可
  232. 参数 4: destinationImageBufferAttributes 描述源像素的缓存区,如果没特殊要求给 NULL 即可, 有的话就把设置的字典信息填进去
  233. 参数 5: outputCallback 已经解码完成的回调函数
  234. 参数 6: decompressionSessionOut 解压 session
  235. */
  236. status = VTDecompressionSessionCreate(kCFAllocatorDefault,
  237. *videoDescRef,
  238. NULL,
  239. attrs,
  240. &callBackRecord,
  241. &session);
  242. CFRelease(attrs);
  243. pthread_mutex_unlock(&lock);
  244. if (status != noErr) {
  245. NSLog(@" Create decoder failed");
  246. [self destoryDecoder];
  247. return NULL;
  248. }
  249. // 4. 设置解码器是实时解码,
  250. // status = VTSessionSetProperty(_decodeSession, kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue);
  251. // if (status != noErr) {
  252. // NSLog(@"initDecoder VTSessionSetProperty() failed! ");
  253. // }
  254. NSLog(@"video decoder init success!");
  255. return session;
  256. }
  257. - (void)destoryDecoder {
  258. pthread_mutex_lock(&_decoder_lock);
  259. if (_decoderInfo.vps) {
  260. free(_decoderInfo.vps);
  261. _decoderInfo.vps_size = 0;
  262. _decoderInfo.vps = NULL;
  263. }
  264. if (_decoderInfo.sps) {
  265. free(_decoderInfo.sps);
  266. _decoderInfo.sps_size = 0;
  267. _decoderInfo.sps = NULL;
  268. }
  269. if (_decoderInfo.f_pps) {
  270. free(_decoderInfo.f_pps);
  271. _decoderInfo.f_pps_size = 0;
  272. _decoderInfo.f_pps = NULL;
  273. }
  274. if (_decoderInfo.r_pps) {
  275. free(_decoderInfo.r_pps);
  276. _decoderInfo.r_pps_size = 0;
  277. _decoderInfo.r_pps = NULL;
  278. }
  279. if (_lastExtraData) {
  280. free(_lastExtraData);
  281. _lastExtraDataSize = 0;
  282. _lastExtraData = NULL;
  283. }
  284. if (_decoderSession) {
  285. //等待异步解码完成
  286. VTDecompressionSessionWaitForAsynchronousFrames(_decoderSession);
  287. // 设置会话无效s
  288. VTDecompressionSessionInvalidate(_decoderSession);
  289. CFRelease(_decoderSession);
  290. _decoderSession = NULL;
  291. }
  292. // 清空解码的视频格式描述信息
  293. if (_decoderFormatDescription) {
  294. CFRelease(_decoderFormatDescription);
  295. _decoderFormatDescription = NULL;
  296. }
  297. pthread_mutex_unlock(&_decoder_lock);
  298. }
  299. - (BOOL)isNeedUpdateExtraDataWithNewExtraData:(uint8_t *)newData newSize:(int)newSize lastData:(uint8_t **)lastData lastSize:(int *)lastSize {
  300. BOOL isNeedUpdate = NO;
  301. if (*lastSize == 0) {
  302. isNeedUpdate = YES;
  303. }else {
  304. if (*lastSize != newSize) {
  305. isNeedUpdate = YES;
  306. }else {
  307. if (memcmp(newData, *lastData, newSize) != 0) {
  308. isNeedUpdate = YES;
  309. }
  310. }
  311. }
  312. if (isNeedUpdate) {
  313. [self destoryDecoder];
  314. *lastData = (uint8_t *)malloc(newSize);
  315. memcpy(*lastData, newData, newSize);
  316. *lastSize = newSize;
  317. }
  318. return isNeedUpdate;
  319. }
  320. #pragma mark Parse NALU Header
  321. - (void)copyDataWithOriginDataRef:(uint8_t **)originDataRef newData:(uint8_t *)newData size:(int)size {
  322. if (*originDataRef) {
  323. free(*originDataRef);
  324. *originDataRef = NULL;
  325. }
  326. *originDataRef = (uint8_t *)malloc(size);
  327. memcpy(*originDataRef, newData, size);
  328. }
  329. - (void)getNALUInfoWithVideoFormat:(BFVideoEncodeFormat)videoFormat extraData:(uint8_t *)extraData extraDataSize:(int)extraDataSize decoderInfo:(BFDecoderInfo *)decoderInfo {
  330. uint8_t *data = extraData;
  331. int size = extraDataSize;
  332. int startCodeVPSIndex = 0;
  333. int startCodeSPSIndex = 0;
  334. int startCodeFPPSIndex = 0;
  335. int startCodeRPPSIndex = 0;
  336. int nalu_type = 0;
  337. for (int i = 0; i < size; i ++) {
  338. if (i >= 3) {
  339. if (data[i] == 0x01 && data[i - 1] == 0x00 && data[i - 2] == 0x00 && data[i - 3] == 0x00) {
  340. if (videoFormat == BFH264EncodeFormat) {
  341. if (startCodeSPSIndex == 0) {
  342. startCodeSPSIndex = i;
  343. }
  344. if (i > startCodeSPSIndex) {
  345. startCodeFPPSIndex = i;
  346. }
  347. }else if (videoFormat == BFH265EncodeFormat) {
  348. if (startCodeVPSIndex == 0) {
  349. startCodeVPSIndex = i;
  350. continue;
  351. }
  352. if (i > startCodeVPSIndex && startCodeSPSIndex == 0) {
  353. startCodeSPSIndex = i;
  354. continue;
  355. }
  356. if (i > startCodeSPSIndex && startCodeFPPSIndex == 0) {
  357. startCodeFPPSIndex = i;
  358. continue;
  359. }
  360. if (i > startCodeFPPSIndex && startCodeRPPSIndex == 0) {
  361. startCodeRPPSIndex = i;
  362. }
  363. }
  364. }
  365. }
  366. }
  367. int spsSize = startCodeFPPSIndex - startCodeSPSIndex - 4;
  368. decoderInfo->sps_size = spsSize;
  369. if (videoFormat == BFH264EncodeFormat) {
  370. int f_ppsSize = size - (startCodeFPPSIndex + 1);
  371. decoderInfo->f_pps_size = f_ppsSize;
  372. nalu_type = ((uint8_t)data[startCodeSPSIndex + 1] & 0x1F);
  373. if (nalu_type == 0x07) {
  374. uint8_t *sps = &data[startCodeSPSIndex + 1];
  375. [self copyDataWithOriginDataRef:&decoderInfo->sps newData:sps size:spsSize];
  376. }
  377. nalu_type = ((uint8_t)data[startCodeFPPSIndex + 1] & 0x1F);
  378. if (nalu_type == 0x08) {
  379. uint8_t *pps = &data[startCodeFPPSIndex + 1];
  380. [self copyDataWithOriginDataRef:&decoderInfo->f_pps newData:pps size:f_ppsSize];
  381. }
  382. } else {
  383. int vpsSize = startCodeSPSIndex - startCodeVPSIndex - 4;
  384. decoderInfo->vps_size = vpsSize;
  385. int f_ppsSize = startCodeRPPSIndex - startCodeFPPSIndex - 4;
  386. decoderInfo->f_pps_size = f_ppsSize;
  387. nalu_type = ((uint8_t) data[startCodeVPSIndex + 1] & 0x4F);
  388. if (nalu_type == 0x40) {
  389. uint8_t *vps = &data[startCodeVPSIndex + 1];
  390. [self copyDataWithOriginDataRef:&decoderInfo->vps newData:vps size:vpsSize];
  391. }
  392. nalu_type = ((uint8_t) data[startCodeSPSIndex + 1] & 0x4F);
  393. if (nalu_type == 0x42) {
  394. uint8_t *sps = &data[startCodeSPSIndex + 1];
  395. [self copyDataWithOriginDataRef:&decoderInfo->sps newData:sps size:spsSize];
  396. }
  397. nalu_type = ((uint8_t) data[startCodeFPPSIndex + 1] & 0x4F);
  398. if (nalu_type == 0x44) {
  399. uint8_t *pps = &data[startCodeFPPSIndex + 1];
  400. [self copyDataWithOriginDataRef:&decoderInfo->f_pps newData:pps size:f_ppsSize];
  401. }
  402. if (startCodeRPPSIndex == 0) {
  403. return;
  404. }
  405. int r_ppsSize = size - (startCodeRPPSIndex + 1);
  406. decoderInfo->r_pps_size = r_ppsSize;
  407. nalu_type = ((uint8_t) data[startCodeRPPSIndex + 1] & 0x4F);
  408. if (nalu_type == 0x44) {
  409. uint8_t *pps = &data[startCodeRPPSIndex + 1];
  410. [self copyDataWithOriginDataRef:&decoderInfo->r_pps newData:pps size:r_ppsSize];
  411. }
  412. }
  413. }
  414. #pragma mark 开始解码
  415. - (void)startDecode:(BFParseVideoDataInfo *)videoInfo session:(VTDecompressionSessionRef)session lock:(pthread_mutex_t)lock {
  416. pthread_mutex_lock(&lock);
  417. uint8_t *data = videoInfo->data;
  418. int size = videoInfo->dataSize;
  419. int rotate = videoInfo->videoRotate;
  420. CMSampleTimingInfo timingInfo = videoInfo->timingInfo;
  421. uint8_t *tempData = (uint8_t *)malloc(size);
  422. memcpy(tempData, data, size);
  423. BFDecodeVideoInfo *sourceRef = (BFDecodeVideoInfo *)malloc(sizeof(BFParseVideoDataInfo));
  424. sourceRef->outputPixelbuffer = NULL;
  425. sourceRef->rotate = rotate;
  426. sourceRef->pts = videoInfo->pts;
  427. sourceRef->fps = videoInfo->fps;
  428. NSLog(@"2827开始解码pts=%f 时间为: %f", videoInfo->pts,[[NSDate date] timeIntervalSince1970]);
  429. //111.MP4
  430. // 1.创建 blockBuffer
  431. /*
  432. 参数 1: structureAllocator 内存分配器
  433. 参数 2: memoryBlock 内容,也就是帧,frame
  434. 参数 3: blockLength 内容的长度
  435. 参数 4: blockAllocator 内存分配器. 给 NULL/kCFAllocatorNull 即可
  436. 参数 5: customBlockSource NULL
  437. 参数 6: offsetToData 数据偏移量, 没有的话就给 0, 从头开始读取
  438. 参数 7: dataLength 数据长度
  439. 参数 8: flags 给 0 即可
  440. 参数 9: blockBufferOut blockBuffer 的地址
  441. */
  442. CMBlockBufferRef blockBuffer;
  443. OSStatus status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
  444. (void *)tempData,
  445. size, kCFAllocatorNull,
  446. NULL,
  447. 0,
  448. size,
  449. 0,
  450. &blockBuffer);
  451. if (status == kCMBlockBufferNoErr) {
  452. // 2. 创建 sampleBuffer
  453. CMSampleBufferRef sampleBuffer = NULL;
  454. const size_t sampleSizeArray[] = { static_cast<size_t>(size) };
  455. /*
  456. 参数1: allocator 分配器,使用默认内存分配, kCFAllocatorDefault
  457. 参数2: blockBuffer.需要编码的数据blockBuffer.不能为NULL
  458. 参数3: formatDescription,视频输出格式
  459. 参数4: numSamples.CMSampleBuffer 个数.
  460. 参数5: numSampleTimingEntries 必须为0,1,numSamples
  461. 参数6: sampleTimingArray. 数组.为空
  462. 参数7: numSampleSizeEntries 默认为1
  463. 参数8: sampleSizeArray
  464. 参数9: sampleBuffer对象
  465. */
  466. status = CMSampleBufferCreateReady(kCFAllocatorDefault,
  467. blockBuffer,
  468. _decoderFormatDescription,
  469. 1,
  470. 1,
  471. &timingInfo,
  472. 1,
  473. sampleSizeArray,
  474. &sampleBuffer);
  475. if (status == kCMBlockBufferNoErr && sampleBuffer) {
  476. // 3.调用解码函数
  477. //解码模式
  478. VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;
  479. //异步解码
  480. VTDecodeInfoFlags flagOut = kVTDecodeInfo_Asynchronous;
  481. /*
  482. VTDecompressionSessionDecodeFrame(
  483. VTDecompressionSessionRef session, //解码器 Session
  484. CMSampleBufferRef sampleBuffer, // 源数据 包含一个或多个视频帧的CMsampleBuffer
  485. VTDecodeFrameFlags decodeFlags, // 解码标志位。bit 0 is enableAsynchronousDecompression
  486. void * sourceFrameRefCon, //用户自定义参数指针。
  487. VTDecodeInfoFlags * infoFlagsOut //解码输出标志
  488. )
  489. */
  490. OSStatus decodeStatus = VTDecompressionSessionDecodeFrame(session,
  491. sampleBuffer,
  492. flags,
  493. sourceRef,
  494. &flagOut);
  495. NSLog(@"decodeStatus is:%d",(int)decodeStatus);
  496. if(decodeStatus == kVTInvalidSessionErr) {
  497. pthread_mutex_unlock(&lock);
  498. [self destoryDecoder];
  499. if (blockBuffer)
  500. CFRelease(blockBuffer);
  501. free(tempData);
  502. tempData = NULL;
  503. CFRelease(sampleBuffer);
  504. return;
  505. }
  506. CFRelease(sampleBuffer);
  507. }
  508. }
  509. if (blockBuffer) {
  510. CFRelease(blockBuffer);
  511. }
  512. free(tempData);
  513. tempData = NULL;
  514. pthread_mutex_unlock(&lock);
  515. }
  516. #pragma mark - Other
  517. - (CMSampleBufferRef)createSampleBufferFromPixelbuffer:(CVImageBufferRef)pixelBuffer videoRotate:(int)videoRotate timingInfo:(CMSampleTimingInfo)timingInfo {
  518. if (!pixelBuffer) {
  519. return NULL;
  520. }
  521. CVPixelBufferRef final_pixelbuffer = pixelBuffer;
  522. CMSampleBufferRef samplebuffer = NULL;
  523. CMVideoFormatDescriptionRef videoInfo = NULL;
  524. OSStatus status = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, final_pixelbuffer, &videoInfo);
  525. status = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, final_pixelbuffer, true, NULL, NULL, videoInfo, &timingInfo, &samplebuffer);
  526. if (videoInfo != NULL) {
  527. CFRelease(videoInfo);
  528. }
  529. if (samplebuffer == NULL || status != noErr) {
  530. return NULL;
  531. }
  532. return samplebuffer;
  533. }
  534. - (void)resetTimestamp {
  535. _decoderInfo.last_decode_pts = 0;
  536. }
  537. @end