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

初始化AVAssetReader

  1. -(void)configAssetReader
  2.  
  3. {
  4.  
  5. NSURL *videoUrl = [NSURL fileURLWithPath:[self resoucePath]];
  6.  
  7. _asset = [AVAsset assetWithURL:videoUrl];
  8.  
  9. //获取资源的一个视频轨道
  10.  
  11. AVAssetTrack *track = [[_asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
  12.  
  13. _assetReader = [[AVAssetReader alloc] initWithAsset:_asset error:nil];
  14.  
  15. //指定将读取的样本数据压缩为BGRA格式
  16.  
  17. NSDictionary *setting = @{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)};
  18.  
  19. //初始化输出,指定从track轨道中读取样本数据
  20.  
  21. _assetOutPut = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:setting];
  22.  
  23. //添加输出
  24.  
  25. [_assetReader addOutput:_assetOutPut];
  26.  
  27. //开始读取过程
  28.  
  29. [_assetReader startReading];
  30.  
  31. }

初始化AVAssetWrite

  1. -(void)configWriteInput
  2.  
  3. {
  4.  
  5. NSString *storePath = nil;
  6.  
  7. NSString *path = [self resoucePath];
  8.  
  9. NSRange range = [path rangeOfString:@"/" options:NSBackwardsSearch];
  10.  
  11. if (range.location != NSNotFound) {
  12.  
  13. NSString *pathRoot = [path substringToIndex:range.location];
  14.  
  15. storePath = [pathRoot stringByAppendingPathComponent:@"copy.mp4"];
  16.  
  17. }
  18.  
  19. if (storePath) {
  20.  
  21. _assetWrite = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:storePath] fileType:AVFileTypeQuickTimeMovie error:nil];
  22.  
  23. //指定编码格式,像素宽高等信息
  24.  
  25. NSDictionary *setting = @{
  26.  
  27. AVVideoCodecKey:AVVideoCodecH264,
  28.  
  29. AVVideoWidthKey:@,
  30.  
  31. AVVideoHeightKey:@,
  32.  
  33. AVVideoCompressionPropertiesKey:@{
  34.  
  35. AVVideoMaxKeyFrameIntervalKey:@,
  36.  
  37. AVVideoAverageBitRateKey:@,
  38.  
  39. AVVideoProfileLevelKey:AVVideoProfileLevelH264Main31
  40.  
  41. }
  42.  
  43. };
  44.  
  45. 初始化写入器,并制定了媒体格式
  46.  
  47. _assetInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:setting];
  48.  
  49. //添加写入器
  50.  
  51. [_assetWrite addInput:_assetInput];
  52.  
  53. [_assetWrite startWriting];
  54.  
  55. }
  56.  
  57. }

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

  1. -(void)assertReadToAssetInput
  2.  
  3. {
  4.  
  5. dispatch_queue_t queue = dispatch_queue_create("com.writequeue", DISPATCH_QUEUE_CONCURRENT);
  6.  
  7. if (_assetInput) {
  8.  
  9. __block NSInteger count = ;
  10.  
  11. __block BOOL isComplete = NO;
  12.  
  13. //开启写入会话,并指定样本的开始时间
  14.  
  15. [_assetWrite startSessionAtSourceTime:kCMTimeZero];
  16.  
  17. [_assetInput requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
  18.  
  19. if (!isComplete && _assetInput.readyForMoreMediaData)
  20.  
  21. {
  22.  
  23. //样本数据
  24.  
  25. CMSampleBufferRef buffer = [_assetOutPut copyNextSampleBuffer];
  26.  
  27. if (buffer) {
  28.  
  29. [_assetInput appendSampleBuffer:buffer];
  30.  
  31. count++;
  32.  
  33. // 展示第2000帧数据
  34.  
  35. if (count == ) {
  36.  
  37. CGImageRef imgref = [UIImage imageFromSampleBufferRef:buffer];
  38.  
  39. //读取CMSampleBuffer中的数据,将其转化为CGImageRef
  40.  
  41. 参考代码见:http://www.jianshu.com/p/3d5ccbde0de1
  42.  
  43. UIImage *img = [UIImage imageWithCGImage:imgref];
  44.  
  45. dispatch_sync(dispatch_get_main_queue(), ^{
  46.  
  47. _imageView.image = img;
  48.  
  49. });
  50.  
  51. }
  52.  
  53. }
  54.  
  55. else
  56.  
  57. {
  58.  
  59. isComplete = YES;
  60.  
  61. }
  62.  
  63. if(isComplete)
  64.  
  65. {
  66.  
  67. //关闭写入会话
  68.  
  69. [_assetWrite finishWritingWithCompletionHandler:^{
  70.  
  71. AVAssetWriterStatus status = self.assetWrite.status;
  72.  
  73. if (status == AVAssetWriterStatusCompleted) {
  74.  
  75. NSLog(@"finsished");
  76.  
  77. }
  78.  
  79. else
  80.  
  81. {
  82.  
  83. NSLog(@"failure");
  84.  
  85. }
  86.  
  87. }];
  88.  
  89. }
  90.  
  91. }
  92.  
  93. }];
  94.  
  95. }
  96.  
  97. }
  1. -(void)assertReadToAssetInput
  2.  
  3. {
  4.  
  5. dispatch_queue_t queue = dispatch_queue_create("com.writequeue", DISPATCH_QUEUE_CONCURRENT);
  6.  
  7. if (_assetInput) {
  8.  
  9. __block NSInteger count = ;
  10.  
  11. __block BOOL isComplete = NO;
  12.  
  13. //开启写入会话,并指定样本的开始时间
  14.  
  15. [_assetWrite startSessionAtSourceTime:kCMTimeZero];
  16.  
  17. [_assetInput requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
  18.  
  19. if (!isComplete && _assetInput.readyForMoreMediaData)
  20.  
  21. {
  22.  
  23. //样本数据
  24.  
  25. CMSampleBufferRef buffer = [_assetOutPut copyNextSampleBuffer];
  26.  
  27. if (buffer) {
  28.  
  29. [_assetInput appendSampleBuffer:buffer];
  30.  
  31. count++;
  32.  
  33. // 展示第2000帧数据
  34.  
  35. if (count == ) {
  36.  
  37. CGImageRef imgref = [UIImage imageFromSampleBufferRef:buffer];
  38.  
  39. //读取CMSampleBuffer中的数据,将其转化为CGImageRef
  40.  
  41. 参考代码见:http://www.jianshu.com/p/3d5ccbde0de1
  42.  
  43. UIImage *img = [UIImage imageWithCGImage:imgref];
  44.  
  45. dispatch_sync(dispatch_get_main_queue(), ^{
  46.  
  47. _imageView.image = img;
  48.  
  49. });
  50.  
  51. }
  52.  
  53. }
  54.  
  55. else
  56.  
  57. {
  58.  
  59. isComplete = YES;
  60.  
  61. }
  62.  
  63. if(isComplete)
  64.  
  65. {
  66.  
  67. //关闭写入会话
  68.  
  69. [_assetWrite finishWritingWithCompletionHandler:^{
  70.  
  71. AVAssetWriterStatus status = self.assetWrite.status;
  72.  
  73. if (status == AVAssetWriterStatusCompleted) {
  74.  
  75. NSLog(@"finsished");
  76.  
  77. }
  78.  
  79. else
  80.  
  81. {
  82.  
  83. NSLog(@"failure");
  84.  
  85. }
  86.  
  87. }];
  88.  
  89. }
  90.  
  91. }
  92.  
  93. }];
  94.  
  95. }
  96.  
  97. }

