diff --git a/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java deleted file mode 100644 index f6340c32..00000000 --- a/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.brentvatne.react; - -import android.annotation.SuppressLint; -import android.media.MediaCodecInfo; -import android.media.MediaCodecList; -import android.media.MediaDrm; -import android.media.MediaFormat; -import android.media.UnsupportedSchemeException; -import android.os.Build; - -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; - -import java.util.UUID; - -@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) -public class VideoDecoderPropertiesModule extends ReactContextBaseJavaModule { - - ReactApplicationContext reactContext; - - @NonNull - @Override - public String getName() { - return "VideoDecoderProperties"; - } - - @SuppressLint("ObsoleteSdkInt") - @ReactMethod - public void getWidevineLevel(Promise p) { - int widevineLevel = 0; - - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { - p.resolve(widevineLevel); - return; - } - final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); - final String WIDEVINE_SECURITY_LEVEL_1 = "L1"; - final String WIDEVINE_SECURITY_LEVEL_2 = "L2"; - final String WIDEVINE_SECURITY_LEVEL_3 = "L3"; - final String SECURITY_LEVEL_PROPERTY = "securityLevel"; - - String securityProperty = null; - try { - MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); - securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); - } catch (UnsupportedSchemeException e) { - e.printStackTrace(); - } - if (securityProperty == null) { - p.resolve(widevineLevel); - return; - } - - switch (securityProperty) { - case WIDEVINE_SECURITY_LEVEL_1: { - widevineLevel = 1; - break; - } - case WIDEVINE_SECURITY_LEVEL_2: { - widevineLevel = 2; - break; - } - case WIDEVINE_SECURITY_LEVEL_3: { - widevineLevel = 3; - break; - } - default: { - // widevineLevel 0 - break; - } - } - p.resolve(widevineLevel); - } - - @SuppressLint("ObsoleteSdkInt") - @ReactMethod - public void isCodecSupported(String mimeType, int width, int height, Promise p) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - p.resolve("unsupported"); - return; - } - - MediaCodecList mRegularCodecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS); - MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height); - String codecName = mRegularCodecs.findDecoderForFormat(format); - - if (codecName == null) { - p.resolve("unsupported"); - return; - } - - // Fallback for android < 10 - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - p.resolve("software"); - return; - } - - boolean isHardwareAccelerated = false; - - for (MediaCodecInfo codecInfo : mRegularCodecs.getCodecInfos()) { - if (codecInfo.getName().equalsIgnoreCase(codecName)) { - isHardwareAccelerated = codecInfo.isHardwareAccelerated(); - break; - } - } - - p.resolve(isHardwareAccelerated ? "software" : "hardware"); - } - - - @ReactMethod - public void isHEVCSupported(Promise p) { - isCodecSupported("video/hevc", 1920, 1080, p); - } - - public VideoDecoderPropertiesModule(ReactApplicationContext reactContext) { - super(reactContext); - this.reactContext = reactContext; - } - -} diff --git a/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.kt b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.kt new file mode 100644 index 00000000..a006d3d4 --- /dev/null +++ b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.kt @@ -0,0 +1,72 @@ +package com.brentvatne.react + +import android.media.MediaCodecList +import android.media.MediaDrm +import android.media.MediaFormat +import android.media.UnsupportedSchemeException +import android.os.Build +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReactMethod +import java.util.UUID + +class VideoDecoderPropertiesModule(reactContext: ReactApplicationContext?) : ReactContextBaseJavaModule(reactContext) { + override fun getName(): String = REACT_CLASS + + @ReactMethod + fun getWidevineLevel(p: Promise) { + var widevineLevel = 0 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + p.resolve(widevineLevel) + return + } + try { + val mediaDrm = MediaDrm(WIDEVINE_UUID) + val securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY) + widevineLevel = when (securityProperty) { + "L1" -> 1 + "L2" -> 2 + "L3" -> 3 + else -> 0 + } + } catch (e: UnsupportedSchemeException) { + e.printStackTrace() + } + p.resolve(widevineLevel) + } + + @ReactMethod + fun isCodecSupported(mimeType: String?, width: Int, height: Int, p: Promise) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + p.resolve("unsupported") + return + } + val mRegularCodecs = MediaCodecList(MediaCodecList.REGULAR_CODECS) + val format = MediaFormat.createVideoFormat(mimeType!!, width, height) + val codecName = mRegularCodecs.findDecoderForFormat(format) + if (codecName == null) { + p.resolve("unsupported") + return + } + + // Fallback for android < 10 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + p.resolve("software") + return + } + val isHardwareAccelerated = mRegularCodecs.codecInfos.any { + it.name.equals(codecName, ignoreCase = true) && it.isHardwareAccelerated + } + p.resolve(if (isHardwareAccelerated) "software" else "hardware") + } + + @ReactMethod + fun isHEVCSupported(p: Promise) = isCodecSupported("video/hevc", 1920, 1080, p) + + companion object { + private val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L) + private const val SECURITY_LEVEL_PROPERTY = "securityLevel" + private const val REACT_CLASS = "VideoManager" + } +}