diff --git a/react-native/android/build.gradle b/react-native/android/build.gradle index e509ee4..e00921b 100644 --- a/react-native/android/build.gradle +++ b/react-native/android/build.gradle @@ -31,8 +31,8 @@ android { defaultConfig { minSdkVersion safeExtGet('ffmpegKitPackage', 'https').contains("-lts") ? 16 : 24 targetSdkVersion 30 - versionCode 451 - versionName "4.5.1" + versionCode 452 + versionName "4.5.2" } buildTypes { diff --git a/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java b/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java index 7f9ce9d..bccdcee 100644 --- a/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java +++ b/react-native/android/src/main/java/com/arthenica/ffmpegkit/reactnative/FFmpegKitReactNativeModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Taner Sener + * Copyright (c) 2021-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -47,7 +47,6 @@ import com.arthenica.ffmpegkit.Signal; import com.arthenica.ffmpegkit.Statistics; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.BaseActivityEventListener; -import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -75,7 +74,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; -public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule implements LifecycleEventListener { +public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule { public static final String LIBRARY_NAME = "ffmpeg-kit-react-native"; public static final String PLATFORM_NAME = "android"; @@ -131,7 +130,6 @@ public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule imple this.asyncExecutorService = Executors.newFixedThreadPool(asyncWriteToPipeConcurrencyLimit); if (reactContext != null) { - reactContext.addLifecycleEventListener(this); registerGlobalCallbacks(reactContext); } } @@ -151,19 +149,6 @@ public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule imple return "FFmpegKitReactNativeModule"; } - @Override - public void onHostResume() { - } - - @Override - public void onHostPause() { - } - - @Override - public void onHostDestroy() { - this.asyncExecutorService.shutdown(); - } - protected void registerGlobalCallbacks(final ReactApplicationContext reactContext) { FFmpegKitConfig.enableFFmpegSessionCompleteCallback(session -> { final DeviceEventManagerModule.RCTDeviceEventEmitter jsModule = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); @@ -984,6 +969,12 @@ public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule imple promise.resolve(toStringArray(Packages.getExternalLibraries())); } + @ReactMethod + public void uninit(final Promise promise) { + this.asyncExecutorService.shutdown(); + promise.resolve(null); + } + protected void enableLogs() { logsEnabled.compareAndSet(false, true); } @@ -1144,16 +1135,18 @@ public class FFmpegKitReactNativeModule extends ReactContextBaseJavaModule imple } protected static WritableMap toMap(final MediaInformation mediaInformation) { - WritableMap map = Arguments.createMap(); - if (mediaInformation != null) { + WritableMap map = Arguments.createMap(); + JSONObject allProperties = mediaInformation.getAllProperties(); if (allProperties != null) { map = toMap(allProperties); } - } - return map; + return map; + } else { + return null; + } } protected static WritableMap toMap(final JSONObject jsonObject) { diff --git a/react-native/ios/FFmpegKitReactNativeModule.m b/react-native/ios/FFmpegKitReactNativeModule.m index 9babaa4..7465cda 100644 --- a/react-native/ios/FFmpegKitReactNativeModule.m +++ b/react-native/ios/FFmpegKitReactNativeModule.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Taner Sener + * Copyright (c) 2021-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -695,6 +695,10 @@ RCT_EXPORT_METHOD(getExternalLibraries:(RCTPromiseResolveBlock)resolve rejecter: resolve([Packages getExternalLibraries]); } +RCT_EXPORT_METHOD(uninit:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { + resolve(nil); +} + - (void)enableLogs { logsEnabled = true; } @@ -724,16 +728,14 @@ RCT_EXPORT_METHOD(getExternalLibraries:(RCTPromiseResolveBlock)resolve rejecter: dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithDouble:[[session getStartTime] timeIntervalSince1970]*1000]; dictionary[KEY_SESSION_COMMAND] = [session getCommand]; - if ([session isFFprobe]) { - if ([session isMediaInformation]) { - MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; - dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitReactNativeModule toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; - dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; - } else { - dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE]; - } - } else { + if ([session isFFmpeg]) { dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG]; + } else if ([session isFFprobe]) { + dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE]; + } else if ([session isMediaInformation]) { + MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; + dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitReactNativeModule toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; + dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; } return dictionary; diff --git a/react-native/package.json b/react-native/package.json index 7e72211..31dd84f 100644 --- a/react-native/package.json +++ b/react-native/package.json @@ -1,6 +1,6 @@ { "name": "ffmpeg-kit-react-native", - "version": "4.5.1", + "version": "4.5.2", "description": "FFmpeg Kit for React Native", "main": "src/index", "types": "src/index.d.ts", diff --git a/react-native/src/index.d.ts b/react-native/src/index.d.ts index 5836754..8de2b56 100644 --- a/react-native/src/index.d.ts +++ b/react-native/src/index.d.ts @@ -92,6 +92,8 @@ declare module 'ffmpeg-kit-react-native' { static init(): Promise; + static uninit(): Promise; + static enableRedirection(): Promise; static disableRedirection(): Promise; diff --git a/react-native/src/index.js b/react-native/src/index.js index 4b28ff5..03241f1 100644 --- a/react-native/src/index.js +++ b/react-native/src/index.js @@ -669,11 +669,12 @@ export class AbstractSession extends Session { } /** - * Cancels running the session. + * Cancels running the session. Only starts cancellation. Does not guarantee that session is cancelled when promise resolves. */ - cancel() { + async cancel() { + const sessionId = this.getSessionId(); if (sessionId === undefined) { - return FFmpegKitReactNativeModule.cancel(); + return Promise.reject(new Error('sessionId is not defined')); } else { return FFmpegKitReactNativeModule.cancelSession(sessionId); } @@ -811,6 +812,15 @@ export class FFmpegKitConfig { await FFmpegKitInitializer.initialize(); } + /** + * Uninitializes the library. + * + * Calling this method before application termination is recommended but not required. + */ + static async uninit() { + return FFmpegKitReactNativeModule.uninit(); + } + /** *

Enables log and statistics redirection. * @@ -1608,7 +1618,7 @@ class FFmpegKitFactory { } static getVersion() { - return "4.5.1"; + return "4.5.2"; } static getLogRedirectionStrategy(sessionId) { @@ -2474,7 +2484,7 @@ export class MediaInformation { /** * Returns duration. * - * @return media duration in milliseconds + * @return media duration in "seconds.microseconds" format */ getDuration() { return this.getStringProperty(MediaInformation.KEY_DURATION);