第五十七篇、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:@, AVVideoHeightKey:@, AVVideoCompressionPropertiesKey:@{ AVVideoMaxKeyFrameIntervalKey:@, AVVideoAverageBitRateKey:@, 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 = ; __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 == ) { 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 = ; __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 == ) { 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"); } }]; } } }]; } }
第五十七篇、AVAssetReader和AVAssetWrite 对视频进行编码的更多相关文章
- 第五十七篇:webpack打包发布
好家伙,到了打包发布这一步了 1.配置打包命令: 在package.json 文件的 scripts 节点下,新增 build 命令如下: "scripts": { "d ...
- Egret入门学习日记 --- 第十七篇(书中 7.4~8.2节 内容)
第十七篇(书中 7.4~8.2节 内容) 昨天看到 7.3 节,那么今天. 开始 7.4节. 好吧,这些其他的服务器运行知识,就不搞了... 至此,7.4节 内容结束. 开始 7.5节 内容. ...
- 解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)
解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译) http://improve.dk/corrupting-databases-purpose-usin ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十七篇】:Django之【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十七篇】:Django【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- 第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码
第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码 scrapy-redis是一个可以scrapy结合redis搭建分布式爬虫的开 ...
- “全栈2019”Java第五十七章:多态与构造方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 孤荷凌寒自学python第五十七天初次尝试使用python来连接远端MongoDb数据库
孤荷凌寒自学python第五十七天初次尝试使用python来连接远端MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第三天.感觉这个东西学习起来还是那么困 ...
随机推荐
- c#与java webservice调用问题
问题描述一: c#调用java写的websrevice,对方接收到的参数与实际传的值不一致,返回的时候值也获取不到,为null. 该参数为普通的string类型,因此不存在类型转换的问题. 处理: 使 ...
- 怎么修改电脑MAC地址 电脑MAC地址修改图文教程
本文转载:http://www.45fan.com/a/Router/2677.html MAC地址是指电脑网卡的硬件地址,此地址一般烧录在网卡上.MAC地址工作在OSI七层模型的第二层,即数据链接层 ...
- Java中的Annotation(2)----Annotation工作原理
Java中的Annotation(2)----Annotation工作原理 分类: 编程语言2013-03-18 01:06 3280人阅读 评论(6) 收藏 举报 上一篇文章已经介绍了如何使用JDK ...
- uva 11983 Weird Advertisement 扫描线
Weird Advertisement Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/probl ...
- codeforces 468B 2-sat
今天明确了2-SAT; 表示对一对整数之间的关系是否存在 #include<cstdio> #include<algorithm> #include<iostream&g ...
- delphi TPopupMenu.Popup
procedure TPopupMenu.Popup(X, Y: Integer); 这个点是相对桌面的而不是窗体的 GetCursorPos是鼠标的位置 鼠标动这个点就不一样 v ...
- 【VBA研究】怎样将单元格数据赋给数组
作者:iamlaosong 将工作表中的数据赋给数组或者将数组的数据赋给工作表,一般有两种.一种是循环的方法,一个一个的传,这样的方法一般用于须要对每一个数据特别处理的场合,还有一种是一次性用赋值语句 ...
- range-bar
https://github.com/edmodo/range-bar
- 日志分析(二) logstash patterns
grok-patterns内置了很多基础变量的正则表达式的log解析规则,其中包括apache的log解析(同样可以用于nginx的log解析). 基于nginx日志分析配置: 1.配置nginx ...
- 描述cookie,sessionstroage,localstrage的区别
HTML5 提供了两种在客户端存储数据的新方法(Web Storage): localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 ...