diff --git a/packages/camera/camera_platform_interface/coverage/lcov.info b/packages/camera/camera_platform_interface/coverage/lcov.info new file mode 100644 index 000000000000..00d4f8ebbc7a --- /dev/null +++ b/packages/camera/camera_platform_interface/coverage/lcov.info @@ -0,0 +1,619 @@ +SF:lib\src\events\camera_event.dart +DA:30,3 +DA:35,2 +DA:38,2 +DA:39,6 +DA:40,6 +DA:42,1 +DA:43,2 +DA:53,2 +DA:65,1 +DA:66,1 +DA:67,1 +DA:68,2 +DA:70,1 +DA:71,2 +DA:72,1 +DA:73,2 +DA:95,4 +DA:96,2 +DA:97,2 +DA:98,2 +DA:99,4 +DA:100,2 +DA:101,4 +DA:102,2 +DA:105,2 +DA:108,2 +DA:109,2 +DA:110,6 +DA:111,6 +DA:112,6 +DA:113,6 +DA:114,6 +DA:115,6 +DA:116,6 +DA:118,1 +DA:119,1 +DA:120,1 +DA:121,1 +DA:122,1 +DA:123,1 +DA:124,1 +DA:125,1 +DA:126,1 +DA:137,2 +DA:145,1 +DA:146,1 +DA:147,1 +DA:148,2 +DA:158,4 +DA:159,2 +DA:160,2 +DA:161,2 +DA:164,2 +DA:167,2 +DA:168,2 +DA:169,6 +DA:170,6 +DA:171,6 +DA:173,1 +DA:174,4 +DA:181,2 +DA:185,1 +DA:186,2 +DA:190,4 +DA:191,2 +DA:194,2 +DA:197,2 +DA:198,1 +DA:199,3 +DA:201,1 +DA:205,1 +DA:214,2 +DA:218,1 +DA:219,1 +DA:220,2 +DA:227,4 +DA:228,2 +DA:229,2 +DA:232,2 +DA:235,2 +DA:236,2 +DA:237,6 +DA:238,6 +DA:240,1 +DA:241,3 +DA:251,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:260,0 +DA:270,0 +DA:271,0 +DA:272,0 +DA:273,0 +DA:276,0 +DA:279,0 +DA:280,0 +DA:281,0 +DA:282,0 +DA:284,0 +DA:285,0 +LF:102 +LH:85 +end_of_record +SF:lib\src\events\device_event.dart +DA:26,4 +DA:32,3 +DA:36,1 +DA:38,2 +DA:45,4 +DA:46,4 +DA:49,2 +DA:52,2 +DA:53,6 +DA:54,6 +DA:56,1 +DA:57,2 +LF:12 +LH:12 +end_of_record +SF:lib\src\platform_interface\camera_platform.dart +DA:24,6 +DA:26,6 +DA:28,3 +DA:33,2 +DA:37,1 +DA:38,2 +DA:45,1 +DA:46,1 +DA:50,1 +DA:55,1 +DA:57,1 +DA:66,1 +DA:70,1 +DA:79,1 +DA:83,1 +DA:87,1 +DA:88,1 +DA:93,1 +DA:94,1 +DA:98,1 +DA:99,1 +DA:103,1 +DA:104,1 +DA:108,0 +DA:109,0 +DA:116,1 +DA:117,1 +DA:122,1 +DA:124,1 +DA:128,1 +DA:129,1 +DA:133,1 +DA:134,1 +DA:138,1 +DA:139,1 +DA:151,1 +DA:152,1 +DA:159,0 +DA:160,0 +DA:161,0 +DA:165,1 +DA:166,1 +DA:170,1 +DA:171,1 +DA:175,1 +DA:176,1 +DA:189,0 +DA:191,0 +DA:196,1 +DA:197,1 +DA:201,1 +DA:202,1 +DA:209,1 +DA:210,1 +DA:214,1 +DA:215,1 +DA:219,1 +DA:220,1 +DA:226,1 +DA:227,1 +DA:241,1 +DA:242,1 +DA:246,1 +DA:247,1 +DA:254,1 +DA:255,1 +DA:259,1 +DA:260,1 +DA:264,1 +DA:265,1 +DA:273,1 +DA:274,1 +DA:278,1 +DA:279,1 +DA:283,1 +DA:284,1 +DA:288,0 +DA:289,0 +DA:294,0 +DA:295,0 +DA:299,1 +DA:300,1 +LF:82 +LH:71 +end_of_record +SF:lib\src\types\media_settings.dart +DA:16,4 +DA:22,1 +DA:23,1 +DA:25,1 +DA:49,1 +DA:54,3 +DA:57,1 +DA:58,3 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:65,1 +DA:66,1 +DA:67,1 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +LF:26 +LH:15 +end_of_record +SF:lib\src\utils\utils.dart +DA:10,2 +DA:12,2 +DA:14,2 +DA:16,1 +DA:19,1 +DA:23,3 +DA:25,3 +DA:27,1 +DA:29,1 +DA:31,1 +DA:37,3 +DA:39,3 +DA:41,1 +DA:43,1 +DA:45,1 +DA:48,0 +LF:16 +LH:15 +end_of_record +SF:lib\src\method_channel\method_channel_camera.dart +DA:22,2 +DA:25,2 +DA:26,0 +DA:59,1 +DA:60,2 +DA:61,4 +DA:63,1 +DA:67,1 +DA:70,0 +DA:73,2 +DA:74,1 +DA:75,1 +DA:77,2 +DA:78,1 +DA:80,1 +DA:81,1 +DA:82,3 +DA:86,0 +DA:92,0 +DA:94,0 +DA:97,1 +DA:104,1 +DA:106,2 +DA:107,1 +DA:109,2 +DA:111,1 +DA:112,1 +DA:113,1 +DA:114,1 +DA:117,1 +DA:118,1 +DA:119,3 +DA:123,1 +DA:128,3 +DA:130,2 +DA:131,1 +DA:132,0 +DA:136,1 +DA:138,4 +DA:139,1 +DA:142,1 +DA:144,1 +DA:146,1 +DA:148,1 +DA:153,1 +DA:154,1 +DA:158,1 +DA:159,3 +DA:165,1 +DA:168,1 +DA:170,2 +DA:171,2 +DA:172,1 +DA:173,2 +DA:176,1 +DA:178,1 +DA:182,1 +DA:184,2 +DA:187,1 +DA:189,2 +DA:192,1 +DA:194,2 +DA:197,1 +DA:199,2 +DA:202,0 +DA:204,0 +DA:207,1 +DA:209,2 +DA:210,1 +DA:213,1 +DA:218,1 +DA:220,1 +DA:222,1 +DA:227,1 +DA:229,1 +DA:231,1 +DA:235,1 +DA:237,1 +DA:239,1 +DA:243,0 +DA:245,0 +DA:249,1 +DA:252,1 +DA:254,1 +DA:256,1 +DA:259,1 +DA:260,1 +DA:263,1 +DA:265,1 +DA:267,1 +DA:268,1 +DA:269,2 +DA:270,1 +DA:274,1 +DA:275,0 +DA:276,0 +DA:280,1 +DA:282,1 +DA:284,1 +DA:288,0 +DA:290,0 +DA:294,1 +DA:297,1 +DA:298,1 +DA:300,1 +DA:303,1 +DA:305,1 +DA:307,1 +DA:310,1 +DA:313,2 +DA:314,2 +DA:317,1 +DA:319,2 +DA:320,0 +DA:321,1 +DA:322,1 +DA:323,1 +DA:325,1 +DA:328,1 +DA:329,1 +DA:332,1 +DA:333,1 +DA:334,1 +DA:337,1 +DA:340,1 +DA:341,2 +DA:342,0 +DA:344,0 +DA:345,0 +DA:346,0 +DA:349,0 +DA:350,0 +DA:354,1 +DA:355,1 +DA:356,2 +DA:357,1 +DA:358,1 +DA:361,0 +DA:362,0 +DA:366,1 +DA:368,1 +DA:370,1 +DA:372,1 +DA:376,1 +DA:378,1 +DA:380,1 +DA:382,1 +DA:386,1 +DA:388,5 +DA:389,5 +DA:391,1 +DA:393,1 +DA:396,1 +DA:397,1 +DA:402,1 +DA:404,1 +DA:406,1 +DA:412,1 +DA:414,1 +DA:416,1 +DA:422,1 +DA:424,1 +DA:426,1 +DA:432,1 +DA:434,1 +DA:436,1 +DA:445,1 +DA:447,1 +DA:449,1 +DA:451,1 +DA:455,1 +DA:457,5 +DA:458,5 +DA:460,1 +DA:462,1 +DA:465,1 +DA:466,1 +DA:471,1 +DA:473,1 +DA:475,1 +DA:481,1 +DA:483,1 +DA:485,1 +DA:491,1 +DA:494,1 +DA:496,1 +DA:501,1 +DA:502,3 +DA:506,1 +DA:508,1 +DA:510,1 +DA:514,1 +DA:516,1 +DA:518,1 +DA:522,1 +DA:525,1 +DA:527,1 +DA:528,1 +DA:533,1 +DA:535,1 +DA:539,1 +DA:541,1 +DA:543,1 +DA:545,1 +DA:547,1 +DA:553,1 +DA:555,1 +DA:557,1 +DA:559,1 +DA:561,1 +DA:563,1 +DA:565,1 +DA:574,1 +DA:575,1 +DA:576,1 +DA:577,1 +DA:578,3 +DA:579,2 +DA:582,0 +DA:590,1 +DA:592,1 +DA:593,1 +DA:594,1 +DA:595,3 +DA:597,1 +DA:598,1 +DA:599,2 +DA:600,1 +DA:601,2 +DA:602,1 +DA:605,1 +DA:606,1 +DA:607,3 +DA:609,1 +DA:610,1 +DA:613,1 +DA:614,3 +DA:618,1 +DA:619,0 +DA:620,0 +DA:622,0 +DA:623,0 +DA:624,0 +DA:628,1 +DA:629,1 +DA:630,3 +DA:632,1 +DA:636,1 +DA:644,1 +DA:645,2 +LF:250 +LH:221 +end_of_record +SF:lib\src\method_channel\type_conversion.dart +DA:11,1 +DA:12,1 +DA:13,2 +DA:14,1 +DA:15,1 +DA:16,1 +DA:17,1 +DA:18,1 +DA:19,1 +DA:20,2 +DA:21,2 +DA:25,1 +DA:26,2 +DA:29,1 +DA:30,2 +DA:32,1 +DA:34,0 +DA:39,2 +DA:41,1 +DA:44,0 +DA:52,1 +DA:53,1 +DA:54,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +LF:27 +LH:25 +end_of_record +SF:lib\src\types\camera_description.dart +DA:23,4 +DA:44,2 +DA:47,2 +DA:48,6 +DA:49,6 +DA:50,6 +DA:52,1 +DA:53,3 +DA:55,0 +DA:57,0 +DA:58,0 +LF:11 +LH:8 +end_of_record +SF:lib\src\types\camera_exception.dart +DA:8,3 +DA:18,1 +DA:19,3 +LF:3 +LH:3 +end_of_record +SF:lib\src\types\camera_image_data.dart +DA:23,2 +DA:52,3 +DA:81,3 +LF:3 +LH:3 +end_of_record +SF:lib\src\types\exposure_mode.dart +DA:15,3 +DA:17,3 +DA:19,3 +DA:25,3 +DA:27,3 +DA:29,3 +DA:32,0 +LF:7 +LH:6 +end_of_record +SF:lib\src\types\focus_mode.dart +DA:15,3 +DA:17,3 +DA:19,3 +DA:25,3 +DA:27,3 +DA:29,3 +DA:32,0 +LF:7 +LH:6 +end_of_record +SF:lib\src\types\image_format_group.dart +DA:47,2 +DA:49,2 +DA:51,2 +DA:53,2 +DA:55,2 +DA:57,2 +LF:6 +LH:6 +end_of_record +SF:lib\src\types\video_capture_options.dart +DA:13,2 +DA:19,1 +DA:42,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:54,0 +LF:11 +LH:2 +end_of_record diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index d2a7b6304ae2..73324a01196e 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -97,19 +97,20 @@ class MethodChannelCamera extends CameraPlatform { @override Future createCameraWithSettings( CameraDescription cameraDescription, - MediaSettings? mediaSettings, + MediaSettings mediaSettings, ) async { try { + final ResolutionPreset? resolutionPreset = mediaSettings.resolutionPreset; final Map? reply = await _channel .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': null != mediaSettings?.resolutionPreset - ? _serializeResolutionPreset(mediaSettings!.resolutionPreset!) + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(mediaSettings.resolutionPreset!) : null, - 'fps': mediaSettings?.fps, - 'videoBitrate': mediaSettings?.videoBitrate, - 'audioBitrate': mediaSettings?.audioBitrate, - 'enableAudio': mediaSettings?.enableAudio ?? false, + 'fps': mediaSettings.fps, + 'videoBitrate': mediaSettings.videoBitrate, + 'audioBitrate': mediaSettings.audioBitrate, + 'enableAudio': mediaSettings.enableAudio ?? false, }); return reply!['cameraId']! as int; diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index da1e7ada87b3..dfcc03975dd9 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -61,9 +61,11 @@ abstract class CameraPlatform extends PlatformInterface { ); /// Creates an uninitialized camera instance and returns the cameraId. + /// + /// Pass MediaSettings() for defaults Future createCameraWithSettings( CameraDescription cameraDescription, - MediaSettings? mediaSettings, + MediaSettings mediaSettings, ) { throw UnimplementedError('createCameraWithSettings() is not implemented.'); } diff --git a/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart b/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart index 79026f11c374..c54ff1857119 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart @@ -10,6 +10,7 @@ import 'resolution_preset.dart'; /// /// Used in [CameraPlatform.createCameraWithSettings]. /// Allows to tune recorded video parameters, such as resolution, frame rate, bitrate. +/// If [fps], [videoBitrate] and [audioBitrate] passed, they must be greater than zero. class MediaSettings { /// Creates a [MediaSettings]. const MediaSettings({ @@ -18,43 +19,65 @@ class MediaSettings { this.videoBitrate, this.audioBitrate, this.enableAudio = false, - }); + }) : assert(fps == null || fps > 0, 'fps must be null or greater than zero'), + assert(videoBitrate == null || videoBitrate > 0, + 'videoBitrate must be null or greater than zero'), + assert(audioBitrate == null || audioBitrate > 0, + 'audioBitrate must be null or greater than zero'); /// [ResolutionPreset] affect the quality of video recording and image capture. final ResolutionPreset? resolutionPreset; /// Rate at which frames should be captured by the camera in frames per second. + /// + /// Must be null or greater than zero final int? fps; /// The video encoding bit rate for recording. + /// + /// Must be null or greater than zero final int? videoBitrate; /// The audio encoding bit rate for recording. + /// + /// Must be null or greater than zero final int? audioBitrate; /// Controls audio presence in recorded video. final bool enableAudio; @override - bool operator ==(Object other) => - identical(this, other) || - other is MediaSettings && - runtimeType == other.runtimeType && - resolutionPreset == other.resolutionPreset && - fps == other.fps && - videoBitrate == other.videoBitrate && - audioBitrate == other.audioBitrate && - enableAudio == other.enableAudio; + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is MediaSettings && + resolutionPreset == other.resolutionPreset && + fps == other.fps && + videoBitrate == other.videoBitrate && + audioBitrate == other.audioBitrate && + enableAudio == other.enableAudio; + } @override - int get hashCode => - resolutionPreset.hashCode ^ - fps.hashCode ^ - videoBitrate.hashCode ^ - audioBitrate.hashCode ^ - enableAudio.hashCode; + int get hashCode => Object.hash( + resolutionPreset, + fps, + videoBitrate, + audioBitrate, + enableAudio, + ); @override - String toString() => - 'MediaSettings{resolutionPreset: $resolutionPreset, fps: $fps, videoBitrate: $videoBitrate, audioBitrate: $audioBitrate, enableAudio: $enableAudio}'; + String toString() { + return 'MediaSettings{' + 'resolutionPreset: $resolutionPreset, ' + 'fps: $fps, ' + 'videoBitrate: $videoBitrate, ' + 'audioBitrate: $audioBitrate, ' + 'enableAudio: $enableAudio}'; + } } diff --git a/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart b/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart index b3ea1d4e82c6..8a5e96edcf28 100644 --- a/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart +++ b/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart @@ -155,6 +155,26 @@ void main() { // Arrange final ExtendsCameraPlatform cameraPlatform = ExtendsCameraPlatform(); + // Act & Assert + expect( + () => cameraPlatform.createCamera( + const CameraDescription( + name: 'back', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0, + ), + ResolutionPreset.low, + ), + throwsUnimplementedError, + ); + }); + + test( + 'Default implementation of createCameraWithSettings() should throw unimplemented error', + () { + // Arrange + final ExtendsCameraPlatform cameraPlatform = ExtendsCameraPlatform(); + // Act & Assert expect( () => cameraPlatform.createCameraWithSettings( diff --git a/packages/camera/camera_platform_interface/test/types/media_settings_test.dart b/packages/camera/camera_platform_interface/test/types/media_settings_test.dart new file mode 100644 index 000000000000..f97cd1c59d19 --- /dev/null +++ b/packages/camera/camera_platform_interface/test/types/media_settings_test.dart @@ -0,0 +1,142 @@ +// 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 'package:camera_platform_interface/camera_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test( + 'MediaSettings non-parametrized constructor should have correct initial values', + () { + const MediaSettings settingsWithNoParameters = MediaSettings(); + + expect( + settingsWithNoParameters.resolutionPreset, + isNull, + reason: + 'MediaSettings constructor should have null default resolutionPreset', + ); + + expect( + settingsWithNoParameters.fps, + isNull, + reason: 'MediaSettings constructor should have null default fps', + ); + + expect( + settingsWithNoParameters.videoBitrate, + isNull, + reason: 'MediaSettings constructor should have null default videoBitrate', + ); + + expect( + settingsWithNoParameters.audioBitrate, + isNull, + reason: 'MediaSettings constructor should have null default audioBitrate', + ); + + expect( + settingsWithNoParameters.enableAudio, + isFalse, + reason: 'MediaSettings constructor should have false default enableAudio', + ); + }); + + test('MediaSettings fps should hold parameters', () { + const MediaSettings settings = MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 20, + videoBitrate: 128000, + audioBitrate: 32000, + enableAudio: true, + ); + + expect( + settings.resolutionPreset, + ResolutionPreset.low, + reason: + 'MediaSettings constructor should hold resolutionPreset parameter', + ); + + expect( + settings.fps, + 20, + reason: 'MediaSettings constructor should hold fps parameter', + ); + + expect( + settings.videoBitrate, + 128000, + reason: 'MediaSettings constructor should hold videoBitrate parameter', + ); + + expect( + settings.audioBitrate, + 32000, + reason: 'MediaSettings constructor should hold audioBitrate parameter', + ); + + expect( + settings.enableAudio, + true, + reason: 'MediaSettings constructor should hold enableAudio parameter', + ); + }); + + test('MediaSettings hash should be Object.hash of passed parameters', () { + const MediaSettings settings = MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 20, + videoBitrate: 128000, + audioBitrate: 32000, + enableAudio: true, + ); + + expect( + settings.hashCode, + Object.hash(ResolutionPreset.low, 20, 128000, 32000, true), + reason: + 'MediaSettings hash() should be equal to Object.hash of parameters', + ); + }); + + test('MediaSettings hash should be Object.hash of passed parameters', () { + const MediaSettings settings1 = MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 20, + videoBitrate: 128000, + audioBitrate: 32000, + enableAudio: true, + ); + + const MediaSettings settings1Copy = MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 20, + videoBitrate: 128000, + audioBitrate: 32000, + enableAudio: true, + ); + + const MediaSettings settings2 = MediaSettings( + resolutionPreset: ResolutionPreset.high, + fps: 30, + videoBitrate: 256000, + audioBitrate: 64000, + ); + + expect( + settings1 == settings1Copy, + isTrue, + reason: + 'MediaSettings == operator should return true for equal parameters', + ); + + expect( + settings1 == settings2, + isFalse, + reason: + 'MediaSettings == operator should return false for non-equal parameters', + ); + }); +}