Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions packages/camera/camera_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.9.22+2

* Migrates `FLTCamConfiguration`, `FLTCamMediaSettingsAVWrapper` classes to Swift.
* Migrates `FLTCaptureOutput`, `FLTCapturePhotoOutput`, `FLTCaptureVideoDataOutput` protocols to Swift.

## 0.9.22+1

* Fixes crash on iOS when `enableAudio` is false.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ final class CameraSessionPresetsTests: XCTestCase {
}

let configuration = CameraTestUtils.createTestCameraConfiguration()
configuration.captureDeviceFactory = { _ in captureDeviceMock }
configuration.videoDimensionsForFormat = { format in
configuration.videoCaptureDeviceFactory = { _ in captureDeviceMock }
configuration.videoDimensionsConverter = { format in
return CMVideoDimensions(width: 1, height: 1)
}
configuration.videoCaptureSession = videoSessionMock
Expand Down Expand Up @@ -65,7 +65,7 @@ final class CameraSessionPresetsTests: XCTestCase {
configuration.videoCaptureSession = videoSessionMock
configuration.mediaSettings = CameraTestUtils.createDefaultMediaSettings(
resolutionPreset: FCPPlatformResolutionPreset.max)
configuration.captureDeviceFactory = { _ in MockCaptureDevice() }
configuration.videoCaptureDeviceFactory = { _ in MockCaptureDevice() }

let _ = CameraTestUtils.createTestCamera(configuration)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private final class TestMediaSettingsAVWrapper: FLTCamMediaSettingsAVWrapper {
}

override func recommendedVideoSettingsForAssetWriter(
withFileType fileType: AVFileType, for output: FLTCaptureVideoDataOutput
withFileType fileType: AVFileType, for output: CaptureVideoDataOutput
) -> [String: Any]? {
return [:]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ enum CameraTestUtils {
enableAudio: true)
}

/// Creates a test `FLTCamConfiguration` with a default mock setup.
static func createTestCameraConfiguration() -> FLTCamConfiguration {
/// Creates a test `CameraConfiguration` with a default mock setup.
static func createTestCameraConfiguration() -> CameraConfiguration {
let captureSessionQueue = DispatchQueue(label: "capture_session_queue")

let videoSessionMock = MockCaptureSession()
Expand Down Expand Up @@ -56,7 +56,7 @@ enum CameraTestUtils {
currentFormat = format
}

let configuration = FLTCamConfiguration(
let configuration = CameraConfiguration(
mediaSettings: createDefaultMediaSettings(
resolutionPreset: FCPPlatformResolutionPreset.medium),
mediaSettingsWrapper: FLTCamMediaSettingsAVWrapper(),
Expand All @@ -72,7 +72,7 @@ enum CameraTestUtils {
configuration.audioCaptureSession = audioSessionMock
configuration.orientation = .portrait

configuration.assetWriterFactory = { _, _, _ in MockAssetWriter() }
configuration.assetWriterFactory = { _, _ in MockAssetWriter() }

configuration.inputPixelBufferAdaptorFactory = { _, _ in
MockAssetWriterInputPixelBufferAdaptor()
Expand All @@ -81,7 +81,7 @@ enum CameraTestUtils {
return configuration
}

static func createTestCamera(_ configuration: FLTCamConfiguration) -> DefaultCamera {
static func createTestCamera(_ configuration: CameraConfiguration) -> DefaultCamera {
return (try? DefaultCamera(configuration: configuration))!
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class FLTCamExposureTests: XCTestCase {
let mockDeviceOrientationProvider = MockDeviceOrientationProvider()

let configuration = CameraTestUtils.createTestCameraConfiguration()
configuration.captureDeviceFactory = { _ in mockDevice }
configuration.videoCaptureDeviceFactory = { _ in mockDevice }
configuration.deviceOrientationProvider = mockDeviceOrientationProvider
let camera = CameraTestUtils.createTestCamera(configuration)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class FLTCamSetFocusModeTests: XCTestCase {
let mockDeviceOrientationProvider = MockDeviceOrientationProvider()

let configuration = CameraTestUtils.createTestCameraConfiguration()
configuration.captureDeviceFactory = { _ in mockDevice }
configuration.videoCaptureDeviceFactory = { _ in mockDevice }
configuration.deviceOrientationProvider = mockDeviceOrientationProvider
let camera = CameraTestUtils.createTestCamera(configuration)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class FLTCamSetFlashModeTests: XCTestCase {
let mockCapturePhotoOutput = MockCapturePhotoOutput()

let configuration = CameraTestUtils.createTestCameraConfiguration()
configuration.captureDeviceFactory = { _ in mockDevice }
configuration.videoCaptureDeviceFactory = { _ in mockDevice }
let camera = CameraTestUtils.createTestCamera(configuration)
camera.capturePhotoOutput = mockCapturePhotoOutput

Expand Down Expand Up @@ -87,9 +87,7 @@ final class FLTCamSetFlashModeTests: XCTestCase {
func testSetFlashModeWithNonTorchMode_setsTrochModeOff_ifTorchModeIsEnabled() {
let (camera, mockDevice, mockCapturePhotoOutput) = createCamera()

mockCapturePhotoOutput.supportedFlashModes = [
NSNumber(value: AVCaptureDevice.FlashMode.auto.rawValue)
]
mockCapturePhotoOutput.supportedFlashModes = [.auto]

mockDevice.hasFlash = true
// Torch mode is enabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class FLTCamZoomTests: XCTestCase {
let mockDevice = MockCaptureDevice()

let configuration = CameraTestUtils.createTestCameraConfiguration()
configuration.captureDeviceFactory = { _ in mockDevice }
configuration.videoCaptureDeviceFactory = { _ in mockDevice }
let camera = CameraTestUtils.createTestCamera(configuration)

return (camera, mockDevice)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import camera_avfoundation
@testable import camera_avfoundation

// Import Objective-C part of the implementation when SwiftPM is used.
#if canImport(camera_avfoundation_objc)
Expand All @@ -11,11 +11,11 @@ import camera_avfoundation

/// Mock implementation of `FLTCapturePhotoOutput` protocol which allows injecting a custom
/// implementation.
final class MockCapturePhotoOutput: NSObject, FLTCapturePhotoOutput {
final class MockCapturePhotoOutput: NSObject, CapturePhotoOutput {
var avOutput = AVCapturePhotoOutput()
var availablePhotoCodecTypes: [AVVideoCodecType] = []
var highResolutionCaptureEnabled = false
var supportedFlashModes: [NSNumber] = []
var isHighResolutionCaptureEnabled = false
var supportedFlashModes: [AVCaptureDevice.FlashMode] = []

// Stub that is called when the corresponding public method is called.
var capturePhotoWithSettingsStub:
Expand All @@ -29,7 +29,7 @@ final class MockCapturePhotoOutput: NSObject, FLTCapturePhotoOutput {
capturePhotoWithSettingsStub?(settings, delegate)
}

func connection(withMediaType mediaType: AVMediaType) -> FLTCaptureConnection? {
func connection(with mediaType: AVMediaType) -> FLTCaptureConnection? {
return connectionWithMediaTypeStub?(mediaType)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import camera_avfoundation
@testable import camera_avfoundation

// Import Objective-C part of the implementation when SwiftPM is used.
#if canImport(camera_avfoundation_objc)
Expand All @@ -11,15 +11,14 @@ import camera_avfoundation

/// Mock implementation of `FLTCaptureVideoDataOutput` protocol which allows injecting a custom
/// implementation.
class MockCaptureVideoDataOutput: NSObject, FLTCaptureVideoDataOutput {

class MockCaptureVideoDataOutput: NSObject, CaptureVideoDataOutput {
var avOutput = AVCaptureVideoDataOutput()
var alwaysDiscardsLateVideoFrames = false
var videoSettings: [String: Any] = [:]
var videoSettings: [String: Any]! = [:]

var connectionWithMediaTypeStub: ((AVMediaType) -> FLTCaptureConnection?)?

func connection(withMediaType mediaType: AVMediaType) -> FLTCaptureConnection? {
func connection(with mediaType: AVMediaType) -> FLTCaptureConnection? {
return connectionWithMediaTypeStub?(mediaType)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ final class PhotoCaptureTests: XCTestCase {
key: captureSessionQueueSpecificKey, value: captureSessionQueueSpecificValue)
let configuration = CameraTestUtils.createTestCameraConfiguration()
configuration.captureSessionQueue = captureSessionQueue
configuration.captureDeviceFactory = { _ in captureDeviceMock }
configuration.videoCaptureDeviceFactory = { _ in captureDeviceMock }
let cam = CameraTestUtils.createTestCamera(configuration)

let filePath = "test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private class FakeMediaSettingsAVWrapper: FLTCamMediaSettingsAVWrapper {
}

override func recommendedVideoSettingsForAssetWriter(
withFileType fileType: AVFileType, for output: FLTCaptureVideoDataOutput
withFileType fileType: AVFileType, for output: CaptureVideoDataOutput
) -> [String: Any]? {
return [:]
}
Expand All @@ -87,7 +87,7 @@ final class CameraSampleBufferTests: XCTestCase {
enableAudio: true)
configuration.mediaSettingsWrapper = FakeMediaSettingsAVWrapper(inputMock: input)

configuration.assetWriterFactory = { url, fileType, error in
configuration.assetWriterFactory = { url, fileType in
return assetWriter
}
configuration.inputPixelBufferAdaptorFactory = { input, settings in
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import AVFoundation
import CoreMedia
import UIKit

// Import Objective-C part of the implementation when SwiftPM is used.
#if canImport(camera_avfoundation_objc)
import camera_avfoundation_objc
#endif

/// Factory block returning an FLTCaptureDevice.
/// Used in tests to inject a video capture device into DefaultCamera.
typealias VideoCaptureDeviceFactory = (_ cameraName: String) -> FLTCaptureDevice

typealias AudioCaptureDeviceFactory = () -> FLTCaptureDevice

typealias CaptureSessionFactory = () -> FLTCaptureSession

typealias AssetWriterFactory = (_ assetUrl: URL, _ fileType: AVFileType) throws -> FLTAssetWriter

typealias InputPixelBufferAdaptorFactory = (
_ input: FLTAssetWriterInput, _ settings: [String: Any]?
) ->
FLTAssetWriterInputPixelBufferAdaptor

/// Determines the video dimensions (width and height) for a given capture device format.
/// Used in tests to mock CMVideoFormatDescriptionGetDimensions.
typealias VideoDimensionsConverter = (FLTCaptureDeviceFormat) -> CMVideoDimensions

/// A configuration object that centralizes dependencies for `DefaultCamera`.
class CameraConfiguration {
var mediaSettings: FCPPlatformMediaSettings
var mediaSettingsWrapper: FLTCamMediaSettingsAVWrapper
var captureSessionQueue: DispatchQueue
var videoCaptureSession: FLTCaptureSession
var audioCaptureSession: FLTCaptureSession
var videoCaptureDeviceFactory: VideoCaptureDeviceFactory
let audioCaptureDeviceFactory: AudioCaptureDeviceFactory
let captureDeviceInputFactory: FLTCaptureDeviceInputFactory
var assetWriterFactory: AssetWriterFactory
var inputPixelBufferAdaptorFactory: InputPixelBufferAdaptorFactory
var videoDimensionsConverter: VideoDimensionsConverter
var deviceOrientationProvider: FLTDeviceOrientationProviding
let initialCameraName: String
var orientation: UIDeviceOrientation

init(
mediaSettings: FCPPlatformMediaSettings,
mediaSettingsWrapper: FLTCamMediaSettingsAVWrapper,
captureDeviceFactory: @escaping VideoCaptureDeviceFactory,
audioCaptureDeviceFactory: @escaping AudioCaptureDeviceFactory,
captureSessionFactory: @escaping CaptureSessionFactory,
captureSessionQueue: DispatchQueue,
captureDeviceInputFactory: FLTCaptureDeviceInputFactory,
initialCameraName: String
) {
self.mediaSettings = mediaSettings
self.mediaSettingsWrapper = mediaSettingsWrapper
self.videoCaptureDeviceFactory = captureDeviceFactory
self.audioCaptureDeviceFactory = audioCaptureDeviceFactory
self.captureSessionQueue = captureSessionQueue
self.videoCaptureSession = captureSessionFactory()
self.audioCaptureSession = captureSessionFactory()
self.captureDeviceInputFactory = captureDeviceInputFactory
self.initialCameraName = initialCameraName
self.orientation = UIDevice.current.orientation
self.deviceOrientationProvider = FLTDefaultDeviceOrientationProvider()

self.videoDimensionsConverter = { format in
return CMVideoFormatDescriptionGetDimensions(format.formatDescription)
}

self.assetWriterFactory = { url, fileType in
var error: NSError?
let writer = FLTDefaultAssetWriter(url: url, fileType: fileType, error: &error)

if let error = error {
throw error
}

return writer
}

self.inputPixelBufferAdaptorFactory = { assetWriterInput, sourcePixelBufferAttributes in
let adaptor = AVAssetWriterInputPixelBufferAdaptor(
assetWriterInput: assetWriterInput.input,
sourcePixelBufferAttributes: sourcePixelBufferAttributes
)
return FLTDefaultAssetWriterInputPixelBufferAdaptor(adaptor: adaptor)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public final class CameraPlugin: NSObject, FlutterPlugin {
private let globalEventAPI: FCPCameraGlobalEventApi
private let deviceDiscoverer: FLTCameraDeviceDiscovering
private let permissionManager: FLTCameraPermissionManager
private let captureDeviceFactory: CaptureDeviceFactory
private let captureDeviceFactory: VideoCaptureDeviceFactory
private let captureSessionFactory: CaptureSessionFactory
private let captureDeviceInputFactory: FLTCaptureDeviceInputFactory

Expand Down Expand Up @@ -52,7 +52,7 @@ public final class CameraPlugin: NSObject, FlutterPlugin {
globalAPI: FCPCameraGlobalEventApi,
deviceDiscoverer: FLTCameraDeviceDiscovering,
permissionManager: FLTCameraPermissionManager,
deviceFactory: @escaping CaptureDeviceFactory,
deviceFactory: @escaping VideoCaptureDeviceFactory,
captureSessionFactory: @escaping CaptureSessionFactory,
captureDeviceInputFactory: FLTCaptureDeviceInputFactory,
captureSessionQueue: DispatchQueue
Expand Down Expand Up @@ -251,7 +251,7 @@ extension CameraPlugin: FCPCameraApi {
) {
let mediaSettingsAVWrapper = FLTCamMediaSettingsAVWrapper()

let camConfiguration = FLTCamConfiguration(
let camConfiguration = CameraConfiguration(
mediaSettings: settings,
mediaSettingsWrapper: mediaSettingsAVWrapper,
captureDeviceFactory: captureDeviceFactory,
Expand Down
Loading