FUVideoDecoder.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //
  2. // FUVideoDecoder.m
  3. // FULiveDemo
  4. //
  5. // Created by 孙慕 on 2019/12/20.
  6. // Copyright © 2019 FaceUnity. All rights reserved.
  7. //
  8. #import "FUVideoDecoder.h"
  9. #import <AVFoundation/AVFoundation.h>
  10. @interface FUVideoDecoder(){
  11. BOOL _isRun;
  12. BOOL _isRepeat;
  13. int _fps;
  14. }
  15. @property (nonatomic, strong) AVAssetReader *assetReader;
  16. @property (nonatomic, strong) AVAssetTrack *videoTrack;
  17. @property (nonatomic, strong) AVAssetReaderTrackOutput* videoReaderOutput;
  18. @property (nonatomic, strong) NSURL *mUrl;
  19. @property (nonatomic, copy) videoDecoderCallBack videoCallBack;
  20. @end
  21. @implementation FUVideoDecoder
  22. -(instancetype)initWithVideoDecodeUrl:(NSURL *)url fps:(int)fps repeat:(BOOL)repeat callback:(videoDecoderCallBack)callback{
  23. if (self = [super init]) {
  24. if (!url) {
  25. NSLog(@"url is nil");
  26. }
  27. _videoCallBack = callback;
  28. _isRepeat = repeat;
  29. _mUrl = url;
  30. _fps = fps;
  31. [self videoStartReading];
  32. }
  33. return self;
  34. }
  35. -(void)setupVideoDecoder:(NSURL *)url{
  36. AVAsset *asset = [AVAsset assetWithURL:url];
  37. NSError *error;
  38. _assetReader = [[AVAssetReader alloc] initWithAsset:asset error:&error];
  39. NSLog(@"error = %@", error);
  40. NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
  41. _videoTrack = videoTracks[0];
  42. // 视频播放时,m_pixelFormatType = kCVPixelFormatType_32BGRA
  43. NSDictionary* options = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:
  44. (int)kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
  45. _videoReaderOutput = [[AVAssetReaderTrackOutput alloc]
  46. initWithTrack:_videoTrack outputSettings:options];
  47. [_assetReader addOutput:_videoReaderOutput];
  48. [_assetReader startReading];
  49. }
  50. -(void)runVideoDecoder{
  51. while (_videoTrack.nominalFrameRate > 0 && _isRun) {
  52. @autoreleasepool {
  53. if (_assetReader.status == AVAssetReaderStatusReading) {
  54. if(!_isRun) return;
  55. // 读取video sample
  56. CMSampleBufferRef videoBuffer = [_videoReaderOutput copyNextSampleBuffer];
  57. CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(videoBuffer);
  58. if (_videoCallBack) {
  59. _videoCallBack(pixelBuffer);
  60. }
  61. if (videoBuffer) {
  62. CMSampleBufferInvalidate(videoBuffer);
  63. CFRelease(videoBuffer);
  64. }
  65. // 根据需要休眠一段时间;比如上层播放视频时每帧之间是有间隔的
  66. [NSThread sleepForTimeInterval: 1.0 / _fps];
  67. }else if ([_assetReader status] == AVAssetReaderStatusCompleted) {
  68. if (_isRepeat) {
  69. [self setupVideoDecoder:_mUrl];
  70. }else{
  71. _isRun = NO;
  72. }
  73. }
  74. }
  75. }
  76. }
  77. -(void)videoStartReading{
  78. if (_isRun) {
  79. return;
  80. }
  81. _isRun = YES;
  82. [self setupVideoDecoder:_mUrl];
  83. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  84. [self runVideoDecoder];
  85. });
  86. }
  87. -(void)videoStopRending{
  88. _isRun = NO;
  89. [_assetReader cancelReading];
  90. _assetReader = nil;
  91. }
  92. /* 继续 */
  93. -(void)continueReading
  94. {
  95. [self setupVideoDecoder:_mUrl];
  96. }
  97. - (void)dealloc
  98. {
  99. NSLog(@"解码器销毁了video dealloc");
  100. }
  101. @end