• 第五十七篇、AVAssetReader和AVAssetWrite 对视频进行编码


    AV Foundation提供了直接处理媒体样本的低级功能,其中需要使用的两个重要的类,AVAssetReader和AVAssetWrite,AVAssetReader用于从AVAsset资源读取媒体样本,AVAssetWrite用于对媒体资源进行编码并写入到容器文件中。下面简单的使用一下:

    初始化AVAssetReader

    -(void)configAssetReader
    
    {
    
           NSURL *videoUrl = [NSURL fileURLWithPath:[self resoucePath]];
    
           _asset = [AVAsset assetWithURL:videoUrl];
    
          //获取资源的一个视频轨道
    
          AVAssetTrack *track = [[_asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
    
       _assetReader = [[AVAssetReader alloc] initWithAsset:_asset error:nil];
    
    //指定将读取的样本数据压缩为BGRA格式
    
        NSDictionary *setting =   @{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)};
    
      //初始化输出,指定从track轨道中读取样本数据
    
       _assetOutPut = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:setting];
    
    //添加输出
    
       [_assetReader addOutput:_assetOutPut];
    
      //开始读取过程
    
       [_assetReader startReading];
    
    }

    初始化AVAssetWrite

    -(void)configWriteInput
    
    {
    
         NSString *storePath = nil;
    
         NSString *path  = [self resoucePath];
    
        NSRange range = [path rangeOfString:@"/" options:NSBackwardsSearch];
    
       if (range.location != NSNotFound) {
    
              NSString *pathRoot = [path substringToIndex:range.location];
    
             storePath = [pathRoot stringByAppendingPathComponent:@"copy.mp4"];
    
       }
    
    if (storePath) {
    
           _assetWrite = [[AVAssetWriter alloc] initWithURL:[NSURL           fileURLWithPath:storePath] fileType:AVFileTypeQuickTimeMovie error:nil];
    
         //指定编码格式,像素宽高等信息
    
         NSDictionary *setting = @{
    
              AVVideoCodecKey:AVVideoCodecH264,
    
            AVVideoWidthKey:@1280,
    
            AVVideoHeightKey:@720,
    
           AVVideoCompressionPropertiesKey:@{
    
                    AVVideoMaxKeyFrameIntervalKey:@1,
    
                   AVVideoAverageBitRateKey:@10500000,
    
                   AVVideoProfileLevelKey:AVVideoProfileLevelH264Main31
    
             }
    
      };
    
        初始化写入器,并制定了媒体格式
    
        _assetInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:setting];
    
        //添加写入器
    
        [_assetWrite addInput:_assetInput];
    
        [_assetWrite startWriting];
    
       }
    
    }

    将读取的数据写入到_assetInput写入器中

    -(void)assertReadToAssetInput
    
    {
    
            dispatch_queue_t queue = dispatch_queue_create("com.writequeue", DISPATCH_QUEUE_CONCURRENT);
    
          if (_assetInput) {
    
                 __block NSInteger count = 0; 
    
                 __block BOOL isComplete = NO;
    
                //开启写入会话,并指定样本的开始时间
    
                [_assetWrite startSessionAtSourceTime:kCMTimeZero];
    
                [_assetInput requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
    
               if (!isComplete && _assetInput.readyForMoreMediaData)
    
               {
    
                       //样本数据
    
                        CMSampleBufferRef buffer = [_assetOutPut copyNextSampleBuffer];
    
                       if (buffer) {
    
                                [_assetInput appendSampleBuffer:buffer];
    
                                 count++;
    
                                 // 展示第2000帧数据
    
                                 if (count == 2000) {
    
                                  CGImageRef imgref = [UIImage imageFromSampleBufferRef:buffer];
    
                                 //读取CMSampleBuffer中的数据,将其转化为CGImageRef
    
                                参考代码见:http://www.jianshu.com/p/3d5ccbde0de1
    
                                 UIImage *img = [UIImage imageWithCGImage:imgref];
    
                                 dispatch_sync(dispatch_get_main_queue(), ^{
    
                                 _imageView.image = img;
    
                                      });
    
                                }
    
                         }
    
                        else
    
                       {
    
                              isComplete = YES;
    
                       }
    
                     if(isComplete)
    
                     {
    
                             //关闭写入会话 
    
                             [_assetWrite finishWritingWithCompletionHandler:^{
    
                                       AVAssetWriterStatus status = self.assetWrite.status;
    
                                       if (status == AVAssetWriterStatusCompleted) {
    
                                        NSLog(@"finsished");
    
                                       }               
    
                                       else
    
                                         {
    
                                                NSLog(@"failure");
    
                                         }
    
                                     }];
    
                       }
    
              } 
    
         }];
    
     }
    
    }
    -(void)assertReadToAssetInput
    
    {
    
            dispatch_queue_t queue = dispatch_queue_create("com.writequeue", DISPATCH_QUEUE_CONCURRENT);
    
          if (_assetInput) {
    
                 __block NSInteger count = 0; 
    
                 __block BOOL isComplete = NO;
    
                //开启写入会话,并指定样本的开始时间
    
                [_assetWrite startSessionAtSourceTime:kCMTimeZero];
    
                [_assetInput requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
    
               if (!isComplete && _assetInput.readyForMoreMediaData)
    
               {
    
                       //样本数据
    
                        CMSampleBufferRef buffer = [_assetOutPut copyNextSampleBuffer];
    
                       if (buffer) {
    
                                [_assetInput appendSampleBuffer:buffer];
    
                                 count++;
    
                                 // 展示第2000帧数据
    
                                 if (count == 2000) {
    
                                  CGImageRef imgref = [UIImage imageFromSampleBufferRef:buffer];
    
                                 //读取CMSampleBuffer中的数据,将其转化为CGImageRef
    
                                参考代码见:http://www.jianshu.com/p/3d5ccbde0de1
    
                                 UIImage *img = [UIImage imageWithCGImage:imgref];
    
                                 dispatch_sync(dispatch_get_main_queue(), ^{
    
                                 _imageView.image = img;
    
                                      });
    
                                }
    
                         }
    
                        else
    
                       {
    
                              isComplete = YES;
    
                       }
    
                     if(isComplete)
    
                     {
    
                             //关闭写入会话 
    
                             [_assetWrite finishWritingWithCompletionHandler:^{
    
                                       AVAssetWriterStatus status = self.assetWrite.status;
    
                                       if (status == AVAssetWriterStatusCompleted) {
    
                                        NSLog(@"finsished");
    
                                       }               
    
                                       else
    
                                         {
    
                                                NSLog(@"failure");
    
                                         }
    
                                     }];
    
                       }
    
              } 
    
         }];
    
     }
    
    }
  • 相关阅读:
    实验5 函数
    实验4 在分支循环结构中调用自定义函数
    Play 内置标签
    POI 正常输出WORD 文档
    用户WORD模板写文件
    Spring 注解过滤
    Spring 循环依赖
    Spring 表单标签
    WebService 客户端生成服务端代码
    Jquery 常用函数
  • 原文地址:https://www.cnblogs.com/HJQ2016/p/5963181.html
Copyright © 2020-2023  润新知