diff --git a/README.md b/README.md index 3d3f22667..c1604eac7 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ https://github.com/CatVodTVOfficial/CatVodTVJarLoader | recordable | 1 | 是否紀錄 | 0:關閉;1:啟用 | | playerType | none | 播放器 | 0:系統;1:IJK;2:EXO | | timeout | 15 | 播放超時 | 單位:秒 | -| header | none | 標頭 | 格式:json | +| header | none | 請求標頭 | 格式:json | +| click | none | 點擊js | javascript | ### 直播欄位 @@ -27,7 +28,8 @@ https://github.com/CatVodTVOfficial/CatVodTVJarLoader | boot | false | 是否自啟動 | | | playerType | none | 播放器 | 0:系統;1:IJK;2:EXO | | timeout | 15 | 播放超時 | 單位:秒 | -| header | none | 標頭 | 格式:json | +| header | none | 請求標頭 | 格式:json | +| click | none | 點擊js | javascript | ### 配置範例 diff --git a/app/build.gradle b/app/build.gradle index daf37729a..5fd83aaf7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { minSdk 21 targetSdk 28 versionCode 215 - versionName "2.1.5" + versionName "1228#2" javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index fc929b8bc..6d2cdf891 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -121,7 +121,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick } private int getPlayerType(int playerType) { - return playerType != -1 ? playerType : getHome() != null && getHome().getPlayerType() != -1 ? getHome().getPlayerType() : Setting.getLivePlayer(); + return playerType != -1 ? playerType : Setting.getLivePlayer(); } private int getTimeout() { @@ -709,7 +709,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick } private void checkError(ErrorEvent event) { - if (getHome() != null && getHome().getPlayerType() == -1 && event.isUrl() && event.getRetry() > 0 && getToggleCount() < 2 && mPlayers.getPlayer() != Players.SYS) { + if (mChannel != null && mChannel.getPlayerType() == -1 && event.isUrl() && event.getRetry() > 0 && getToggleCount() < 2 && mPlayers.getPlayer() != Players.SYS) { toggleCount++; nextPlayer(); } else { diff --git a/app/src/main/java/com/fongmi/android/tv/api/Decoder.java b/app/src/main/java/com/fongmi/android/tv/api/Decoder.java index 533ef7a1a..9a101df54 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/Decoder.java +++ b/app/src/main/java/com/fongmi/android/tv/api/Decoder.java @@ -69,11 +69,11 @@ public class Decoder { SecretKeySpec spec = new SecretKeySpec(padEnd(key).getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, spec); - return new String(cipher.doFinal(decodeHex(data)), StandardCharsets.UTF_8); + return new String(cipher.doFinal(Util.hex2byte(data)), StandardCharsets.UTF_8); } private static String cbc(String data) throws Exception { - String decode = new String(decodeHex(data)).toLowerCase(); + String decode = new String(Util.hex2byte(data)).toLowerCase(); String key = padEnd(decode.substring(decode.indexOf("$#") + 2, decode.indexOf("#$"))); String iv = padEnd(decode.substring(decode.length() - 13)); SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES"); @@ -81,7 +81,7 @@ public class Decoder { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); data = data.substring(data.indexOf("2324") + 4, data.length() - 26); - byte[] decryptData = cipher.doFinal(decodeHex(data)); + byte[] decryptData = cipher.doFinal(Util.hex2byte(data)); return new String(decryptData, StandardCharsets.UTF_8); } @@ -99,10 +99,4 @@ public class Decoder { private static String padEnd(String key) { return key + "0000000000000000".substring(key.length()); } - - private static byte[] decodeHex(String s) { - byte[] bytes = new byte[s.length() / 2]; - for (int i = 0; i < bytes.length; i++) bytes[i] = Integer.valueOf(s.substring(i * 2, i * 2 + 2), 16).byteValue(); - return bytes; - } } diff --git a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java index 8f609466f..9b6a16e67 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java +++ b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java @@ -59,15 +59,16 @@ public class LiveParser { Setting setting = Setting.create(); Channel channel = Channel.create(""); for (String line : text.split("\n")) { - setting.check(line); if (Thread.interrupted()) break; if (line.startsWith("#EXTINF:")) { Group group = live.find(Group.create(extract(line, GROUP))); channel = group.find(Channel.create(extract(line, NAME))); channel.setLogo(extract(line, LOGO)); - setting.copy(channel).clear(); } else if (line.contains("://")) { + setting.copy(channel).clear(); channel.getUrls().add(line); + } else { + setting.check(line); } } } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Drm.java b/app/src/main/java/com/fongmi/android/tv/bean/Drm.java index 93d2c631a..e37688652 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Drm.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Drm.java @@ -31,11 +31,16 @@ public class Drm { return TextUtils.isEmpty(key) ? "" : key; } + public void setKey(String key) { + this.key = key; + } + private String getType() { return TextUtils.isEmpty(type) ? "" : type; } private UUID getUUID() { + if (getType().contains("playready")) return C.PLAYREADY_UUID; if (getType().contains("widevine")) return C.WIDEVINE_UUID; if (getType().contains("clearkey")) return C.CLEARKEY_UUID; return C.UUID_NIL; diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index e27b6e006..96148c49b 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -131,7 +131,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List } private int getPlayerType(int playerType) { - return playerType != -1 ? playerType : getHome() != null && getHome().getPlayerType() != -1 ? getHome().getPlayerType() : Setting.getLivePlayer(); + return playerType != -1 ? playerType : Setting.getLivePlayer(); } private int getTimeout() { @@ -484,6 +484,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List } private void showControl() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode()) return; mBinding.control.info.setVisibility(mPlayers.isEmpty() ? View.GONE : View.VISIBLE); mBinding.control.cast.setVisibility(mPlayers.isEmpty() ? View.GONE : View.VISIBLE); mBinding.control.right.rotate.setVisibility(isLock() ? View.GONE : View.VISIBLE); @@ -779,7 +780,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List } private void checkError(ErrorEvent event) { - if (getHome() != null && getHome().getPlayerType() == -1 && event.isUrl() && event.getRetry() > 0 && getToggleCount() < 2 && mPlayers.getPlayer() != Players.SYS) { + if (mChannel != null && mChannel.getPlayerType() == -1 && event.isUrl() && event.getRetry() > 0 && getToggleCount() < 2 && mPlayers.getPlayer() != Players.SYS) { toggleCount++; nextPlayer(); } else { diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index afc8c2d2d..481bde138 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -9,6 +9,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.v4.media.MediaMetadataCompat; @@ -979,6 +980,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } private void showControl() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode()) return; mBinding.control.danmu.setVisibility(isLock() || !mBinding.danmaku.isPrepared() ? View.GONE : View.VISIBLE); mBinding.control.setting.setVisibility(mHistory == null || isFullscreen() ? View.GONE : View.VISIBLE); mBinding.control.right.rotate.setVisibility(isFullscreen() && !isLock() ? View.VISIBLE : View.GONE); diff --git a/catvod/src/main/java/com/github/catvod/utils/Util.java b/catvod/src/main/java/com/github/catvod/utils/Util.java index c619f3d9e..46f6d5591 100644 --- a/catvod/src/main/java/com/github/catvod/utils/Util.java +++ b/catvod/src/main/java/com/github/catvod/utils/Util.java @@ -24,8 +24,8 @@ public class Util { public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"; - public static String base64(String ext) { - return base64(ext.getBytes()); + public static String base64(String s) { + return base64(s.getBytes()); } public static String base64(byte[] bytes) { @@ -36,6 +36,12 @@ public class Util { return "Basic " + base64(uri.getUserInfo()); } + public static byte[] hex2byte(String s) { + byte[] bytes = new byte[s.length() / 2]; + for (int i = 0; i < bytes.length; i++) bytes[i] = Integer.valueOf(s.substring(i * 2, i * 2 + 2), 16).byteValue(); + return bytes; + } + public static boolean equals(String name, String md5) { return md5(Path.jar(name)).equalsIgnoreCase(md5); } diff --git a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java index 85ddc5c44..1c0dd3e47 100644 --- a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java +++ b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java @@ -26,8 +26,8 @@ public class IjkMediaCodecInfo { public static final int RANK_NO_SENSE = 0; public MediaCodecInfo mCodecInfo; - public int mRank = 0; public String mMimeType; + public int mRank = 0; private static Map sKnownCodecList; @@ -56,6 +56,14 @@ public class IjkMediaCodecInfo { // MSM8260 // Xiaomi MI 1S sKnownCodecList.put("OMX.qcom.video.decoder.avc", RANK_TESTED); + sKnownCodecList.put("OMX.qcom.video.decoder.avc.secure", RANK_SECURE); + sKnownCodecList.put("OMX.qcom.video.decoder.avc.low_latency", RANK_MAX); + sKnownCodecList.put("OMX.qcom.video.decoder.hevc", RANK_TESTED); + sKnownCodecList.put("OMX.qcom.video.decoder.hevc.secure", RANK_SECURE); + sKnownCodecList.put("OMX.qcom.video.decoder.hevc.low_latency", RANK_MAX); + sKnownCodecList.put("OMX.qcom.video.decoder.vp9", RANK_TESTED); + sKnownCodecList.put("OMX.qcom.video.decoder.vp9.secure", RANK_SECURE); + sKnownCodecList.put("OMX.qcom.video.decoder.vp9.low_latency", RANK_MAX); sKnownCodecList.put("OMX.ittiam.video.decoder.avc", RANK_NO_SENSE); // ----- Samsung ----- @@ -98,38 +106,8 @@ public class IjkMediaCodecInfo { sKnownCodecList.put("OMX.MARVELL.VIDEO.HW.CODA7542DECODER", RANK_TESTED); sKnownCodecList.put("OMX.MARVELL.VIDEO.H264DECODER", RANK_SOFTWARE); - // ----- TODO: need test ----- - sKnownCodecList.remove("OMX.Action.Video.Decoder"); - sKnownCodecList.remove("OMX.allwinner.video.decoder.avc"); - sKnownCodecList.remove("OMX.BRCM.vc4.decoder.avc"); - sKnownCodecList.remove("OMX.brcm.video.h264.hw.decoder"); - sKnownCodecList.remove("OMX.brcm.video.h264.decoder"); - sKnownCodecList.remove("OMX.cosmo.video.decoder.avc"); - sKnownCodecList.remove("OMX.duos.h264.decoder"); - sKnownCodecList.remove("OMX.hantro.81x0.video.decoder"); - sKnownCodecList.remove("OMX.hantro.G1.video.decoder"); - sKnownCodecList.remove("OMX.hisi.video.decoder"); - sKnownCodecList.remove("OMX.LG.decoder.video.avc"); - sKnownCodecList.remove("OMX.MS.AVC.Decoder"); - sKnownCodecList.remove("OMX.RENESAS.VIDEO.DECODER.H264"); - sKnownCodecList.remove("OMX.RTK.video.decoder"); - sKnownCodecList.remove("OMX.sprd.h264.decoder"); - sKnownCodecList.remove("OMX.ST.VFM.H264Dec"); - sKnownCodecList.remove("OMX.vpu.video_decoder.avc"); - sKnownCodecList.remove("OMX.WMT.decoder.avc"); - - // Really ? - sKnownCodecList.remove("OMX.bluestacks.hw.decoder"); - - // --------------- - // Useless codec - // ----- google ----- - sKnownCodecList.put("OMX.google.h264.decoder", RANK_SOFTWARE); - sKnownCodecList.put("OMX.google.h264.lc.decoder", RANK_SOFTWARE); - // ----- huawei k920 ----- - sKnownCodecList.put("OMX.k3.ffmpeg.decoder", RANK_SOFTWARE); - sKnownCodecList.put("OMX.ffmpeg.video.decoder", RANK_SOFTWARE); // ----- unknown ----- + sKnownCodecList.put("OMX.sprd.h264.decoder", RANK_TESTED); sKnownCodecList.put("OMX.sprd.soft.h264.decoder", RANK_SOFTWARE); return sKnownCodecList; @@ -162,8 +140,7 @@ public class IjkMediaCodecInfo { } else if (name.startsWith("omx.mtk.")) { // 1. MTK only works on 4.3 and above // 2. MTK works on MIUI 6 (4.2.1) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) rank = RANK_NO_SENSE; - else rank = RANK_TESTED; + rank = Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 ? RANK_NO_SENSE : RANK_TESTED; } else { Integer knownRank = getKnownCodecList().get(name); if (knownRank != null) {