AV Foundation系列(四)AVAssetReader和AVAssetWrite
阿新 • • 發佈:2019-01-27
http://www.jianshu.com/p/aeb441816a7d
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");
}
}];
}
}
}];
}
}
執行結果生成了copy.mp4視訊檔案,點選播放,發現只有視訊沒有音訊資訊,因為我們只有讀取了視訊的樣本資料並寫入,並沒有讀取裡面的音訊資料。所以沒有音訊,AVAsset往往對應的是一個格式容器,裡面包含了很多格式的資料,音訊,視訊,字幕等。
文/jiangamh(簡書作者)
原文連結:http://www.jianshu.com/p/aeb441816a7d
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。