Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add new protocols
  • Loading branch information
mchudy committed Feb 11, 2025
commit 5ce76551a0322d39159b38829c32df3f024fd050
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FA99E582D22C75300582559 /* CameraExposureTests.m */; };
7FCEDD352D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCEDD342D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m */; };
7FCEDD362D43C2B900EA1CA8 /* MockCaptureDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCEDD322D43C2B900EA1CA8 /* MockCaptureDevice.m */; };
7FD582352D57D97C003B1200 /* MockCaptureDeviceFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */; };
7FD582122D579650003B1200 /* MockWritableData.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582112D579650003B1200 /* MockWritableData.m */; };
7FD582202D579ECC003B1200 /* MockCapturePhotoOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD5821F2D579ECC003B1200 /* MockCapturePhotoOutput.m */; };
7FD582272D57C020003B1200 /* MockAssetWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582262D57C020003B1200 /* MockAssetWriter.m */; };
7FD582352D57D97C003B1200 /* MockCaptureDeviceFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
Expand Down Expand Up @@ -105,12 +106,14 @@
7FCEDD322D43C2B900EA1CA8 /* MockCaptureDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDevice.m; sourceTree = "<group>"; };
7FCEDD332D43C2B900EA1CA8 /* MockDeviceOrientationProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockDeviceOrientationProvider.h; sourceTree = "<group>"; };
7FCEDD342D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockDeviceOrientationProvider.m; sourceTree = "<group>"; };
7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDeviceFormat.m; sourceTree = "<group>"; };
7FD582362D57D989003B1200 /* MockCaptureDeviceFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceFormat.h; sourceTree = "<group>"; };
7FD582112D579650003B1200 /* MockWritableData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockWritableData.m; sourceTree = "<group>"; };
7FD582132D57965A003B1200 /* MockWritableData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockWritableData.h; sourceTree = "<group>"; };
7FD5821F2D579ECC003B1200 /* MockCapturePhotoOutput.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCapturePhotoOutput.m; sourceTree = "<group>"; };
7FD582212D579ED9003B1200 /* MockCapturePhotoOutput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCapturePhotoOutput.h; sourceTree = "<group>"; };
7FD582262D57C020003B1200 /* MockAssetWriter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockAssetWriter.m; sourceTree = "<group>"; };
7FD582282D57C02B003B1200 /* MockAssetWriter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockAssetWriter.h; sourceTree = "<group>"; };
7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDeviceFormat.m; sourceTree = "<group>"; };
7FD582362D57D989003B1200 /* MockCaptureDeviceFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceFormat.h; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -200,6 +203,8 @@
7F29EB3F2D281C6D00740257 /* Mocks */ = {
isa = PBXGroup;
children = (
7FD582282D57C02B003B1200 /* MockAssetWriter.h */,
7FD582262D57C020003B1200 /* MockAssetWriter.m */,
7F8FD22D2D4D0B73001AF2C1 /* MockFlutterBinaryMessenger.h */,
7F8FD22E2D4D0B88001AF2C1 /* MockFlutterBinaryMessenger.m */,
7F8FD22A2D4D07A6001AF2C1 /* MockFlutterTextureRegistry.h */,
Expand Down Expand Up @@ -533,6 +538,7 @@
E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */,
7F29EB292D26A59000740257 /* MockCameraDeviceDiscoverer.m in Sources */,
788A065A27B0E02900533D74 /* StreamingTest.m in Sources */,
7FD582272D57C020003B1200 /* MockAssetWriter.m in Sources */,
E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */,
7F29EB412D281C7E00740257 /* MockCaptureSession.m in Sources */,
E01EE4A82799F3A5008C1950 /* QueueUtilsTests.m in Sources */,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@import AVFoundation;
@import camera_avfoundation;

#import "MockAssetWriter.h"
#import "MockCaptureDevice.h"
#import "MockCaptureDeviceFormat.h"
#import "MockCaptureSession.h"
Expand Down Expand Up @@ -68,6 +69,14 @@
configuration.videoCaptureSession = videoSessionMock;
configuration.audioCaptureSession = audioSessionMock;
configuration.orientation = UIDeviceOrientationPortrait;
configuration.assetWriterFactory = ^NSObject<FLTAssetWriter> *(
NSURL *url, AVFileType fileType, NSError **error) {
return assetWriter;
};
configuration.pixelBufferAdaptorFactory = ^NSObject<FLTPixelBufferAdaptor> *(
NSObject<FLTAssetWriterInput> *input, NSDictionary<NSString *, id> *settings) {
return pixelBufferAdaptor;
};

return configuration;
}
Expand All @@ -86,6 +95,8 @@
.andReturn(@{});
OCMStub([captureVideoDataOutputMock sampleBufferCallbackQueue])
.andReturn(configuration.captureSessionQueue);



id videoMock = OCMClassMock([AVAssetWriterInputPixelBufferAdaptor class]);
OCMStub([videoMock assetWriterInputPixelBufferAdaptorWithAssetWriterInput:OCMOCK_ANY
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@import camera_avfoundation;
@import AVFoundation;

/// Mock implementation of `FLTAssetWriter` protocol which allows injecting a custom
/// implementation.
@interface MockAssetWriter : NSObject <FLTAssetWriter>

// Properties re-declared as read/write so a mocked value can be set during testing.
@property(nonatomic, assign) AVAssetWriterStatus status;
@property(nonatomic, strong) NSError *error;

// Stubs that are called when the corresponding public method is called.
@property(nonatomic, copy) void (^getStatusStub)(void);
@property(nonatomic, copy) void (^startWritingStub)(void);
@property(nonatomic, copy) void (^finishWritingStub)(void (^)(void));

@end

/// Mock implementation of `FLTAssetWriterInput` protocol which allows injecting a custom
/// implementation.
@interface MockAssetWriterInput : NSObject <FLTAssetWriterInput>

// Properties re-declared as read/write so a mocked value can be set during testing.
@property(nonatomic, strong) AVAssetWriterInput *input;
@property(nonatomic, assign) BOOL isReadyForMoreMediaData;
@property(nonatomic, assign) BOOL expectsMediaDataInRealTime;

// Stub that is called when the `appendSampleBuffer` method is called.
@property(nonatomic, copy) BOOL (^appendSampleBufferStub)(CMSampleBufferRef);

@end

/// Mock implementation of `FLTAssetWriterInput` protocol which allows injecting a custom
/// implementation.
@interface MockAssetWriterInputPixelBufferAdaptor : NSObject <FLTAssetWriterInputPixelBufferAdaptor>

// Stub that is called when the `appendPixelBuffer` method is called.
@property(nonatomic, copy) BOOL (^appendPixelBufferStub)(CVPixelBufferRef, CMTime);

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "MockAssetWriter.h"

@implementation MockAssetWriter

- (BOOL)startWriting {
if (self.startWritingStub) {
self.startWritingStub();
}
return YES;
}

- (void)finishWritingWithCompletionHandler:(void (^)(void))handler {
if (self.finishWritingStub) {
self.finishWritingStub(handler);
}
}

- (void)startSessionAtSourceTime:(CMTime)startTime {
}

- (void)addInput:(AVAssetWriterInput *)input {
}

@end

@implementation MockAssetWriterInput

- (BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer {
if (self.appendSampleBufferStub) {
return self.appendSampleBufferStub(sampleBuffer);
}
return YES;
}

@end

@implementation MockAssetWriterInputPixelBufferAdaptor

- (BOOL)appendPixelBuffer:(CVPixelBufferRef)pixelBuffer
withPresentationTime:(CMTime)presentationTime {
if (self.appendPixelBufferStub) {
return self.appendPixelBufferStub(pixelBuffer, presentationTime);
}
return YES;
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "./include/camera_avfoundation/FLTAssetWriter.h"

@interface FLTDefaultAssetWriter ()
@property(nonatomic, strong) AVAssetWriter *writer;
@end

@implementation FLTDefaultAssetWriter

- (instancetype)initWithURL:(NSURL *)url fileType:(AVFileType)fileType error:(NSError **)error {
self = [super init];
if (self) {
_writer = [[AVAssetWriter alloc] initWithURL:url fileType:fileType error:error];
}
return self;
}

- (BOOL)startWriting {
return [_writer startWriting];
}

- (void)finishWritingWithCompletionHandler:(void (^)(void))handler {
[_writer finishWritingWithCompletionHandler:handler];
}

- (AVAssetWriterStatus)status {
return _writer.status;
}

- (NSError *)error {
return _writer.error;
}

- (void)startSessionAtSourceTime:(CMTime)startTime {
return [_writer startSessionAtSourceTime:startTime];
}

- (void)addInput:(AVAssetWriterInput *)input {
return [_writer addInput:input];
}

@end

@interface FLTDefaultAssetWriterInput ()
@property(nonatomic, strong) AVAssetWriterInput *input;
@end

@implementation FLTDefaultAssetWriterInput

- (instancetype)initWithInput:(AVAssetWriterInput *)input {
self = [super init];
if (self) {
_input = input;
}
return self;
}

- (BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer {
return [_input appendSampleBuffer:sampleBuffer];
}

- (BOOL)expectsMediaDataInRealTime {
return [_input expectsMediaDataInRealTime];
}

- (void)setExpectsMediaDataInRealTime:(BOOL)expectsMediaDataInRealTime {
_input.expectsMediaDataInRealTime = expectsMediaDataInRealTime;
}

- (BOOL)isReadyForMoreMediaData {
return [_input isReadyForMoreMediaData];
}

@end

@interface FLTDefaultAssetWriterInputPixelBufferAdaptor ()
@property(nonatomic, strong) AVAssetWriterInputPixelBufferAdaptor *adaptor;
@end

@implementation FLTDefaultAssetWriterInputPixelBufferAdaptor

- (instancetype)initWithAdaptor:(AVAssetWriterInputPixelBufferAdaptor *)adaptor {
self = [super init];
if (self) {
_adaptor = adaptor;
}
return self;
}

- (BOOL)appendPixelBuffer:(CVPixelBufferRef)pixelBuffer
withPresentationTime:(CMTime)presentationTime {
return [_adaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentationTime];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ framework module camera_avfoundation {
module * { export * }

explicit module Test {
header "FLTAssetWriter.h"
header "FLTCameraDeviceDiscovering.h"
header "FLTCaptureDevice.h"
header "FLTCaptureDeviceFormat.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@import Foundation;
@import AVFoundation;

NS_ASSUME_NONNULL_BEGIN

/// A protocol that is a direct passthrough to `AVAssetWriter`. It is used to allow for mocking
/// `AVAssetWriter` in tests.
@protocol FLTAssetWriter <NSObject>

@property(nonatomic, readonly) AVAssetWriterStatus status;
@property(readonly, nullable) NSError *error;

- (BOOL)startWriting;
- (void)finishWritingWithCompletionHandler:(void (^)(void))handler;
- (void)startSessionAtSourceTime:(CMTime)startTime;
- (void)addInput:(AVAssetWriterInput *)input;

@end

/// A protocol that is a direct passthrough to `AVAssetWriterInput`. It is used to allow for mocking
/// `AVAssetWriterInput` in tests.
@protocol FLTAssetWriterInput <NSObject>

/// The underlying `AVAssetWriterInput` instance. All method and property calls will be forwarded
/// to this instance.
@property(nonatomic, readonly) AVAssetWriterInput *input;

@property(nonatomic, assign) BOOL expectsMediaDataInRealTime;
@property(nonatomic, readonly) BOOL isReadyForMoreMediaData;

- (BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer;

@end

/// A protocol that is a direct passthrough to `AVAssetWriterInputPixelBufferAdaptor`. It is used to
/// allow for mocking `AVAssetWriterInputPixelBufferAdaptor` in tests.
@protocol FLTAssetWriterInputPixelBufferAdaptor <NSObject>
- (BOOL)appendPixelBuffer:(CVPixelBufferRef)pixelBuffer
withPresentationTime:(CMTime)presentationTime;
@end

/// A default implementation of `FLTAssetWriter` which creates an `AVAssetWriter` instance and
/// forwards calls to it.
@interface FLTDefaultAssetWriter : NSObject <FLTAssetWriter>

/// Creates an `AVAssetWriter` instance with the given URL and file type. It takes the same params
/// as the `AVAssetWriter`'s initializer.
- (instancetype)initWithURL:(NSURL *)url fileType:(AVFileType)fileType error:(NSError **)error;

@end

/// A default implementation of `FLTAssetWriterInput` which forwards calls to the
/// underlying `AVAssetWriterInput`.
@interface FLTDefaultAssetWriterInput : NSObject <FLTAssetWriterInput>

/// Creates a wrapper around the `input` which will forward calls to it.
- (instancetype)initWithInput:(AVAssetWriterInput *)input;

@end

/// A default implementation of `FLTAssetWriterInputPixelBufferAdaptor` which forwards calls to the
/// underlying `AVAssetWriterInputPixelBufferAdaptor`.
@interface FLTDefaultAssetWriterInputPixelBufferAdaptor : NSObject <FLTAssetWriterInputPixelBufferAdaptor>

/// Creates a wrapper around the `adaptor` which will forward calls to it.
- (instancetype)initWithAdaptor:(AVAssetWriterInputPixelBufferAdaptor *)adaptor;

@end

NS_ASSUME_NONNULL_END