我遇到了一个奇怪的边缘情况,用AVAssetWriterInput初始化AVAssetWriterInputPixelBufferAdaptor会阻止AVAssetWriter使用相同的AVAssetWriterInput进行写入。仅当使用小于113的高度或宽度时才会发生这种情况。看起来AVAssetWriterInputPixelBufferAdaptor必须在其初始化程序期间修改AVAssetWriterInput。有什么想法吗?
这是一个解决问题的测试:
#import <XCTest/XCTest.h>
#import <AVFoundation/AVFoundation.h>
#define HEIGHT @100
#define WIDTH @100
@interface AVAssetWriterInput (dimensions)
+ (AVAssetWriterInput*)AVAssetWriterInputWithHeight: (NSNumber*) height width: (NSNumber*) width;
@end
@implementation AVAssetWriterInput (dimensions)
+ (AVAssetWriterInput*)AVAssetWriterInputWithHeight: (NSNumber*) height width: (NSNumber*) width{
NSDictionary* cleanApertureSettings = @{AVVideoCleanApertureWidthKey : width,
AVVideoCleanApertureHeightKey : height,
AVVideoCleanApertureHorizontalOffsetKey : @0,
AVVideoCleanApertureVerticalOffsetKey : @0};
NSDictionary *videoCodecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1000000], AVVideoAverageBitRateKey,
[NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
cleanApertureSettings, AVVideoCleanApertureKey,
nil];
NSDictionary *videoSettings = @{AVVideoCodecKey: AVVideoCodecH264,
AVVideoCompressionPropertiesKey : videoCodecSettings,
AVVideoWidthKey: width,
AVVideoHeightKey: height
};
AVAssetWriterInput* input = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings];
input.expectsMediaDataInRealTime = FALSE;
return input;
}
@end
@interface AVAssetWriterInputTest : XCTestCase
@end
@implementation AVAssetWriterInputTest
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (BOOL) validAVAssetWriterStatus: (AVAssetWriterInput*) input{
NSURL* outputURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"temp.mp4"]];
NSError* writerError;
AVAssetWriter * writer = [[AVAssetWriter alloc] initWithURL:outputURL fileType:AVFileTypeMPEG4 error:&writerError];
XCTAssertNil(writerError);
[writer addInput:input];
[writer startWriting];
BOOL validStatus = writer.status != AVAssetWriterStatusFailed;
[writer cancelWriting];
return validStatus;
}
//Succeeds
- (void)testDefaultCase{
AVAssetWriterInput* input = [AVAssetWriterInput AVAssetWriterInputWithHeight:HEIGHT width:WIDTH];
XCTAssertTrue([self validAVAssetWriterStatus:input], @"%@ x %@ default case fails", HEIGHT, WIDTH);
}
//Fails when height or width < 113
- (void)testWithAVAssetWriterInputPixelBufferAdaptor{
AVAssetWriterInput* input = [AVAssetWriterInput AVAssetWriterInputWithHeight:HEIGHT width:WIDTH];
NSDictionary* attributes = @{
(NSString*)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32ARGB),
(NSString*)kCVPixelBufferWidthKey : WIDTH,
(NSString*)kCVPixelBufferHeightKey : HEIGHT,
(NSString*)kCVPixelBufferCGImageCompatibilityKey : @YES,
(NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES
};
[[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:input sourcePixelBufferAttributes:attributes];
XCTAssertTrue([self validAVAssetWriterStatus:input], @"%@ x %@ adaptor case fails", HEIGHT, WIDTH);
}
@end