diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Channel.java b/app/src/main/java/com/fongmi/android/tv/bean/Channel.java index 500e4fe8e..55a69645f 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Channel.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Channel.java @@ -37,6 +37,8 @@ public class Channel { private String referer; @SerializedName("header") private JsonElement header; + @SerializedName("drm") + private Drm drm; private boolean selected; private Group group; @@ -131,6 +133,14 @@ public class Channel { this.header = header; } + public Drm getDrm() { + return drm; + } + + public void setDrm(Drm drm) { + this.drm = drm; + } + public Group getGroup() { return group; } 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 new file mode 100644 index 000000000..aec17a08d --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/bean/Drm.java @@ -0,0 +1,33 @@ +package com.fongmi.android.tv.bean; + +import androidx.media3.common.C; +import androidx.media3.common.MediaItem; + +import com.google.gson.annotations.SerializedName; + +import java.nio.charset.StandardCharsets; + +public class Drm { + + @SerializedName("licenseType") + private String licenseType; + @SerializedName("licenseKey") + private String licenseKey; + + public Drm(String licenseType, String licenseKey) { + this.licenseType = licenseType; + this.licenseKey = licenseKey; + } + + public String getLicenseType() { + return licenseType; + } + + public String getLicenseKey() { + return licenseKey; + } + + public MediaItem.DrmConfiguration get() { + return new MediaItem.DrmConfiguration.Builder(C.CLEARKEY_UUID).setKeySetId(getLicenseKey().getBytes(StandardCharsets.UTF_8)).build(); + } +} diff --git a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java index 4a2afec31..9b249dd76 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java @@ -36,6 +36,8 @@ import androidx.media3.ui.CaptionStyleCompat; import com.fongmi.android.tv.App; import com.fongmi.android.tv.Setting; +import com.fongmi.android.tv.bean.Channel; +import com.fongmi.android.tv.bean.Drm; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.bean.Sub; import com.fongmi.android.tv.utils.Sniffer; @@ -97,23 +99,28 @@ public class ExoUtil { } public static MediaSource getSource(Result result, int errorCode) { - return getSource(result.getHeaders(), result.getRealUrl(), result.getFormat(), result.getSubs(), errorCode); + return getSource(result.getHeaders(), result.getRealUrl(), result.getFormat(), result.getSubs(), null, errorCode); + } + + public static MediaSource getSource(Channel channel, int errorCode) { + return getSource(channel.getHeaders(), channel.getUrl(), null, Collections.emptyList(), channel.getDrm(), errorCode); } public static MediaSource getSource(Map headers, String url, int errorCode) { - return getSource(headers, url, null, Collections.emptyList(), errorCode); + return getSource(headers, url, null, Collections.emptyList(), null, errorCode); } - private static MediaSource getSource(Map headers, String url, String format, List subs, int errorCode) { + private static MediaSource getSource(Map headers, String url, String format, List subs, Drm drm, int errorCode) { Uri uri = Uri.parse(url.trim().replace("\\", "")); String mimeType = getMimeType(format, errorCode); if (uri.getUserInfo() != null) headers.put(HttpHeaders.AUTHORIZATION, "Basic " + Util.base64(uri.getUserInfo())); - return new DefaultMediaSourceFactory(getDataSourceFactory(headers), getExtractorsFactory()).createMediaSource(getMediaItem(uri, mimeType, subs)); + return new DefaultMediaSourceFactory(getDataSourceFactory(headers), getExtractorsFactory()).createMediaSource(getMediaItem(uri, mimeType, subs, drm)); } - private static MediaItem getMediaItem(Uri uri, String mimeType, List subs) { + private static MediaItem getMediaItem(Uri uri, String mimeType, List subs, Drm drm) { MediaItem.Builder builder = new MediaItem.Builder().setUri(uri); if (subs.size() > 0) builder.setSubtitleConfigurations(getSubtitles(subs)); + if (drm != null) builder.setDrmConfiguration(drm.get()); builder.setAllowChunklessPreparation(Players.isHard()); if (mimeType != null) builder.setMimeType(mimeType); builder.setAds(Sniffer.getRegex(uri)); diff --git a/app/src/main/java/com/fongmi/android/tv/player/IjkUtil.java b/app/src/main/java/com/fongmi/android/tv/player/IjkUtil.java index aa7fdf299..b9cd6ff82 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/IjkUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/player/IjkUtil.java @@ -2,6 +2,7 @@ package com.fongmi.android.tv.player; import android.net.Uri; +import com.fongmi.android.tv.bean.Channel; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.server.Server; import com.fongmi.android.tv.utils.Sniffer; @@ -18,6 +19,10 @@ public class IjkUtil { return getSource(result.getHeaders(), result.getRealUrl()); } + public static MediaSource getSource(Channel channel) { + return getSource(channel.getHeaders(), channel.getUrl()); + } + public static MediaSource getSource(Map headers, String url) { Uri uri = Uri.parse(url.trim().replace("\\", "")); if (Sniffer.isAds(uri)) uri = Uri.parse(Server.get().getAddress().concat("/m3u8?url=").concat(URLEncoder.encode(url))); diff --git a/app/src/main/java/com/fongmi/android/tv/player/Players.java b/app/src/main/java/com/fongmi/android/tv/player/Players.java index 8363eb396..2ee08d56c 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/Players.java +++ b/app/src/main/java/com/fongmi/android/tv/player/Players.java @@ -296,7 +296,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic if (channel.getUrl().isEmpty()) { ErrorEvent.url(); } else { - setMediaSource(channel.getHeaders(), channel.getUrl()); + setMediaSource(channel); } } @@ -365,6 +365,14 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic setTimeoutCheck(result.getRealUrl()); } + private void setMediaSource(Channel channel) { + SpiderDebug.log(errorCode + "," + channel.getUrl()); + if (isIjk()) ijkPlayer.setMediaSource(IjkUtil.getSource(channel)); + if (isExo()) exoPlayer.setMediaSource(ExoUtil.getSource(channel, errorCode)); + if (isExo()) exoPlayer.prepare(); + setTimeoutCheck(channel.getUrl()); + } + private void setMediaSource(Map headers, String url) { SpiderDebug.log(errorCode + "," + url); if (isIjk()) ijkPlayer.setMediaSource(IjkUtil.getSource(headers, url));