카메라로 촬영 한 무비에서 원시 푸티 지에 액세스 할 수 있으므로 원시 푸티지를 편집하거나 변형 할 수 있습니다 (예 : 검정/흰색으로 변경).IOS4 : AVFoundation : 무비에서 원시 푸티지를 얻는 방법
나는 AVAsset으로 mov를로드 할 수 있다는 것을 알고있다. 다른 AVAsset의 으로 컴포지션을 만든 다음 새 동영상으로 내 보내야하지만 동영상에 액세스하려면 어떻게해야합니까?
카메라로 촬영 한 무비에서 원시 푸티 지에 액세스 할 수 있으므로 원시 푸티지를 편집하거나 변형 할 수 있습니다 (예 : 검정/흰색으로 변경).IOS4 : AVFoundation : 무비에서 원시 푸티지를 얻는 방법
나는 AVAsset으로 mov를로드 할 수 있다는 것을 알고있다. 다른 AVAsset의 으로 컴포지션을 만든 다음 새 동영상으로 내 보내야하지만 동영상에 액세스하려면 어떻게해야합니까?
나는 모든 과정을 잘 모르겠지만, 좀 알고 :
당신은 개별 프레임을 처리하기 위해 AV 재단 프레임 워크 및 아마 코어 비디오 프레임 워크를 사용할 필요가 있습니다. 당신은 아마 AVWriter를 사용합니다 :
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
[NSURL fileURLWithPath:path]
fileType:AVFileTypeQuickTimeMovie
error:&error];
당신은 (이 예는 CV입니다) AVFoundation 또는 CV를 사용하여 픽셀 버퍼를 유지, 다음처럼 작성할 수 있습니다
[pixelBufferAdaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];
프레임을 얻으려면, AVAssetStillImageGenerator
ISN 정말 충분하지 않습니다.
또는 AVVideoMutableComposition, AVMutableComposition 또는 AVAssetExportSession에 사용할 수있는 필터 또는 명령어가있을 수 있습니다.
8 월에 요청한 이후로 진행 한 경우 관심이 있으시면 게시하십시오.
입력 애셋의 비디오 프레임을 읽고, 드로잉을하기 위해 각 프레임에 대한 CGContextRef를 작성한 다음 프레임을 새 비디오 파일에 작성해야합니다. 기본 단계는 다음과 같습니다. 모든 필러 코드와 오류 처리를 생략 했으므로 주요 단계를 더 쉽게 읽을 수 있습니다.
// AVURLAsset to read input movie (i.e. mov recorded to local storage)
NSDictionary *inputOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVURLAsset *inputAsset = [[AVURLAsset alloc] initWithURL:inputURL options:inputOptions];
// Load the input asset tracks information
[inputAsset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler: ^{
// Check status of "tracks", make sure they were loaded
AVKeyValueStatus tracksStatus = [inputAsset statusOfValueForKey:@"tracks" error:&error];
if (!tracksStatus == AVKeyValueStatusLoaded)
// failed to load
return;
// Fetch length of input video; might be handy
NSTimeInterval videoDuration = CMTimeGetSeconds([inputAsset duration]);
// Fetch dimensions of input video
CGSize videoSize = [inputAsset naturalSize];
/* Prepare output asset writer */
self.assetWriter = [[[AVAssetWriter alloc] initWithURL:outputURL fileType:AVFileTypeQuickTimeMovie error:&error] autorelease];
NSParameterAssert(assetWriter);
assetWriter.shouldOptimizeForNetworkUse = NO;
// Video output
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:videoSize.width], AVVideoWidthKey,
[NSNumber numberWithInt:videoSize.height], AVVideoHeightKey,
nil];
self.assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings];
NSParameterAssert(assetWriterVideoInput);
NSParameterAssert([assetWriter canAddInput:assetWriterVideoInput]);
[assetWriter addInput:assetWriterVideoInput];
// Start writing
CMTime presentationTime = kCMTimeZero;
[assetWriter startWriting];
[assetWriter startSessionAtSourceTime:presentationTime];
/* Read video samples from input asset video track */
self.reader = [AVAssetReader assetReaderWithAsset:inputAsset error:&error];
NSMutableDictionary *outputSettings = [NSMutableDictionary dictionary];
[outputSettings setObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey: (NSString*)kCVPixelBufferPixelFormatTypeKey];
self.readerVideoTrackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[inputAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
outputSettings:outputSettings];
// Assign the tracks to the reader and start to read
[reader addOutput:readerVideoTrackOutput];
if ([reader startReading] == NO) {
// Handle error
}
dispatch_queue_t dispatch_queue = dispatch_get_main_queue();
[assetWriterVideoInput requestMediaDataWhenReadyOnQueue:dispatch_queue usingBlock:^{
CMTime presentationTime = kCMTimeZero;
while ([assetWriterVideoInput isReadyForMoreMediaData]) {
CMSampleBufferRef sample = [readerVideoTrackOutput copyNextSampleBuffer];
if (sample) {
presentationTime = CMSampleBufferGetPresentationTimeStamp(sample);
/* Composite over video frame */
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sample);
// Lock the image buffer
CVPixelBufferLockBaseAddress(imageBuffer,0);
// Get information about the image
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
// Create a CGImageRef from the CVImageBufferRef
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
/*** Draw into context ref to draw over video frame ***/
// We unlock the image buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
// We release some components
CGContextRelease(newContext);
CGColorSpaceRelease(colorSpace);
/* End composite */
[assetWriterVideoInput appendSampleBuffer:sample];
CFRelease(sample);
}
else {
[assetWriterVideoInput markAsFinished];
/* Close output */
[assetWriter endSessionAtSourceTime:presentationTime];
if (![assetWriter finishWriting]) {
NSLog(@"[assetWriter finishWriting] failed, status=%@ error=%@", assetWriter.status, assetWriter.error);
}
}
}
}];
}];
이 코드 이제까지 실행이 있기 때문에입니까? 필자가 만든 비디오 샘플 버퍼를 추가 할 수 없었기 때문에 묻습니다. 나는 항상 AVAssetWriterInputPixelBufferAdaptor를 사용해야 만한다. 내가 볼 수있는 유일한 차이점은 샘플 버퍼가 기존 자산에서 비롯된 것입니다. 샘플 버퍼를 잘못 구성했을 수 있습니다. 아니면이 코드가 작동하지 않을 수도 있습니다. –
리드 미스 피스트맨 : 예, 코드는 작동하는 응용 프로그램에서 왔습니다. 당신이 처음부터 그것을 만드는 경우, 당신도 샘플 버퍼를 잘못 구성했다 것 같아요. 그건 내가하려고 노력한 것이 아닙니다. –
내가 지금 avassetwriter 실험 해요하지만 그것은 단지 만점에 4.1 –