Support exo drm

pull/137/head
FongMi 2 years ago
parent 48146995e0
commit b32132fa48
  1. 34
      app/src/main/java/com/fongmi/android/tv/api/LiveParser.java
  2. 10
      app/src/main/java/com/fongmi/android/tv/bean/Channel.java
  3. 52
      app/src/main/java/com/fongmi/android/tv/bean/Drm.java
  4. 14
      app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
  5. 2
      app/src/main/java/com/fongmi/android/tv/server/Nano.java

@ -4,6 +4,7 @@ import android.util.Base64;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.bean.Drm;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.utils.Utils;
@ -55,13 +56,16 @@ public class LiveParser {
}
private static void m3u(Live live, String text) {
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("://")) {
channel.getUrls().add(line);
}
@ -113,9 +117,11 @@ public class LiveParser {
private static class Setting {
public String ua;
public String referer;
public Integer player;
private String ua;
private String key;
private String type;
private String referer;
private Integer player;
public static Setting create() {
return new Setting();
@ -125,13 +131,17 @@ public class LiveParser {
if (line.startsWith("ua")) ua(line);
if (line.startsWith("player")) player(line);
if (line.startsWith("referer")) referer(line);
if (line.startsWith("#KODIPROP:inputstream.adaptive.license_key")) key(line);
if (line.startsWith("#KODIPROP:inputstream.adaptive.license_type")) type(line);
if (line.contains("#genre#")) clear();
}
public void copy(Channel channel) {
public Setting copy(Channel channel) {
if (ua != null) channel.setUa(ua);
if (referer != null) channel.setReferer(referer);
if (player != null) channel.setPlayerType(player);
if (key != null && type != null) channel.setDrm(Drm.create(key, type));
return this;
}
private void ua(String line) {
@ -158,6 +168,22 @@ public class LiveParser {
}
}
private void key(String line) {
try {
key = line.split("=")[1].trim();
} catch (Exception e) {
key = null;
}
}
private void type(String line) {
try {
type = line.split("=")[1].trim();
} catch (Exception e) {
type = null;
}
}
private void clear() {
player = null;
referer = null;

@ -39,6 +39,8 @@ public class Channel {
private JsonElement header;
@SerializedName("playerType")
private Integer playerType;
@SerializedName("drm")
private Drm drm;
private boolean selected;
private Group group;
@ -141,6 +143,14 @@ public class Channel {
this.playerType = playerType;
}
public Drm getDrm() {
return drm;
}
public void setDrm(Drm drm) {
this.drm = drm;
}
public Group getGroup() {
return group;
}

@ -0,0 +1,52 @@
package com.fongmi.android.tv.bean;
import android.text.TextUtils;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import com.fongmi.android.tv.server.Server;
import com.github.catvod.utils.Util;
import com.google.gson.annotations.SerializedName;
import java.util.UUID;
public class Drm {
@SerializedName("key")
private String key;
@SerializedName("type")
private String type;
public static Drm create(String key, String type) {
return new Drm(key, type);
}
private Drm(String key, String type) {
this.key = key;
this.type = type;
}
private String getKey() {
return TextUtils.isEmpty(key) ? "" : key;
}
private String getType() {
return TextUtils.isEmpty(type) ? "" : type;
}
private UUID getUUID() {
if (getType().contains("widevine")) return C.WIDEVINE_UUID;
if (getType().contains("clearkey")) return C.CLEARKEY_UUID;
return C.UUID_NIL;
}
private String getUri() {
if (getKey().startsWith("http")) return getKey();
return Server.get().getAddress("license/") + Util.base64(getKey());
}
public MediaItem.DrmConfiguration get() {
return new MediaItem.DrmConfiguration.Builder(getUUID()).setLicenseUri(getUri()).build();
}
}

@ -37,6 +37,7 @@ 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;
@ -98,27 +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(), errorCode);
return getSource(channel.getHeaders(), channel.getUrl(), null, Collections.emptyList(), channel.getDrm(), errorCode);
}
public static MediaSource getSource(Map<String, String> 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<String, String> headers, String url, String format, List<Sub> subs, int errorCode) {
private static MediaSource getSource(Map<String, String> headers, String url, String format, List<Sub> 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<Sub> subs) {
private static MediaItem getMediaItem(Uri uri, String mimeType, List<Sub> 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));

@ -1,6 +1,7 @@
package com.fongmi.android.tv.server;
import android.net.Uri;
import android.util.Base64;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
@ -94,6 +95,7 @@ public class Nano extends NanoHTTPD {
else if (url.startsWith("/newFolder")) return doNewFolder(session.getParms());
else if (url.startsWith("/delFolder") || url.startsWith("/delFile")) return doDelFolder(session.getParms());
else if (url.startsWith("/tvbus")) return createSuccessResponse(LiveConfig.get().getHome().getCore().getResp());
else if (url.startsWith("/license/")) return createSuccessResponse(new String(Base64.decode(url.substring(9), Base64.DEFAULT)));
break;
}
return createErrorResponse(NanoHTTPD.Response.Status.NOT_FOUND, "Not Found");

Loading…
Cancel
Save