From 03b30a3b9ffe2bb02aa8711fdee40a3fd6943cee Mon Sep 17 00:00:00 2001 From: ywatanabe-dev <102775353+ywatanabe-dev@users.noreply.github.com> Date: Tue, 28 May 2024 08:26:35 +0900 Subject: [PATCH 1/4] Add OpenSourceLicenses protocol --- .../ThetaClientFlutterPlugin.kt | 19 +++++++ .../SwiftThetaClientFlutterPlugin.swift | 27 +++++++++- flutter/lib/theta_client_flutter.dart | 8 +++ .../theta_client_flutter_method_channel.dart | 12 +++++ ...eta_client_flutter_platform_interface.dart | 4 ++ flutter/test/theta_client_flutter_test.dart | 26 ++++++++++ .../com/ricoh360/thetaclient/ThetaApi.kt | 19 +++++++ .../ricoh360/thetaclient/ThetaRepository.kt | 24 +++++++++ .../thetaclient/transferred/licenseApi.kt | 14 ++++++ .../repository/GetThetaLicenseTest.kt | 50 +++++++++++++++++++ .../resources/getThetaLicense/license.html | 4 ++ .../ThetaClientSdkModule.kt | 21 ++++++++ react-native/ios/ThetaClientReactNative.m | 3 ++ react-native/ios/ThetaClientReactNative.swift | 21 ++++++++ .../theta-repository/theta-license.test.ts | 27 ++++++++++ .../src/theta-repository/theta-repository.ts | 10 ++++ .../get-info-screen/get-info-screen.tsx | 47 +++++++++++++++-- 17 files changed, 329 insertions(+), 7 deletions(-) create mode 100644 kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/licenseApi.kt create mode 100644 kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/GetThetaLicenseTest.kt create mode 100644 kotlin-multiplatform/src/commonTest/resources/getThetaLicense/license.html create mode 100644 react-native/src/__tests__/theta-repository/theta-license.test.ts diff --git a/flutter/android/src/main/kotlin/com/ricoh360/thetaclient/theta_client_flutter/ThetaClientFlutterPlugin.kt b/flutter/android/src/main/kotlin/com/ricoh360/thetaclient/theta_client_flutter/ThetaClientFlutterPlugin.kt index 7e9c9f79d4..6aec8756ed 100644 --- a/flutter/android/src/main/kotlin/com/ricoh360/thetaclient/theta_client_flutter/ThetaClientFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/com/ricoh360/thetaclient/theta_client_flutter/ThetaClientFlutterPlugin.kt @@ -134,6 +134,12 @@ class ThetaClientFlutterPlugin : FlutterPlugin, MethodCallHandler { } } + "getThetaLicense" -> { + scope.launch { + getThetaLicense(result) + } + } + "getThetaState" -> { scope.launch { getThetaState(result) @@ -574,6 +580,19 @@ class ThetaClientFlutterPlugin : FlutterPlugin, MethodCallHandler { } } + suspend fun getThetaLicense(result: Result) { + if (thetaRepository == null) { + result.error(errorCode, messageNotInit, null) + return + } + try { + val response = thetaRepository!!.getThetaLicense() + result.success(response) + } catch (e: Exception) { + result.error(e.javaClass.simpleName, e.message, null) + } + } + suspend fun getThetaState(result: Result) { if (thetaRepository == null) { result.error(errorCode, messageNotInit, null) diff --git a/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift b/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift index bb330c312a..2130d26edb 100644 --- a/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift +++ b/flutter/ios/Classes/SwiftThetaClientFlutterPlugin.swift @@ -95,6 +95,8 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre getThetaModel(result: result) case "getThetaInfo": getThetaInfo(result: result) + case "getThetaLicense": + getThetaLicense(result: result) case "getThetaState": getThetaState(result: result) case "getLivePreview": @@ -330,16 +332,37 @@ public class SwiftThetaClientFlutterPlugin: NSObject, FlutterPlugin, FlutterStre } } - func getThetaState(result: @escaping FlutterResult) { + func getThetaLicense(result: @escaping FlutterResult) { if thetaRepository == nil { let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNotInit, details: nil) result(flutterError) return } - thetaRepository!.getThetaState { response, error in + thetaRepository!.getThetaLicense(completionHandler: { response, error in if let thetaError = error { let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: thetaError.localizedDescription, details: nil) result(flutterError) + } else { + if let response { + result(response) + } else { + let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNoResult, details: nil) + result(flutterError) + } + } + }) + } + + func getThetaState(result: @escaping FlutterResult) { + if thetaRepository == nil { + let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: SwiftThetaClientFlutterPlugin.messageNotInit, details: nil) + result(flutterError) + return + } + thetaRepository!.getThetaState { response, error in + if let error { + let flutterError = FlutterError(code: SwiftThetaClientFlutterPlugin.errorCode, message: error.localizedDescription, details: nil) + result(flutterError) } else { let resultState = convertResult(thetaState: response!) result(resultState) diff --git a/flutter/lib/theta_client_flutter.dart b/flutter/lib/theta_client_flutter.dart index c844dc46c9..c539f84d54 100644 --- a/flutter/lib/theta_client_flutter.dart +++ b/flutter/lib/theta_client_flutter.dart @@ -64,6 +64,14 @@ class ThetaClientFlutter { return ThetaClientFlutterPlatform.instance.getThetaInfo(); } + /// Acquires open source license information related to the camera. + /// + /// - @return HTML string of the license + /// - @throws If an error occurs in THETA. + Future getThetaLicense() { + return ThetaClientFlutterPlatform.instance.getThetaLicense(); + } + /// Get current state of Theta. /// /// - @return Mutable values representing Theta status. diff --git a/flutter/lib/theta_client_flutter_method_channel.dart b/flutter/lib/theta_client_flutter_method_channel.dart index 03abb1a1c5..e288d238fb 100644 --- a/flutter/lib/theta_client_flutter_method_channel.dart +++ b/flutter/lib/theta_client_flutter_method_channel.dart @@ -137,6 +137,18 @@ class MethodChannelThetaClientFlutter extends ThetaClientFlutterPlatform { return completer.future; } + @override + Future getThetaLicense() async { + var completer = Completer(); + try { + var result = await methodChannel.invokeMethod('getThetaLicense'); + completer.complete(result); + } catch (e) { + completer.completeError(e); + } + return completer.future; + } + @override Future getThetaState() async { var completer = Completer(); diff --git a/flutter/lib/theta_client_flutter_platform_interface.dart b/flutter/lib/theta_client_flutter_platform_interface.dart index 1799c791ca..a652b02eb4 100644 --- a/flutter/lib/theta_client_flutter_platform_interface.dart +++ b/flutter/lib/theta_client_flutter_platform_interface.dart @@ -52,6 +52,10 @@ abstract class ThetaClientFlutterPlatform extends PlatformInterface { throw UnimplementedError('getThetaInfo() has not been implemented.'); } + Future getThetaLicense() { + throw UnimplementedError('getThetaLicense() has not been implemented.'); + } + Future getThetaState() { throw UnimplementedError('getThetaInfo() has not been implemented.'); } diff --git a/flutter/test/theta_client_flutter_test.dart b/flutter/test/theta_client_flutter_test.dart index ee74810059..727761e287 100644 --- a/flutter/test/theta_client_flutter_test.dart +++ b/flutter/test/theta_client_flutter_test.dart @@ -29,6 +29,11 @@ class MockThetaClientFlutterPlatform return onGetThetaInfo(); } + @override + Future getThetaLicense() { + return onGetThetaLicense(); + } + @override Future getThetaState() { return onGetThetaState(); @@ -410,6 +415,7 @@ Future Function() onCallInitialize = Future.value; Future Function() onCallIsInitialized = Future.value; Future Function() onGetThetaModel = Future.value; Future Function() onGetThetaInfo = Future.value; +Future Function() onGetThetaLicense = Future.value; Future Function() onGetThetaState = Future.value; Future Function() onCallGetLivePreview = Future.value; Future Function() onCallListFiles = Future.value; @@ -583,6 +589,26 @@ void main() { expect(thetaInfo.thetaModel, thetaModel); }); + test('getThetaLicense', () async { + ThetaClientFlutter thetaClientPlugin = ThetaClientFlutter(); + MockThetaClientFlutterPlatform fakePlatform = + MockThetaClientFlutterPlatform(); + ThetaClientFlutterPlatform.instance = fakePlatform; + + var license = """ + + + + + """; + onGetThetaLicense = () { + return Future.value(license); + }; + + var result = await thetaClientPlugin.getThetaLicense(); + expect(result, license); + }); + test('getThetaState', () async { ThetaClientFlutter thetaClientPlugin = ThetaClientFlutter(); MockThetaClientFlutterPlatform fakePlatform = diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaApi.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaApi.kt index b5c6a7c2c8..1e0d8a6d46 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaApi.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaApi.kt @@ -70,6 +70,25 @@ internal object ThetaApi { } } + /** + * Call [/legal-information/open-source-licenses](https://github.com/ricohapi/theta-api-specs/blob/main/theta-web-api-v2.1/protocols/open_source_licenses.md) + * @param endpoint Endpoint of Theta web API + * @return response of /legal-information/open-source-licenses API + * @exception java.net.ConnectException can not connect to target endpoint + * @exception io.ktor.client.network.sockets.ConnectTimeoutException timeout to connect target endpoint + * @exception io.ktor.client.plugins.RedirectResponseException target response 3xx status + * @exception io.ktor.client.plugins.ClientRequestException target response 4xx status + * @exception io.ktor.client.plugins.ServerResponseException target response 5xx status + */ + @Throws(Throwable::class) + suspend fun callLicenseApi( + endpoint: String, + ): HttpResponse { + return syncExecutor(requestSemaphore, ApiClient.timeout.requestTimeout) { + httpClient.get(getApiUrl(endpoint, LicenseApi.PATH)) + } + } + /** * Call [/osc/state](https://github.com/ricohapi/theta-api-specs/blob/main/theta-web-api-v2.1/protocols/state.md) * @param endpoint Endpoint of Theta web API diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt index 4d40ed0a3c..697a8e9003 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt @@ -401,6 +401,30 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? } } + /** + * Acquires open source license information related to the camera. + * + * @return HTML string of the license + * @exception ThetaWebApiException If an error occurs in THETA. + * @exception NotConnectedException + */ + @Throws(Throwable::class) + suspend fun getThetaLicense(): String { + try { + val response = ThetaApi.callLicenseApi(endpoint) + if (response.status != HttpStatusCode.OK) { + throw ThetaWebApiException(response.toString()) + } + return response.bodyAsText() + } catch (e: JsonConvertException) { + throw ThetaWebApiException(e.message ?: e.toString()) + } catch (e: ResponseException) { + throw ThetaWebApiException(e.message ?: e.toString()) + } catch (e: Exception) { + throw NotConnectedException(e.message ?: e.toString()) + } + } + /** * Get current state of Theta. * diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/licenseApi.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/licenseApi.kt new file mode 100644 index 0000000000..36ec0b01c0 --- /dev/null +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/transferred/licenseApi.kt @@ -0,0 +1,14 @@ +/* + * [/legal-information/open-source-licenses](https://github.com/ricohapi/theta-api-specs/blob/main/theta-web-api-v2.1/protocols/open_source_licenses.md) + */ +package com.ricoh360.thetaclient.transferred + +import io.ktor.http.HttpMethod + +/** + * open-source-licenses api request + */ +internal object LicenseApi { + const val PATH = "/legal-information/open-source-licenses" + val METHOD = HttpMethod.Get +} diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/GetThetaLicenseTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/GetThetaLicenseTest.kt new file mode 100644 index 0000000000..36e77de6e6 --- /dev/null +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/GetThetaLicenseTest.kt @@ -0,0 +1,50 @@ +package com.ricoh360.thetaclient.repository + +import com.goncalossilva.resources.Resource +import com.ricoh360.thetaclient.MockApiClient +import com.ricoh360.thetaclient.ThetaRepository +import io.ktor.http.HttpStatusCode +import io.ktor.utils.io.ByteReadChannel +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.ExperimentalSerializationApi +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@OptIn(ExperimentalSerializationApi::class, ExperimentalCoroutinesApi::class) +class GetThetaLicenseTest { + private val endpoint = "http://192.168.1.1:80/" + + @BeforeTest + fun setup() { + MockApiClient.status = HttpStatusCode.OK + } + + @AfterTest + fun teardown() { + MockApiClient.status = HttpStatusCode.OK + } + + @Test + fun getPluginLicenseTest() = runTest { + MockApiClient.onRequest = { request -> + // check request + assertEquals(request.url.encodedPath, "/legal-information/open-source-licenses", "request path") + ByteReadChannel(Resource("src/commonTest/resources/getThetaLicense/license.html").readText()) + } + + val thetaRepository = ThetaRepository(endpoint) + var html = "" + kotlin.runCatching { + html = thetaRepository.getThetaLicense() + }.onSuccess { + assertTrue(html.startsWith(""), "getThetaLicense()") + }.onFailure { + println(it.toString()) + assertTrue(false, "getThetaLicense()") + } + } +} diff --git a/kotlin-multiplatform/src/commonTest/resources/getThetaLicense/license.html b/kotlin-multiplatform/src/commonTest/resources/getThetaLicense/license.html new file mode 100644 index 0000000000..1895d20345 --- /dev/null +++ b/kotlin-multiplatform/src/commonTest/resources/getThetaLicense/license.html @@ -0,0 +1,4 @@ + + + + diff --git a/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/ThetaClientSdkModule.kt b/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/ThetaClientSdkModule.kt index e7bd03f4d1..351b165a8c 100644 --- a/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/ThetaClientSdkModule.kt +++ b/react-native/android/src/main/java/com/ricoh360/thetaclientreactnative/ThetaClientSdkModule.kt @@ -205,6 +205,27 @@ class ThetaClientReactNativeModule( } } + /** + * getPluginLicense - acquires open source license information related to the camera. + * @param promise promise to set result + */ + @ReactMethod + fun getThetaLicense(promise: Promise) { + val theta = theta + if (theta == null) { + promise.reject(Exception(messageNotInit)) + return + } + launch { + try { + val result = theta.getThetaLicense() + promise.resolve(result) + } catch (t: Throwable) { + promise.reject(t) + } + } + } + /** * getThetaState - retrieve ThetaState from THETA via repository * @param promise promise to set result diff --git a/react-native/ios/ThetaClientReactNative.m b/react-native/ios/ThetaClientReactNative.m index a5a00bad25..b30949bdce 100644 --- a/react-native/ios/ThetaClientReactNative.m +++ b/react-native/ios/ThetaClientReactNative.m @@ -21,6 +21,9 @@ @interface RCT_EXTERN_MODULE(ThetaClientReactNative, NSObject) RCT_EXTERN_METHOD(getThetaInfo:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(getThetaLicense:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(getThetaState:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) diff --git a/react-native/ios/ThetaClientReactNative.swift b/react-native/ios/ThetaClientReactNative.swift index 7783640ed5..d5e4d036a3 100644 --- a/react-native/ios/ThetaClientReactNative.swift +++ b/react-native/ios/ThetaClientReactNative.swift @@ -210,6 +210,27 @@ class ThetaClientReactNative: RCTEventEmitter { } } + @objc(getThetaLicense:withRejecter:) + func getThetaLicense( + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock + ) { + guard let thetaRepository else { + reject(ERROR_CODE_ERROR, MESSAGE_NOT_INIT, nil) + return + } + + thetaRepository.getThetaLicense() { response, error in + if let error { + reject(ERROR_CODE_ERROR, error.localizedDescription, error) + } else if let response { + resolve(response) + } else { + reject(ERROR_CODE_ERROR, MESSAGE_NO_RESULT, nil) + } + } + } + @objc(getThetaState:withRejecter:) func getThetaState( resolve: @escaping RCTPromiseResolveBlock, diff --git a/react-native/src/__tests__/theta-repository/theta-license.test.ts b/react-native/src/__tests__/theta-repository/theta-license.test.ts new file mode 100644 index 0000000000..3bfd9d443d --- /dev/null +++ b/react-native/src/__tests__/theta-repository/theta-license.test.ts @@ -0,0 +1,27 @@ +import { NativeModules } from 'react-native'; +import { getThetaLicense } from '../../theta-repository'; + +describe('getThetaLicense', () => { + const thetaClient = NativeModules.ThetaClientReactNative; + + beforeEach(() => { + thetaClient.getThetaLicense = jest.fn(); + jest.clearAllMocks(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('getThetaLicense', async () => { + const license = '\n \n \n'; + jest.mocked(thetaClient.getThetaLicense).mockImplementation( + jest.fn(async () => { + return license; + }) + ); + + const html = await getThetaLicense(); + expect(html).toBe(license); + }); +}); diff --git a/react-native/src/theta-repository/theta-repository.ts b/react-native/src/theta-repository/theta-repository.ts index fc90d9fde4..676e6fe5cf 100644 --- a/react-native/src/theta-repository/theta-repository.ts +++ b/react-native/src/theta-repository/theta-repository.ts @@ -311,6 +311,16 @@ export function getThetaInfo(): Promise { return ThetaClientReactNative.getThetaInfo(); } +/** + * Acquires open source license information related to the camera. + * + * @function getThetaLicense + * @return Promise of string result, HTML string of the license. + */ +export function getThetaLicense(): Promise { + return ThetaClientReactNative.getThetaLicense(); +} + /** * Get current state of Theta. * diff --git a/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx b/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx index 211f317b44..0176daf828 100644 --- a/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx +++ b/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx @@ -5,6 +5,7 @@ import styles from './styles'; import { getPluginOrders, getThetaInfo, + getThetaLicense, getThetaState, listAccessPoints, listPlugins, @@ -32,7 +33,35 @@ const commandList: CommandItem[] = [ const result = await getThetaInfo(); return `OK getThetaInfo()\n${getJsonString(result)}`; } catch (error) { - return JSON.stringify(error); + return error instanceof Error + ? error.toString() + : 'An error occurred.'; + } + }, + }, + }, + { + name: 'getThetaLicense', + value: { + commandFunction: async () => { + try { + const result = await getThetaLicense(); + const maxChars = 200; + return ( + `OK getThetaLicense()\nlength:${result.length}\n\n${result.slice( + 0, + maxChars + )}\n\n` + + (result.length > maxChars + ? `(The remaining ${ + result.length - maxChars + } characters were omitted.)` + : '') + ); + } catch (error) { + return error instanceof Error + ? error.toString() + : 'An error occurred.'; } }, }, @@ -45,7 +74,9 @@ const commandList: CommandItem[] = [ const result = await getThetaState(); return `OK getThetaState()\n${getJsonString(result)}`; } catch (error) { - return JSON.stringify(error); + return error instanceof Error + ? error.toString() + : 'An error occurred.'; } }, }, @@ -58,7 +89,9 @@ const commandList: CommandItem[] = [ const result = await listAccessPoints(); return `OK listAccessPoints()\n${getJsonString(result)}`; } catch (error) { - return JSON.stringify(error); + return error instanceof Error + ? error.toString() + : 'An error occurred.'; } }, }, @@ -71,7 +104,9 @@ const commandList: CommandItem[] = [ const result = await listPlugins(); return `OK listPlugins()\n${getJsonString(result)}`; } catch (error) { - return JSON.stringify(error); + return error instanceof Error + ? error.toString() + : 'An error occurred.'; } }, }, @@ -84,7 +119,9 @@ const commandList: CommandItem[] = [ const result = await getPluginOrders(); return `OK getPluginOrders()\n${getJsonString(result)}`; } catch (error) { - return JSON.stringify(error); + return error instanceof Error + ? error.toString() + : 'An error occurred.'; } }, }, From 2b34ab117484ceebffa0dbebe6bcf0d58f96f3f2 Mon Sep 17 00:00:00 2001 From: osakila Date: Mon, 1 Jul 2024 16:16:27 +0900 Subject: [PATCH 2/4] Add video file format of SC2 --- flutter/lib/capture/capture.dart | 17 ++-- flutter/lib/capture/capture_builder.dart | 29 +++++-- flutter/lib/options/file_format.dart | 14 ++++ flutter/test/enum_name_test.dart | 2 + .../test/options/option_file_format_test.dart | 2 + .../ricoh360/thetaclient/ThetaRepository.kt | 40 +++++++++ .../ricoh360/thetaclient/capture/Capture.kt | 83 +++++++++++++++++++ .../thetaclient/capture/PhotoCapture.kt | 33 ++------ .../thetaclient/capture/VideoCapture.kt | 12 +-- .../thetaclient/capture/PhotoCaptureTest.kt | 27 ++++-- .../thetaclient/capture/VideoCaptureTest.kt | 38 +++++++-- .../repository/options/FileFormatTest.kt | 2 + react-native/package.json | 2 +- .../options/option-file-format.test.tsx | 4 + react-native/src/capture/capture.ts | 15 ++++ react-native/src/capture/photo-capture.ts | 20 +---- .../options/option-file-format.ts | 4 + 17 files changed, 265 insertions(+), 79 deletions(-) diff --git a/flutter/lib/capture/capture.dart b/flutter/lib/capture/capture.dart index 0c32a2f97e..77b202e5fd 100644 --- a/flutter/lib/capture/capture.dart +++ b/flutter/lib/capture/capture.dart @@ -52,8 +52,18 @@ class Capture { Capture(this._options); } +/// Common PhotoCapture class +class PhotoCaptureBase extends Capture { + PhotoCaptureBase(super.options); + + /// Get photo file format. + PhotoFileFormatEnum? getFileFormat() { + return _options[TagNameEnum.photoFileFormat.rawValue]; + } +} + /// Capture of Photo -class PhotoCapture extends Capture { +class PhotoCapture extends PhotoCaptureBase { PhotoCapture(super.options); /// Get image processing filter. @@ -61,11 +71,6 @@ class PhotoCapture extends Capture { return _options[OptionNameEnum.filter.rawValue]; } - /// Get photo file format. - PhotoFileFormatEnum? getFileFormat() { - return _options[TagNameEnum.photoFileFormat.rawValue]; - } - /// Get preset mode of Theta SC2 and Theta SC2 for business. PresetEnum? getPreset() { return _options[OptionNameEnum.preset.rawValue]; diff --git a/flutter/lib/capture/capture_builder.dart b/flutter/lib/capture/capture_builder.dart index 6c03528da3..cdc1e02050 100644 --- a/flutter/lib/capture/capture_builder.dart +++ b/flutter/lib/capture/capture_builder.dart @@ -82,13 +82,17 @@ class CaptureBuilder { } } -/// Builder of [PhotoCapture] -class PhotoCaptureBuilder extends CaptureBuilder { +/// Common PhotoCaptureBuilder class +class PhotoCaptureBuilderBase extends CaptureBuilder { /// Set photo file format. - PhotoCaptureBuilder setFileFormat(PhotoFileFormatEnum fileFormat) { + T setFileFormat(PhotoFileFormatEnum fileFormat) { _options[TagNameEnum.photoFileFormat.rawValue] = fileFormat; - return this; + return this as T; } +} + +/// Builder of [PhotoCapture] +class PhotoCaptureBuilder extends PhotoCaptureBuilderBase { /// Set image processing filter. PhotoCaptureBuilder setFilter(FilterEnum filter) { @@ -106,7 +110,8 @@ class PhotoCaptureBuilder extends CaptureBuilder { Future build() async { var completer = Completer(); try { - await ThetaClientFlutterPlatform.instance.buildPhotoCapture(_options); + await ThetaClientFlutterPlatform.instance + .buildPhotoCapture(_options); completer.complete(PhotoCapture(_options)); } catch (e) { completer.completeError(e); @@ -456,6 +461,13 @@ enum VideoFileFormatEnum { /// For RICOH THETA Z1 or V video_2K(FileFormatEnum.video_2K), + /// Video File format. + /// type: mp4 + /// size: 1920 x 960 + /// + /// For RICOH THETA SC2 or SC2 for business + video_2KnoCodec(FileFormatEnum.video_2KnoCodec), + /// Video File format. /// type: mp4 /// size: 3840 x 1920 @@ -464,6 +476,13 @@ enum VideoFileFormatEnum { /// For RICOH THETA Z1 or V video_4K(FileFormatEnum.video_4K), + /// Video File format. + /// type: mp4 + /// size: 3840 x 1920 + /// + /// For RICOH THETA SC2 or SC2 for business + video_4KnoCodec(FileFormatEnum.video_4KnoCodec), + /// Video File format. /// type: mp4 /// size: 1920 x 960 diff --git a/flutter/lib/options/file_format.dart b/flutter/lib/options/file_format.dart index 958a4a8472..49b840e637 100644 --- a/flutter/lib/options/file_format.dart +++ b/flutter/lib/options/file_format.dart @@ -67,6 +67,13 @@ enum FileFormatEnum { /// For RICOH THETA Z1 or V video_2K('VIDEO_2K'), + /// Video File format. + /// type: mp4 + /// size: 1920 x 960 + /// + /// For RICOH THETA SC2 or SC2 for business + video_2KnoCodec('VIDEO_2K_NO_CODEC'), + /// Video File format. /// type: mp4 /// size: 3840 x 1920 @@ -75,6 +82,13 @@ enum FileFormatEnum { /// For RICOH THETA Z1 or V video_4K('VIDEO_4K'), + /// Video File format. + /// type: mp4 + /// size: 3840 x 1920 + /// + /// For RICOH THETA SC2 or SC2 for business + video_4KnoCodec('VIDEO_4K_NO_CODEC'), + /// Video File format. /// type: mp4 /// size: 1920 x 960 diff --git a/flutter/test/enum_name_test.dart b/flutter/test/enum_name_test.dart index 57f30fda3c..7f720ae390 100644 --- a/flutter/test/enum_name_test.dart +++ b/flutter/test/enum_name_test.dart @@ -574,7 +574,9 @@ void main() { [VideoFileFormatEnum.videoHD, 'VIDEO_HD'], [VideoFileFormatEnum.videoFullHD, 'VIDEO_FULL_HD'], [VideoFileFormatEnum.video_2K, 'VIDEO_2K'], + [VideoFileFormatEnum.video_2KnoCodec, 'VIDEO_2K_NO_CODEC'], [VideoFileFormatEnum.video_4K, 'VIDEO_4K'], + [VideoFileFormatEnum.video_4KnoCodec, 'VIDEO_4K_NO_CODEC'], [VideoFileFormatEnum.video_2K_30F, 'VIDEO_2K_30F'], [VideoFileFormatEnum.video_2K_60F, 'VIDEO_2K_60F'], [VideoFileFormatEnum.video_2_7K_1F, 'VIDEO_2_7K_1F'], diff --git a/flutter/test/options/option_file_format_test.dart b/flutter/test/options/option_file_format_test.dart index 3a1e922b00..a8b056cec8 100644 --- a/flutter/test/options/option_file_format_test.dart +++ b/flutter/test/options/option_file_format_test.dart @@ -31,11 +31,13 @@ void main() { [FileFormatEnum.videoHD, 'VIDEO_HD'], [FileFormatEnum.videoFullHD, 'VIDEO_FULL_HD'], [FileFormatEnum.video_2K, 'VIDEO_2K'], + [FileFormatEnum.video_2KnoCodec, 'VIDEO_2K_NO_CODEC'], [FileFormatEnum.video_2_7K_1F, 'VIDEO_2_7K_1F'], [FileFormatEnum.video_2_7K_2F, 'VIDEO_2_7K_2F'], [FileFormatEnum.video_3_6K_1F, 'VIDEO_3_6K_1F'], [FileFormatEnum.video_3_6K_2F, 'VIDEO_3_6K_2F'], [FileFormatEnum.video_4K, 'VIDEO_4K'], + [FileFormatEnum.video_4KnoCodec, 'VIDEO_4K_NO_CODEC'], [FileFormatEnum.video_2K_30F, 'VIDEO_2K_30F'], [FileFormatEnum.video_2K_60F, 'VIDEO_2K_60F'], [FileFormatEnum.video_4K_30F, 'VIDEO_4K_30F'], diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt index 697a8e9003..e3f03814d5 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt @@ -3246,6 +3246,16 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_2K(FileFormatTypeEnum.MP4, 1920, 960, "H.264/MPEG-4 AVC", null), + /** + * Video File format. + * + * type: mp4 + * size: 1920 x 960 + * + * For RICOH THETA SC2 or SC2 for business + */ + VIDEO_2K_NO_CODEC(FileFormatTypeEnum.MP4, 1920, 960, null, null), + /** * Video File format. * @@ -3257,6 +3267,16 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_4K(FileFormatTypeEnum.MP4, 3840, 1920, "H.264/MPEG-4 AVC", null), + /** + * Video File format. + * + * type: mp4 + * size: 3840 x 1920 + * + * For RICOH THETA SC2 or SC2 for business + */ + VIDEO_4K_NO_CODEC(FileFormatTypeEnum.MP4, 3840, 1920, null, null), + /** * Video File format. * @@ -3595,6 +3615,16 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_2K(FileFormatEnum.VIDEO_2K), + /** + * Video File format. + * + * type: mp4 + * size: 1920 x 960 + * + * For RICOH THETA SC2 or SC2 for business + */ + VIDEO_2K_NO_CODEC(FileFormatEnum.VIDEO_2K_NO_CODEC), + /** * Video File format. * @@ -3606,6 +3636,16 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_4K(FileFormatEnum.VIDEO_4K), + /** + * Video File format. + * + * type: mp4 + * size: 3840 x 1920 + * + * For RICOH THETA SC2 or SC2 for business + */ + VIDEO_4K_NO_CODEC(FileFormatEnum.VIDEO_4K_NO_CODEC), + /** * Video File format. * diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/Capture.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/Capture.kt index 0d345d751b..e4bea546aa 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/Capture.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/Capture.kt @@ -13,6 +13,28 @@ import io.ktor.client.statement.HttpResponse */ abstract class Capture internal constructor(internal val options: Options) { + /** + * Get photo file format. + * + * @return Photo file format + */ + internal fun getPhotoFileFormat() = options.fileFormat?.let { fileFormat -> + ThetaRepository.FileFormatEnum.get(fileFormat).let { + ThetaRepository.PhotoFileFormatEnum.get(it) + } + } + + /** + * Get video file format. + * + * @return Video file format + */ + internal fun getVideoFileFormat() = options.fileFormat?.let { it -> + ThetaRepository.FileFormatEnum.get(it).let { + ThetaRepository.VideoFileFormatEnum.get(it) + } + } + /** * Get aperture value. * @@ -112,6 +134,30 @@ abstract class Capture internal constructor(internal val options: Options) { abstract class Builder { internal val options = Options() + /** + * Set photo file format. + * + * @param fileFormat Photo file format + * @return Builder + */ + internal fun setPhotoFileFormat(fileFormat: ThetaRepository.PhotoFileFormatEnum): T { + options.fileFormat = fileFormat.fileFormat.toMediaFileFormat() + @Suppress("UNCHECKED_CAST") + return this as T + } + + /** + * Set video file format. + * + * @param fileFormat Video file format + * @return Builder + */ + internal fun setVideoFileFormat(fileFormat: ThetaRepository.VideoFileFormatEnum): T { + options.fileFormat = fileFormat.fileFormat.toMediaFileFormat() + @Suppress("UNCHECKED_CAST") + return this as T + } + /** * Set aperture value. * @@ -256,3 +302,40 @@ internal suspend fun isCanceledShootingResponse(httpResponse: HttpResponse): Boo } return false } + +/* + * Common PhotoCapture class + * + * @property options option of take a picture + */ +abstract class PhotoCaptureBase internal constructor( + options: Options, +) : Capture(options) { + /** + * Get photo file format. + * + * @return Photo file format + */ + fun getFileFormat() = getPhotoFileFormat() + + /* + * Builder of PhotoCaptureBase + * + * @property endpoint URL of Theta web API endpoint + * @property cameraModel Camera model info. + */ + abstract class Builder internal constructor( + ) : Capture.Builder() { + /** + * Set photo file format. + * + * @param fileFormat Photo file format + * @return Builder + */ + fun setFileFormat(fileFormat: ThetaRepository.PhotoFileFormatEnum): T { + setPhotoFileFormat(fileFormat) + @Suppress("UNCHECKED_CAST") + return this as T + } + } +} diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/PhotoCapture.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/PhotoCapture.kt index 2bd608332f..86a5950dba 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/PhotoCapture.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/PhotoCapture.kt @@ -14,7 +14,10 @@ import kotlinx.coroutines.* * @property endpoint URL of Theta web API endpoint * @property options option of take a picture */ -class PhotoCapture private constructor(private val endpoint: String, options: Options) : Capture(options) { +class PhotoCapture private constructor( + private val endpoint: String, + options: Options, + ) : PhotoCaptureBase(options) { private val scope = CoroutineScope(Dispatchers.Default) @@ -25,17 +28,6 @@ class PhotoCapture private constructor(private val endpoint: String, options: Op */ fun getFilter() = options._filter?.let { ThetaRepository.FilterEnum.get(it) } - /** - * Get photo file format. - * - * @return Photo file format - */ - fun getFileFormat() = options.fileFormat?.let { it -> - ThetaRepository.FileFormatEnum.get(it)?.let { - ThetaRepository.PhotoFileFormatEnum.get(it) - } - } - /** * Get preset mode of Theta SC2 and Theta SC2 for business. * @@ -127,8 +119,10 @@ class PhotoCapture private constructor(private val endpoint: String, options: Op * @property endpoint URL of Theta web API endpoint * @property cameraModel Camera model info. */ - class Builder internal constructor(private val endpoint: String, private val cameraModel: ThetaRepository.ThetaModel? = null) : Capture.Builder() { - + class Builder internal constructor( + private val endpoint: String, + private val cameraModel: ThetaRepository.ThetaModel? = null + ) : PhotoCaptureBase.Builder() { internal fun isPreset(): Boolean { return options._preset != null && (cameraModel == ThetaRepository.ThetaModel.THETA_SC2 || cameraModel == ThetaRepository.ThetaModel.THETA_SC2_B) } @@ -186,17 +180,6 @@ class PhotoCapture private constructor(private val endpoint: String, options: Op return this } - /** - * Set photo file format. - * - * @param fileFormat Photo file format - * @return Builder - */ - fun setFileFormat(fileFormat: ThetaRepository.PhotoFileFormatEnum): Builder { - options.fileFormat = fileFormat.fileFormat.toMediaFileFormat() - return this - } - /** * Set preset mode of Theta SC2 and Theta SC2 for business. * diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/VideoCapture.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/VideoCapture.kt index 96ec44e310..328c3dc7c5 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/VideoCapture.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/capture/VideoCapture.kt @@ -40,11 +40,7 @@ class VideoCapture private constructor(private val endpoint: String, options: Op * * @return Video file format */ - fun getFileFormat() = options.fileFormat?.let { it -> - ThetaRepository.FileFormatEnum.get(it)?.let { - ThetaRepository.VideoFileFormatEnum.get(it) - } - } + fun getFileFormat() = getVideoFileFormat() // TODO: Add get video option property @@ -233,10 +229,8 @@ class VideoCapture private constructor(private val endpoint: String, options: Op * @param fileFormat Video file format * @return Builder */ - fun setFileFormat(fileFormat: ThetaRepository.VideoFileFormatEnum): Builder { - options.fileFormat = fileFormat.fileFormat.toMediaFileFormat() - return this - } + fun setFileFormat(fileFormat: ThetaRepository.VideoFileFormatEnum): Builder = + setVideoFileFormat(fileFormat) // TODO: Add set video option property } diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/PhotoCaptureTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/PhotoCaptureTest.kt index e60b9daa68..2c2eef52fc 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/PhotoCaptureTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/PhotoCaptureTest.kt @@ -5,10 +5,10 @@ import com.ricoh360.thetaclient.CheckRequest import com.ricoh360.thetaclient.MockApiClient import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.transferred.CaptureMode +import com.ricoh360.thetaclient.transferred.MediaFileFormat +import com.ricoh360.thetaclient.transferred.MediaType import io.ktor.client.network.sockets.* -import io.ktor.client.request.* import io.ktor.http.* -import io.ktor.http.content.* import io.ktor.utils.io.* import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -332,7 +332,14 @@ class PhotoCaptureTest { @Test fun settingFileFormatTest() = runTest { // setup - val fileFormatList = ThetaRepository.PhotoFileFormatEnum.values() + val valueList = listOf( + Pair(ThetaRepository.PhotoFileFormatEnum.IMAGE_2K, MediaFileFormat(MediaType.JPEG, 2048, 1024, null, null)), + Pair(ThetaRepository.PhotoFileFormatEnum.IMAGE_5K, MediaFileFormat(MediaType.JPEG, 5376, 2688, null, null)), + Pair(ThetaRepository.PhotoFileFormatEnum.IMAGE_6_7K, MediaFileFormat(MediaType.JPEG, 6720, 3360, null, null)), + Pair(ThetaRepository.PhotoFileFormatEnum.RAW_P_6_7K, MediaFileFormat(MediaType.RAW, 6720, 3360, null, null)), + Pair(ThetaRepository.PhotoFileFormatEnum.IMAGE_5_5K, MediaFileFormat(MediaType.JPEG, 5504, 2752, null, null)), + Pair(ThetaRepository.PhotoFileFormatEnum.IMAGE_11K, MediaFileFormat(MediaType.JPEG, 11008, 5504, null, null)), + ) val responseArray = arrayOf( Resource("src/commonTest/resources/setOptions/set_options_done.json").readText(), @@ -353,7 +360,7 @@ class PhotoCaptureTest { 1 -> { CheckRequest.checkSetOptions( request = request, - fileFormat = fileFormatList[fileFormatIndex].fileFormat.toMediaFileFormat() + fileFormat = valueList[fileFormatIndex].second ) } } @@ -364,15 +371,17 @@ class PhotoCaptureTest { // execute val thetaRepository = ThetaRepository(endpoint) - fileFormatList.forEach { - val photoCapture = thetaRepository.getPhotoCaptureBuilder() - .setFileFormat(it) - .build() + assertEquals(valueList.size, ThetaRepository.PhotoFileFormatEnum.entries.size) + valueList.forEach { + val builder = thetaRepository.getPhotoCaptureBuilder() + builder.setFileFormat(it.first) + assertEquals(builder.options.fileFormat, it.second, "fileFormat ${it.second}") + val photoCapture = builder.build() // check result assertEquals( photoCapture.getFileFormat(), - it, + it.first, "set option fileFormat $fileFormatIndex" ) diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt index 623f45fe8d..5d3123584e 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt @@ -5,6 +5,8 @@ import com.ricoh360.thetaclient.CheckRequest import com.ricoh360.thetaclient.MockApiClient import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.transferred.CaptureMode +import com.ricoh360.thetaclient.transferred.MediaFileFormat +import com.ricoh360.thetaclient.transferred.MediaType import io.ktor.client.network.sockets.* import io.ktor.http.* import io.ktor.utils.io.* @@ -12,7 +14,6 @@ import kotlinx.coroutines.* import kotlinx.coroutines.test.runTest import kotlin.test.* -@OptIn(ExperimentalCoroutinesApi::class) class VideoCaptureTest { private val endpoint = "http://192.168.1.1:80/" @@ -323,7 +324,28 @@ class VideoCaptureTest { @Test fun settingFileFormatTest() = runTest { // setup - val valueList = ThetaRepository.VideoFileFormatEnum.entries.toTypedArray() + val valueList = listOf( + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_HD, MediaFileFormat(MediaType.MP4, 1280, 720, null, null)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_FULL_HD, MediaFileFormat(MediaType.MP4, 1920, 1080, null, null)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2K, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", null)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2K_NO_CODEC, MediaFileFormat(MediaType.MP4, 1920, 960, null, null)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", null)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_NO_CODEC, MediaFileFormat(MediaType.MP4, 3840, 1920, null, null)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2K_30F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 30)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2K_60F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 60)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_1F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 1)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_2F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_3_6K_1F, MediaFileFormat(MediaType.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 1)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_3_6K_2F, MediaFileFormat(MediaType.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_30F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 30)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_60F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 60)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_2F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_5F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 5)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_30F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 30)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_7K_2F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_7K_5F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 5)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_7K_10F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 10)), + ) val responseArray = arrayOf( Resource("src/commonTest/resources/setOptions/set_options_done.json").readText(), @@ -344,7 +366,7 @@ class VideoCaptureTest { 1 -> { CheckRequest.checkSetOptions( request = request, - fileFormat = valueList[valueIndex].fileFormat.toMediaFileFormat() + fileFormat = valueList[valueIndex].second ) } } @@ -355,15 +377,17 @@ class VideoCaptureTest { // execute val thetaRepository = ThetaRepository(endpoint) + assertEquals(valueList.size, ThetaRepository.VideoFileFormatEnum.entries.size) valueList.forEach { - val videoCapture = thetaRepository.getVideoCaptureBuilder() - .setFileFormat(it) - .build() + val builder = thetaRepository.getVideoCaptureBuilder() + builder.setFileFormat(it.first) + assertEquals(builder.options.fileFormat, it.second, "fileFormat ${it.second}") + val videoCapture = builder.build() // check result assertEquals( videoCapture.getFileFormat(), - it, + it.first, "set option fileFormat $valueIndex" ) diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt index 1cdd6e67bc..42bfc9e30b 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt @@ -112,7 +112,9 @@ class FileFormatTest { Pair(ThetaRepository.FileFormatEnum.VIDEO_HD, MediaFileFormat(MediaType.MP4, 1280, 720, null, null)), Pair(ThetaRepository.FileFormatEnum.VIDEO_FULL_HD, MediaFileFormat(MediaType.MP4, 1920, 1080, null, null)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2K, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", null)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_2K_NO_CODEC, MediaFileFormat(MediaType.MP4, 1920, 960, null, null)), Pair(ThetaRepository.FileFormatEnum.VIDEO_4K, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", null)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_4K_NO_CODEC, MediaFileFormat(MediaType.MP4, 3840, 1920, null, null)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2K_30F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2K_60F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 60)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_1F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 1)), diff --git a/react-native/package.json b/react-native/package.json index 4ff863e1cb..5c1e7a1451 100644 --- a/react-native/package.json +++ b/react-native/package.json @@ -83,7 +83,7 @@ "engines": { "node": ">= 16.0.0" }, - "packageManager": "^yarn@1.22.15", + "packageManager": "yarn@1.22.15", "jest": { "preset": "react-native", "modulePathIgnorePatterns": [ diff --git a/react-native/src/__tests__/options/option-file-format.test.tsx b/react-native/src/__tests__/options/option-file-format.test.tsx index 7547b60b70..1e44f21fb7 100644 --- a/react-native/src/__tests__/options/option-file-format.test.tsx +++ b/react-native/src/__tests__/options/option-file-format.test.tsx @@ -50,6 +50,7 @@ describe('VideoFileFormatEnum', () => { [VideoFileFormatEnum.VIDEO_HD, 'VIDEO_HD'], [VideoFileFormatEnum.VIDEO_FULL_HD, 'VIDEO_FULL_HD'], [VideoFileFormatEnum.VIDEO_2K, 'VIDEO_2K'], + [VideoFileFormatEnum.VIDEO_2K_NO_CODEC, 'VIDEO_2K_NO_CODEC'], [VideoFileFormatEnum.VIDEO_2K_30F, 'VIDEO_2K_30F'], [VideoFileFormatEnum.VIDEO_2K_60F, 'VIDEO_2K_60F'], [VideoFileFormatEnum.VIDEO_2_7K_1F, 'VIDEO_2_7K_1F'], @@ -57,6 +58,7 @@ describe('VideoFileFormatEnum', () => { [VideoFileFormatEnum.VIDEO_3_6K_1F, 'VIDEO_3_6K_1F'], [VideoFileFormatEnum.VIDEO_3_6K_2F, 'VIDEO_3_6K_2F'], [VideoFileFormatEnum.VIDEO_4K, 'VIDEO_4K'], + [VideoFileFormatEnum.VIDEO_4K_NO_CODEC, 'VIDEO_4K_NO_CODEC'], [VideoFileFormatEnum.VIDEO_4K_30F, 'VIDEO_4K_30F'], [VideoFileFormatEnum.VIDEO_4K_60F, 'VIDEO_4K_60F'], [VideoFileFormatEnum.VIDEO_5_7K_2F, 'VIDEO_5_7K_2F'], @@ -90,6 +92,7 @@ describe('FileFormatEnum', () => { [FileFormatEnum.VIDEO_HD, 'VIDEO_HD'], [FileFormatEnum.VIDEO_FULL_HD, 'VIDEO_FULL_HD'], [FileFormatEnum.VIDEO_2K, 'VIDEO_2K'], + [FileFormatEnum.VIDEO_2K_NO_CODEC, 'VIDEO_2K_NO_CODEC'], [FileFormatEnum.VIDEO_2K_30F, 'VIDEO_2K_30F'], [FileFormatEnum.VIDEO_2K_60F, 'VIDEO_2K_60F'], [FileFormatEnum.VIDEO_2_7K_1F, 'VIDEO_2_7K_1F'], @@ -97,6 +100,7 @@ describe('FileFormatEnum', () => { [FileFormatEnum.VIDEO_3_6K_1F, 'VIDEO_3_6K_1F'], [FileFormatEnum.VIDEO_3_6K_2F, 'VIDEO_3_6K_2F'], [FileFormatEnum.VIDEO_4K, 'VIDEO_4K'], + [FileFormatEnum.VIDEO_4K_NO_CODEC, 'VIDEO_4K_NO_CODEC'], [FileFormatEnum.VIDEO_4K_30F, 'VIDEO_4K_30F'], [FileFormatEnum.VIDEO_4K_60F, 'VIDEO_4K_60F'], [FileFormatEnum.VIDEO_5_7K_2F, 'VIDEO_5_7K_2F'], diff --git a/react-native/src/capture/capture.ts b/react-native/src/capture/capture.ts index fa83c41f22..82c91ec9a0 100644 --- a/react-native/src/capture/capture.ts +++ b/react-native/src/capture/capture.ts @@ -8,6 +8,7 @@ import type { IsoAutoHighLimitEnum, IsoEnum, Options, + PhotoFileFormatEnum, WhiteBalanceEnum, } from '../theta-repository/options'; @@ -122,3 +123,17 @@ export abstract class CaptureBuilder> { return this as unknown as T; } } + +export class PhotoCaptureBuilderBase< + T extends PhotoCaptureBuilderBase +> extends CaptureBuilder { + /** + * Set photo file format. + * @param {PhotoFileFormatEnum} fileFormat Photo file format to set + * @return PhotoCaptureBuilder + */ + setFileFormat(fileFormat: PhotoFileFormatEnum): T { + this.options.fileFormat = fileFormat; + return this as unknown as T; + } +} diff --git a/react-native/src/capture/photo-capture.ts b/react-native/src/capture/photo-capture.ts index 682ddc7a3b..4a1b3e84fe 100644 --- a/react-native/src/capture/photo-capture.ts +++ b/react-native/src/capture/photo-capture.ts @@ -1,9 +1,5 @@ -import { CaptureBuilder } from './capture'; -import type { - FilterEnum, - PhotoFileFormatEnum, - PresetEnum, -} from '../theta-repository/options'; +import { PhotoCaptureBuilderBase } from './capture'; +import type { FilterEnum, PresetEnum } from '../theta-repository/options'; import { NativeModules } from 'react-native'; const ThetaClientReactNative = NativeModules.ThetaClientReactNative; @@ -28,22 +24,12 @@ export class PhotoCapture { /** * PhotoCaptureBaseBuilder class */ -export class PhotoCaptureBuilder extends CaptureBuilder { +export class PhotoCaptureBuilder extends PhotoCaptureBuilderBase { /** construct PhotoCaptureBuilder instance */ constructor() { super(); } - /** - * Set photo file format. - * @param {PhotoFileFormatEnum} fileFormat Photo file format to set - * @return PhotoCaptureBuilder - */ - setFileFormat(fileFormat: PhotoFileFormatEnum): PhotoCaptureBuilder { - this.options.fileFormat = fileFormat; - return this; - } - /** * Set image processing filter. * @param {FilterEnum} filter Image processing filter to set diff --git a/react-native/src/theta-repository/options/option-file-format.ts b/react-native/src/theta-repository/options/option-file-format.ts index ec8a9b055d..19f9f35bac 100644 --- a/react-native/src/theta-repository/options/option-file-format.ts +++ b/react-native/src/theta-repository/options/option-file-format.ts @@ -38,8 +38,12 @@ export const VideoFileFormatEnum = { VIDEO_FULL_HD: 'VIDEO_FULL_HD', /** mp4 1920 x 960 */ VIDEO_2K: 'VIDEO_2K', + /** mp4 1920 x 960 no codec */ + VIDEO_2K_NO_CODEC: 'VIDEO_2K_NO_CODEC', /** mp4 3840 x 1920 */ VIDEO_4K: 'VIDEO_4K', + /** mp4 3840 x 1920 no codec */ + VIDEO_4K_NO_CODEC: 'VIDEO_4K_NO_CODEC', /** mp4 1920 x 960 30fps */ VIDEO_2K_30F: 'VIDEO_2K_30F', /** mp4 1920 x 960 60fps */ From 9c7291b2312bbc336261097b5173c7647810c5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=BE=E5=B2=A1=E3=80=80=E4=BE=91=E5=87=9B?= <129148471+LassicYM@users.noreply.github.com> Date: Tue, 2 Jul 2024 08:56:29 +0900 Subject: [PATCH 3/4] add more format for video. --- flutter/lib/capture/capture_builder.dart | 84 +++++++ flutter/lib/options/file_format.dart | 84 +++++++ flutter/test/enum_name_test.dart | 8 + .../test/options/option_file_format_test.dart | 8 + .../ricoh360/thetaclient/ThetaRepository.kt | 208 ++++++++++++++++++ .../thetaclient/capture/VideoCaptureTest.kt | 26 ++- .../repository/options/FileFormatTest.kt | 17 +- .../options/option-file-format.test.tsx | 16 ++ .../options/option-file-format.ts | 16 ++ 9 files changed, 459 insertions(+), 8 deletions(-) diff --git a/flutter/lib/capture/capture_builder.dart b/flutter/lib/capture/capture_builder.dart index cdc1e02050..3b8f27281e 100644 --- a/flutter/lib/capture/capture_builder.dart +++ b/flutter/lib/capture/capture_builder.dart @@ -501,6 +501,54 @@ enum VideoFileFormatEnum { /// For RICOH THETA X or later video_2K_60F(FileFormatEnum.video_2K_60F), + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 2 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_2F(FileFormatEnum.video_2_7K_2752_2F), + + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 5 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_5F(FileFormatEnum.video_2_7K_2752_5F), + + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 10 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_10F(FileFormatEnum.video_2_7K_2752_10F), + + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 30 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_30F(FileFormatEnum.video_2_7K_2752_30F), + /// Video File format. /// type: mp4 /// size: 2688 x 2688 @@ -549,6 +597,24 @@ enum VideoFileFormatEnum { /// and _1 is back lens. This mode does not record audio track to MP4 file. video_3_6K_2F(FileFormatEnum.video_3_6K_2F), + /// Video File format. + /// type: mp4 + /// size: 3840 x 1920 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 10 + /// + /// For RICOH THETA X or later + video_4K_10F(FileFormatEnum.video_4K_10F), + + /// Video File format. + /// type: mp4 + /// size: 3840 x 1920 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 15 + /// + /// For RICOH THETA X or later + video_4K_15F(FileFormatEnum.video_4K_15F), + /// Video File format. /// type: mp4 /// size: 3840 x 1920 @@ -585,6 +651,24 @@ enum VideoFileFormatEnum { /// For RICOH THETA X or later video_5_7K_5F(FileFormatEnum.video_5_7K_5F), + /// Video File format. + /// type: mp4 + /// size: 5760 x 2880 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 10 + /// + /// For RICOH THETA X or later + video_5_7K_10F(FileFormatEnum.video_5_7K_10F), + + /// Video File format. + /// type: mp4 + /// size: 5760 x 2880 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 15 + /// + /// For RICOH THETA X or later + video_5_7K_15F(FileFormatEnum.video_5_7K_15F), + /// Video File format. /// type: mp4 /// size: 5760 x 2880 diff --git a/flutter/lib/options/file_format.dart b/flutter/lib/options/file_format.dart index 49b840e637..40e40460b8 100644 --- a/flutter/lib/options/file_format.dart +++ b/flutter/lib/options/file_format.dart @@ -107,6 +107,54 @@ enum FileFormatEnum { /// For RICOH THETA X or later video_2K_60F('VIDEO_2K_60F'), + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 2 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_2F('VIDEO_2_7K_2752_2F'), + + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 5 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_5F('VIDEO_2_7K_2752_5F'), + + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 10 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_10F('VIDEO_2_7K_2752_10F'), + + /// Video File format. + /// + /// type: mp4 + /// size: 2752 x 2752 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 30 + /// + /// RICOH THETA X firmware v2.50.2 or later. + /// This mode outputs two fisheye video for each lens. + /// The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + video_2_7K_2752_30F('VIDEO_2_7K_2752_30F'), + /// Video File format. /// type: mp4 /// size: 2688 x 2688 @@ -155,6 +203,24 @@ enum FileFormatEnum { /// and _1 is back lens. This mode does not record audio track to MP4 file. video_3_6K_2F('VIDEO_3_6K_2F'), + /// Video File format. + /// type: mp4 + /// size: 3840 x 1920 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 10 + /// + /// For RICOH THETA X or later + video_4K_10F('VIDEO_4K_10F'), + + /// Video File format. + /// type: mp4 + /// size: 3840 x 1920 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 15 + /// + /// For RICOH THETA X or later + video_4K_15F('VIDEO_4K_15F'), + /// Video File format. /// type: mp4 /// size: 3840 x 1920 @@ -191,6 +257,24 @@ enum FileFormatEnum { /// For RICOH THETA X or later video_5_7K_5F('VIDEO_5_7K_5F'), + /// Video File format. + /// type: mp4 + /// size: 5760 x 2880 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 10 + /// + /// For RICOH THETA X or later + video_5_7K_10F('VIDEO_5_7K_10F'), + + /// Video File format. + /// type: mp4 + /// size: 5760 x 2880 + /// codec: H.264/MPEG-4 AVC + /// frame rate: 15 + /// + /// For RICOH THETA X or later + video_5_7K_15F('VIDEO_5_7K_15F'), + /// Video File format. /// type: mp4 /// size: 5760 x 2880 diff --git a/flutter/test/enum_name_test.dart b/flutter/test/enum_name_test.dart index 7f720ae390..ff86986fa4 100644 --- a/flutter/test/enum_name_test.dart +++ b/flutter/test/enum_name_test.dart @@ -579,14 +579,22 @@ void main() { [VideoFileFormatEnum.video_4KnoCodec, 'VIDEO_4K_NO_CODEC'], [VideoFileFormatEnum.video_2K_30F, 'VIDEO_2K_30F'], [VideoFileFormatEnum.video_2K_60F, 'VIDEO_2K_60F'], + [VideoFileFormatEnum.video_2_7K_2752_2F, 'VIDEO_2_7K_2752_2F'], + [VideoFileFormatEnum.video_2_7K_2752_5F, 'VIDEO_2_7K_2752_5F'], + [VideoFileFormatEnum.video_2_7K_2752_10F, 'VIDEO_2_7K_2752_10F'], + [VideoFileFormatEnum.video_2_7K_2752_30F, 'VIDEO_2_7K_2752_30F'], [VideoFileFormatEnum.video_2_7K_1F, 'VIDEO_2_7K_1F'], [VideoFileFormatEnum.video_2_7K_2F, 'VIDEO_2_7K_2F'], [VideoFileFormatEnum.video_3_6K_1F, 'VIDEO_3_6K_1F'], [VideoFileFormatEnum.video_3_6K_2F, 'VIDEO_3_6K_2F'], + [VideoFileFormatEnum.video_4K_10F, 'VIDEO_4K_10F'], + [VideoFileFormatEnum.video_4K_15F, 'VIDEO_4K_15F'], [VideoFileFormatEnum.video_4K_30F, 'VIDEO_4K_30F'], [VideoFileFormatEnum.video_4K_60F, 'VIDEO_4K_60F'], [VideoFileFormatEnum.video_5_7K_2F, 'VIDEO_5_7K_2F'], [VideoFileFormatEnum.video_5_7K_5F, 'VIDEO_5_7K_5F'], + [VideoFileFormatEnum.video_5_7K_10F, 'VIDEO_5_7K_10F'], + [VideoFileFormatEnum.video_5_7K_15F, 'VIDEO_5_7K_15F'], [VideoFileFormatEnum.video_5_7K_30F, 'VIDEO_5_7K_30F'], [VideoFileFormatEnum.video_7K_2F, 'VIDEO_7K_2F'], [VideoFileFormatEnum.video_7K_5F, 'VIDEO_7K_5F'], diff --git a/flutter/test/options/option_file_format_test.dart b/flutter/test/options/option_file_format_test.dart index a8b056cec8..9d6268a99d 100644 --- a/flutter/test/options/option_file_format_test.dart +++ b/flutter/test/options/option_file_format_test.dart @@ -40,10 +40,18 @@ void main() { [FileFormatEnum.video_4KnoCodec, 'VIDEO_4K_NO_CODEC'], [FileFormatEnum.video_2K_30F, 'VIDEO_2K_30F'], [FileFormatEnum.video_2K_60F, 'VIDEO_2K_60F'], + [FileFormatEnum.video_2_7K_2752_2F, 'VIDEO_2_7K_2752_2F'], + [FileFormatEnum.video_2_7K_2752_5F, 'VIDEO_2_7K_2752_5F'], + [FileFormatEnum.video_2_7K_2752_10F, 'VIDEO_2_7K_2752_10F'], + [FileFormatEnum.video_2_7K_2752_30F, 'VIDEO_2_7K_2752_30F'], + [FileFormatEnum.video_4K_10F, 'VIDEO_4K_10F'], + [FileFormatEnum.video_4K_15F, 'VIDEO_4K_15F'], [FileFormatEnum.video_4K_30F, 'VIDEO_4K_30F'], [FileFormatEnum.video_4K_60F, 'VIDEO_4K_60F'], [FileFormatEnum.video_5_7K_2F, 'VIDEO_5_7K_2F'], [FileFormatEnum.video_5_7K_5F, 'VIDEO_5_7K_5F'], + [FileFormatEnum.video_5_7K_10F, 'VIDEO_5_7K_10F'], + [FileFormatEnum.video_5_7K_15F, 'VIDEO_5_7K_15F'], [FileFormatEnum.video_5_7K_30F, 'VIDEO_5_7K_30F'], [FileFormatEnum.video_7K_2F, 'VIDEO_7K_2F'], [FileFormatEnum.video_7K_5F, 'VIDEO_7K_5F'], diff --git a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt index e3f03814d5..a549156bd2 100644 --- a/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt +++ b/kotlin-multiplatform/src/commonMain/kotlin/com/ricoh360/thetaclient/ThetaRepository.kt @@ -3301,6 +3301,62 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_2K_60F(FileFormatTypeEnum.MP4, 1920, 960, "H.264/MPEG-4 AVC", 60), + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 2 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_2F(FileFormatTypeEnum.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 2), + + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 5 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_5F(FileFormatTypeEnum.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 5), + + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 10 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_10F(FileFormatTypeEnum.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 10), + + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 30 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_30F(FileFormatTypeEnum.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 30), + /** * Video File format. * @@ -3361,6 +3417,30 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_3_6K_2F(FileFormatTypeEnum.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 2), + /** + * Video File format. + * + * type: mp4 + * size: 3840 x 1920 + * codec: H.264/MPEG-4 AVC + * frame rate: 10 + * + * For RICOH THETA X or later + */ + VIDEO_4K_10F(FileFormatTypeEnum.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 10), + + /** + * Video File format. + * + * type: mp4 + * size: 3840 x 1920 + * codec: H.264/MPEG-4 AVC + * frame rate: 15 + * + * For RICOH THETA X or later + */ + VIDEO_4K_15F(FileFormatTypeEnum.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 15), + /** * Video File format. * @@ -3409,6 +3489,30 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_5_7K_5F(FileFormatTypeEnum.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 5), + /** + * Video File format. + * + * type: mp4 + * size: 5760 x 2880 + * codec: H.264/MPEG-4 AVC + * frame rate: 10 + * + * For RICOH THETA X or later + */ + VIDEO_5_7K_10F(FileFormatTypeEnum.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 10), + + /** + * Video File format. + * + * type: mp4 + * size: 5760 x 2880 + * codec: H.264/MPEG-4 AVC + * frame rate: 15 + * + * For RICOH THETA X or later + */ + VIDEO_5_7K_15F(FileFormatTypeEnum.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 15), + /** * Video File format. * @@ -3670,6 +3774,62 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_2K_60F(FileFormatEnum.VIDEO_2K_60F), + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 2 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_2F(FileFormatEnum.VIDEO_2_7K_2752_2F), + + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 5 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_5F(FileFormatEnum.VIDEO_2_7K_2752_5F), + + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 10 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_10F(FileFormatEnum.VIDEO_2_7K_2752_10F), + + /** + * Video File format. + * + * type: mp4 + * size: 2752 x 2752 + * codec: H.264/MPEG-4 AVC + * frame rate: 30 + * + * RICOH THETA X firmware v2.50.2 or later. + * This mode outputs two fisheye video for each lens. + * The MP4 file name ending with _0 is the video file on the front lens, and _1 is back lens. + */ + VIDEO_2_7K_2752_30F(FileFormatEnum.VIDEO_2_7K_2752_30F), + /** * Video File format. * @@ -3730,6 +3890,30 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_3_6K_2F(FileFormatEnum.VIDEO_3_6K_2F), + /** + * Video File format. + * + * type: mp4 + * size: 3840 x 1920 + * codec: H.264/MPEG-4 AVC + * frame rate: 10 + * + * For RICOH THETA X or later + */ + VIDEO_4K_10F(FileFormatEnum.VIDEO_4K_10F), + + /** + * Video File format. + * + * type: mp4 + * size: 3840 x 1920 + * codec: H.264/MPEG-4 AVC + * frame rate: 15 + * + * For RICOH THETA X or later + */ + VIDEO_4K_15F(FileFormatEnum.VIDEO_4K_15F), + /** * Video File format. * @@ -3778,6 +3962,30 @@ class ThetaRepository internal constructor(val endpoint: String, config: Config? */ VIDEO_5_7K_5F(FileFormatEnum.VIDEO_5_7K_5F), + /** + * Video File format. + * + * type: mp4 + * size: 5760 x 2880 + * codec: H.264/MPEG-4 AVC + * frame rate: 10 + * + * For RICOH THETA X or later + */ + VIDEO_5_7K_10F(FileFormatEnum.VIDEO_5_7K_10F), + + /** + * Video File format. + * + * type: mp4 + * size: 5760 x 2880 + * codec: H.264/MPEG-4 AVC + * frame rate: 15 + * + * For RICOH THETA X or later + */ + VIDEO_5_7K_15F(FileFormatEnum.VIDEO_5_7K_15F), + /** * Video File format. * diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt index 5d3123584e..480d868fa7 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/capture/VideoCaptureTest.kt @@ -7,12 +7,20 @@ import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.transferred.CaptureMode import com.ricoh360.thetaclient.transferred.MediaFileFormat import com.ricoh360.thetaclient.transferred.MediaType -import io.ktor.client.network.sockets.* -import io.ktor.http.* -import io.ktor.utils.io.* -import kotlinx.coroutines.* +import io.ktor.client.network.sockets.ConnectTimeoutException +import io.ktor.http.HttpStatusCode +import io.ktor.utils.io.ByteReadChannel +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest -import kotlin.test.* +import kotlinx.coroutines.withTimeout +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull +import kotlin.test.assertTrue class VideoCaptureTest { private val endpoint = "http://192.168.1.1:80/" @@ -333,14 +341,22 @@ class VideoCaptureTest { Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_NO_CODEC, MediaFileFormat(MediaType.MP4, 3840, 1920, null, null)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2K_30F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2K_60F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 60)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_2752_2F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_2752_5F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 5)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_2752_10F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 10)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_2752_30F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_1F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 1)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_2_7K_2F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 2)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_3_6K_1F, MediaFileFormat(MediaType.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 1)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_3_6K_2F, MediaFileFormat(MediaType.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_10F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 10)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_15F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 15)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_30F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_4K_60F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 60)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_2F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 2)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_5F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 5)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_10F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 10)), + Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_15F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 15)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_5_7K_30F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_7K_2F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 2)), Pair(ThetaRepository.VideoFileFormatEnum.VIDEO_7K_5F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 5)), diff --git a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt index 42bfc9e30b..a0650150ee 100644 --- a/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt +++ b/kotlin-multiplatform/src/commonTest/kotlin/com/ricoh360/thetaclient/repository/options/FileFormatTest.kt @@ -7,10 +7,13 @@ import com.ricoh360.thetaclient.ThetaRepository import com.ricoh360.thetaclient.transferred.MediaFileFormat import com.ricoh360.thetaclient.transferred.MediaType import com.ricoh360.thetaclient.transferred.Options -import io.ktor.http.* -import io.ktor.utils.io.* +import io.ktor.http.HttpStatusCode +import io.ktor.utils.io.ByteReadChannel import kotlinx.coroutines.test.runTest -import kotlin.test.* +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals class FileFormatTest { private val endpoint = "http://192.168.1.1:80/" @@ -117,14 +120,22 @@ class FileFormatTest { Pair(ThetaRepository.FileFormatEnum.VIDEO_4K_NO_CODEC, MediaFileFormat(MediaType.MP4, 3840, 1920, null, null)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2K_30F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2K_60F, MediaFileFormat(MediaType.MP4, 1920, 960, "H.264/MPEG-4 AVC", 60)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_2752_2F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_2752_5F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 5)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_2752_10F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 10)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_2752_30F, MediaFileFormat(MediaType.MP4, 2752, 2752, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_1F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 1)), Pair(ThetaRepository.FileFormatEnum.VIDEO_2_7K_2F, MediaFileFormat(MediaType.MP4, 2688, 2688, "H.264/MPEG-4 AVC", 2)), Pair(ThetaRepository.FileFormatEnum.VIDEO_3_6K_1F, MediaFileFormat(MediaType.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 1)), Pair(ThetaRepository.FileFormatEnum.VIDEO_3_6K_2F, MediaFileFormat(MediaType.MP4, 3648, 3648, "H.264/MPEG-4 AVC", 2)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_4K_10F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 10)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_4K_15F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 15)), Pair(ThetaRepository.FileFormatEnum.VIDEO_4K_30F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.FileFormatEnum.VIDEO_4K_60F, MediaFileFormat(MediaType.MP4, 3840, 1920, "H.264/MPEG-4 AVC", 60)), Pair(ThetaRepository.FileFormatEnum.VIDEO_5_7K_2F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 2)), Pair(ThetaRepository.FileFormatEnum.VIDEO_5_7K_5F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 5)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_5_7K_10F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 10)), + Pair(ThetaRepository.FileFormatEnum.VIDEO_5_7K_15F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 15)), Pair(ThetaRepository.FileFormatEnum.VIDEO_5_7K_30F, MediaFileFormat(MediaType.MP4, 5760, 2880, "H.264/MPEG-4 AVC", 30)), Pair(ThetaRepository.FileFormatEnum.VIDEO_7K_2F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 2)), Pair(ThetaRepository.FileFormatEnum.VIDEO_7K_5F, MediaFileFormat(MediaType.MP4, 7680, 3840, "H.264/MPEG-4 AVC", 5)), diff --git a/react-native/src/__tests__/options/option-file-format.test.tsx b/react-native/src/__tests__/options/option-file-format.test.tsx index 1e44f21fb7..a88d77ce63 100644 --- a/react-native/src/__tests__/options/option-file-format.test.tsx +++ b/react-native/src/__tests__/options/option-file-format.test.tsx @@ -53,16 +53,24 @@ describe('VideoFileFormatEnum', () => { [VideoFileFormatEnum.VIDEO_2K_NO_CODEC, 'VIDEO_2K_NO_CODEC'], [VideoFileFormatEnum.VIDEO_2K_30F, 'VIDEO_2K_30F'], [VideoFileFormatEnum.VIDEO_2K_60F, 'VIDEO_2K_60F'], + [VideoFileFormatEnum.VIDEO_2_7K_2752_2F, 'VIDEO_2_7K_2752_2F'], + [VideoFileFormatEnum.VIDEO_2_7K_2752_5F, 'VIDEO_2_7K_2752_5F'], + [VideoFileFormatEnum.VIDEO_2_7K_2752_10F, 'VIDEO_2_7K_2752_10F'], + [VideoFileFormatEnum.VIDEO_2_7K_2752_30F, 'VIDEO_2_7K_2752_30F'], [VideoFileFormatEnum.VIDEO_2_7K_1F, 'VIDEO_2_7K_1F'], [VideoFileFormatEnum.VIDEO_2_7K_2F, 'VIDEO_2_7K_2F'], [VideoFileFormatEnum.VIDEO_3_6K_1F, 'VIDEO_3_6K_1F'], [VideoFileFormatEnum.VIDEO_3_6K_2F, 'VIDEO_3_6K_2F'], [VideoFileFormatEnum.VIDEO_4K, 'VIDEO_4K'], [VideoFileFormatEnum.VIDEO_4K_NO_CODEC, 'VIDEO_4K_NO_CODEC'], + [VideoFileFormatEnum.VIDEO_4K_10F, 'VIDEO_4K_10F'], + [VideoFileFormatEnum.VIDEO_4K_15F, 'VIDEO_4K_15F'], [VideoFileFormatEnum.VIDEO_4K_30F, 'VIDEO_4K_30F'], [VideoFileFormatEnum.VIDEO_4K_60F, 'VIDEO_4K_60F'], [VideoFileFormatEnum.VIDEO_5_7K_2F, 'VIDEO_5_7K_2F'], [VideoFileFormatEnum.VIDEO_5_7K_5F, 'VIDEO_5_7K_5F'], + [VideoFileFormatEnum.VIDEO_5_7K_10F, 'VIDEO_5_7K_10F'], + [VideoFileFormatEnum.VIDEO_5_7K_15F, 'VIDEO_5_7K_15F'], [VideoFileFormatEnum.VIDEO_5_7K_30F, 'VIDEO_5_7K_30F'], [VideoFileFormatEnum.VIDEO_7K_2F, 'VIDEO_7K_2F'], [VideoFileFormatEnum.VIDEO_7K_5F, 'VIDEO_7K_5F'], @@ -95,16 +103,24 @@ describe('FileFormatEnum', () => { [FileFormatEnum.VIDEO_2K_NO_CODEC, 'VIDEO_2K_NO_CODEC'], [FileFormatEnum.VIDEO_2K_30F, 'VIDEO_2K_30F'], [FileFormatEnum.VIDEO_2K_60F, 'VIDEO_2K_60F'], + [FileFormatEnum.VIDEO_2_7K_2752_2F, 'VIDEO_2_7K_2752_2F'], + [FileFormatEnum.VIDEO_2_7K_2752_5F, 'VIDEO_2_7K_2752_5F'], + [FileFormatEnum.VIDEO_2_7K_2752_10F, 'VIDEO_2_7K_2752_10F'], + [FileFormatEnum.VIDEO_2_7K_2752_30F, 'VIDEO_2_7K_2752_30F'], [FileFormatEnum.VIDEO_2_7K_1F, 'VIDEO_2_7K_1F'], [FileFormatEnum.VIDEO_2_7K_2F, 'VIDEO_2_7K_2F'], [FileFormatEnum.VIDEO_3_6K_1F, 'VIDEO_3_6K_1F'], [FileFormatEnum.VIDEO_3_6K_2F, 'VIDEO_3_6K_2F'], [FileFormatEnum.VIDEO_4K, 'VIDEO_4K'], [FileFormatEnum.VIDEO_4K_NO_CODEC, 'VIDEO_4K_NO_CODEC'], + [FileFormatEnum.VIDEO_4K_10F, 'VIDEO_4K_10F'], + [FileFormatEnum.VIDEO_4K_15F, 'VIDEO_4K_15F'], [FileFormatEnum.VIDEO_4K_30F, 'VIDEO_4K_30F'], [FileFormatEnum.VIDEO_4K_60F, 'VIDEO_4K_60F'], [FileFormatEnum.VIDEO_5_7K_2F, 'VIDEO_5_7K_2F'], [FileFormatEnum.VIDEO_5_7K_5F, 'VIDEO_5_7K_5F'], + [FileFormatEnum.VIDEO_5_7K_10F, 'VIDEO_5_7K_10F'], + [FileFormatEnum.VIDEO_5_7K_15F, 'VIDEO_5_7K_15F'], [FileFormatEnum.VIDEO_5_7K_30F, 'VIDEO_5_7K_30F'], [FileFormatEnum.VIDEO_7K_2F, 'VIDEO_7K_2F'], [FileFormatEnum.VIDEO_7K_5F, 'VIDEO_7K_5F'], diff --git a/react-native/src/theta-repository/options/option-file-format.ts b/react-native/src/theta-repository/options/option-file-format.ts index 19f9f35bac..25b538049e 100644 --- a/react-native/src/theta-repository/options/option-file-format.ts +++ b/react-native/src/theta-repository/options/option-file-format.ts @@ -48,6 +48,14 @@ export const VideoFileFormatEnum = { VIDEO_2K_30F: 'VIDEO_2K_30F', /** mp4 1920 x 960 60fps */ VIDEO_2K_60F: 'VIDEO_2K_60F', + /** mp4 2752 x 2752 2fps */ + VIDEO_2_7K_2752_2F: 'VIDEO_2_7K_2752_2F', + /** mp4 2752 x 2752 5fps */ + VIDEO_2_7K_2752_5F: 'VIDEO_2_7K_2752_5F', + /** mp4 2752 x 2752 10fps */ + VIDEO_2_7K_2752_10F: 'VIDEO_2_7K_2752_10F', + /** mp4 2752 x 2752 30fps */ + VIDEO_2_7K_2752_30F: 'VIDEO_2_7K_2752_30F', /** mp4 2688 x 2688 1fps */ VIDEO_2_7K_1F: 'VIDEO_2_7K_1F', /** mp4 2688 x 2688 2fps */ @@ -56,6 +64,10 @@ export const VideoFileFormatEnum = { VIDEO_3_6K_1F: 'VIDEO_3_6K_1F', /** mp4 3648 x 3648 2fps */ VIDEO_3_6K_2F: 'VIDEO_3_6K_2F', + /** mp4 3840 x 1920 10fps */ + VIDEO_4K_10F: 'VIDEO_4K_10F', + /** mp4 3840 x 1920 15fps */ + VIDEO_4K_15F: 'VIDEO_4K_15F', /** mp4 3840 x 1920 30fps */ VIDEO_4K_30F: 'VIDEO_4K_30F', /** mp4 3840 x 1920 60fps */ @@ -64,6 +76,10 @@ export const VideoFileFormatEnum = { VIDEO_5_7K_2F: 'VIDEO_5_7K_2F', /** mp4 5760 x 2880 5fps */ VIDEO_5_7K_5F: 'VIDEO_5_7K_5F', + /** mp4 5760 x 2880 10fps */ + VIDEO_5_7K_10F: 'VIDEO_5_7K_10F', + /** mp4 5760 x 2880 15fps */ + VIDEO_5_7K_15F: 'VIDEO_5_7K_15F', /** mp4 5760 x 2880 30fps */ VIDEO_5_7K_30F: 'VIDEO_5_7K_30F', /** mp4 7680 x 3840 2fps */ From 140f3c103b65bd0bfb56d08cc64c42c05fd884b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=BE=E5=B2=A1=E3=80=80=E4=BE=91=E5=87=9B?= <129148471+LassicYM@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:52:29 +0900 Subject: [PATCH 4/4] Update version to 1.9.1 --- demos/demo-android/app/build.gradle | 2 +- demos/demo-ios/Podfile | 2 +- demos/demo-react-native/package.json | 2 +- docs/tutorial-android.ja.md | 2 +- docs/tutorial-android.md | 2 +- flutter/android/build.gradle | 2 +- flutter/ios/theta_client_flutter.podspec | 4 ++-- flutter/pubspec.yaml | 2 +- kotlin-multiplatform/build.gradle.kts | 2 +- react-native/android/build.gradle | 2 +- react-native/package.json | 2 +- react-native/theta-client-react-native.podspec | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/demos/demo-android/app/build.gradle b/demos/demo-android/app/build.gradle index 2b1c8a0747..1407a30387 100755 --- a/demos/demo-android/app/build.gradle +++ b/demos/demo-android/app/build.gradle @@ -75,7 +75,7 @@ dependencies { implementation 'com.jakewharton.timber:timber:5.0.1' implementation 'io.coil-kt:coil-compose:2.2.2' implementation "io.ktor:ktor-client-cio:2.3.9" - implementation "com.ricoh360.thetaclient:theta-client:1.9.0" + implementation "com.ricoh360.thetaclient:theta-client:1.9.1" testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" diff --git a/demos/demo-ios/Podfile b/demos/demo-ios/Podfile index 7306eb6634..2bf4212214 100644 --- a/demos/demo-ios/Podfile +++ b/demos/demo-ios/Podfile @@ -7,5 +7,5 @@ target 'SdkSample' do use_frameworks! # Pods for SdkSample - pod 'THETAClient', '1.9.0' + pod 'THETAClient', '1.9.1' end diff --git a/demos/demo-react-native/package.json b/demos/demo-react-native/package.json index d7fd847fb7..c199795939 100644 --- a/demos/demo-react-native/package.json +++ b/demos/demo-react-native/package.json @@ -13,7 +13,7 @@ "dependencies": { "@react-navigation/native": "^6.1.0", "@react-navigation/native-stack": "^6.9.5", - "theta-client-react-native": "1.9.0", + "theta-client-react-native": "1.9.1", "react": "18.2.0", "react-native": "0.71.14", "react-native-safe-area-context": "^4.4.1", diff --git a/docs/tutorial-android.ja.md b/docs/tutorial-android.ja.md index 3ada8dd08a..0114c03c60 100644 --- a/docs/tutorial-android.ja.md +++ b/docs/tutorial-android.ja.md @@ -4,7 +4,7 @@ - モジュールの`build.gradle`の`dependencies`に次を追加します。 ``` - implementation "com.ricoh360.thetaclient:theta-client:1.9.0" + implementation "com.ricoh360.thetaclient:theta-client:1.9.1" ``` - 本 SDK を使用したアプリケーションが動作するスマートフォンと THETA を無線 LAN 接続しておきます。 diff --git a/docs/tutorial-android.md b/docs/tutorial-android.md index 269387460e..4199bf37c5 100644 --- a/docs/tutorial-android.md +++ b/docs/tutorial-android.md @@ -5,7 +5,7 @@ - Add following descriptions to the `dependencies` of your module's `build.gradle`. ``` - implementation "com.ricoh360.thetaclient:theta-client:1.9.0" + implementation "com.ricoh360.thetaclient:theta-client:1.9.1" ``` - Connect the wireless LAN between THETA and the smartphone that runs on the application using this SDK. diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 0bbe0fcb9a..64968793b0 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -53,5 +53,5 @@ dependencies { implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.9") implementation("com.soywiz.korlibs.krypto:krypto:4.0.10") - implementation("com.ricoh360.thetaclient:theta-client:1.9.0") + implementation("com.ricoh360.thetaclient:theta-client:1.9.1") } diff --git a/flutter/ios/theta_client_flutter.podspec b/flutter/ios/theta_client_flutter.podspec index d59488220f..a615a9ce40 100644 --- a/flutter/ios/theta_client_flutter.podspec +++ b/flutter/ios/theta_client_flutter.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'theta_client_flutter' - s.version = '1.9.0' + s.version = '1.9.1' s.summary = 'theta-client plugin project.' s.description = <<-DESC theta-client Flutter plugin project. @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.dependency 'Flutter' s.platform = :ios, '15.0' - s.dependency 'THETAClient', '1.9.0' + s.dependency 'THETAClient', '1.9.1' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index f00effd060..6bc79646e3 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,6 +1,6 @@ name: theta_client_flutter description: THETA Client Flutter plugin project. -version: 1.9.0 +version: 1.9.1 homepage: environment: diff --git a/kotlin-multiplatform/build.gradle.kts b/kotlin-multiplatform/build.gradle.kts index cb763182df..93f3565c7a 100644 --- a/kotlin-multiplatform/build.gradle.kts +++ b/kotlin-multiplatform/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { dokkaPlugin("org.jetbrains.dokka:versioning-plugin:1.9.10") } -val thetaClientVersion = "1.9.0" +val thetaClientVersion = "1.9.1" group = "com.ricoh360.thetaclient" version = thetaClientVersion diff --git a/react-native/android/build.gradle b/react-native/android/build.gradle index 5a83efe377..889ef179ad 100644 --- a/react-native/android/build.gradle +++ b/react-native/android/build.gradle @@ -135,7 +135,7 @@ dependencies { implementation "com.facebook.react:react-native:+" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3" - implementation "com.ricoh360.thetaclient:theta-client:1.9.0" + implementation "com.ricoh360.thetaclient:theta-client:1.9.1" // From node_modules } diff --git a/react-native/package.json b/react-native/package.json index 5c1e7a1451..57381f315f 100644 --- a/react-native/package.json +++ b/react-native/package.json @@ -1,6 +1,6 @@ { "name": "theta-client-react-native", - "version": "1.9.0", + "version": "1.9.1", "description": "This library provides a way to control RICOH THETA using.", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/react-native/theta-client-react-native.podspec b/react-native/theta-client-react-native.podspec index 9ef34885e7..0844a25c52 100644 --- a/react-native/theta-client-react-native.podspec +++ b/react-native/theta-client-react-native.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm,swift}" s.dependency "React-Core" - s.dependency "THETAClient", "1.9.0" + s.dependency "THETAClient", "1.9.1" # Don't install the dependencies when we run `pod install` in the old architecture. if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then