第五十七篇、AVAssetReader和AVAssetWrite 对视频进行编码的更多相关文章

  1. 第五十七篇:webpack打包发布

    好家伙,到了打包发布这一步了 1.配置打包命令: 在package.json 文件的 scripts 节点下,新增 build 命令如下: "scripts": { "d ...

  2. Egret入门学习日记 --- 第十七篇(书中 7.4~8.2节 内容)

    第十七篇(书中 7.4~8.2节 内容) 昨天看到 7.3 节,那么今天. 开始 7.4节.     好吧,这些其他的服务器运行知识,就不搞了... 至此,7.4节 内容结束. 开始 7.5节 内容. ...

  3. 解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)

    解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译) http://improve.dk/corrupting-databases-purpose-usin ...

  4. Python之路【第十七篇】:Django【进阶篇 】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  5. Python之路【第十七篇】:Django之【进阶篇】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  6. Python之路【第十七篇】:Django【进阶篇】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  7. 第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码

    第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码 scrapy-redis是一个可以scrapy结合redis搭建分布式爬虫的开 ...

  8. “全栈2019”Java第五十七章:多态与构造方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. 孤荷凌寒自学python第五十七天初次尝试使用python来连接远端MongoDb数据库

    孤荷凌寒自学python第五十七天初次尝试使用python来连接远端MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第三天.感觉这个东西学习起来还是那么困 ...

随机推荐

  1. 2015 NOIP day1 t1 神奇的幻方 模拟

    神奇的幻方 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.luogu.org/problem/show?pid=2615 Descri ...

  2. POJ 2420 A Star not a Tree? 爬山算法

    B - A Star not a Tree? Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/co ...

  3. 读《C# 和 Java 的比较》有感

    网上的一篇<C# 和 Java 的比较>(或者叫<Java 和 C# 的比较>)写的挺不错的,今天忽然搜索到. 自己刚刚接触C#,也不由自主地随时都拿来和Java做对比,所以就 ...

  4. 【项目实例】android开发游戏音效代码实例

    //音效的音量 int streamVolume; //定义SoundPool 对象 private SoundPool soundPool; //定义HASH表 private HashMap< ...

  5. Github上最全的APICloud开源前端框架效果盘点(转)

    1.微信网站几分钟变身“原生 App” 微信推出了微信JS-SDK,使微信公共号可以直接调用微信原生的接口,具备部分原生应用的能力.微信JS-SDK的推出,将大大提高微信公共号的 用户体验,但是如果存 ...

  6. apue.h

    [root@localhost unix_env_advance_prog]# cat apue.h #ifndef _APUE_H #define _APUE_H #define _XOPEN_SO ...

  7. C++:构造函数和析构函数能否为虚函数

    原文:http://blog.csdn.net/xhz1234/article/details/6510568 C++:构造函数和析构函数能否为虚函数? 简单回答是:构造函数不能为虚函数,而析构函数可 ...

  8. JS_CSS_logon_Mask

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 1、netlink 连接器 通信机制

    使用netlink之前,先参考一下资料:http://www.ibm.com/developerworks/cn/linux/l-connector/ netlink通信机制介绍:资料来源 linux ...

  10. G - Just a Hook

    Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of t ...