From 63249734a36e5f58ef071744fcaafcc07ea270e9 Mon Sep 17 00:00:00 2001 From: jhengazuki Date: Sat, 29 Nov 2025 15:08:29 +0800 Subject: [PATCH] Optimize track selection --- .../{34.json => 35.json} | 25 +++----- .../com/fongmi/android/tv/bean/Track.java | 33 ++++------- .../com/fongmi/android/tv/db/AppDatabase.java | 3 +- .../com/fongmi/android/tv/db/Migrations.java | 9 +++ .../com/fongmi/android/tv/player/Players.java | 19 +++--- .../fongmi/android/tv/player/exo/ExoUtil.java | 32 ---------- .../android/tv/player/exo/TrackUtil.java | 59 +++++++++++++++++++ .../android/tv/ui/dialog/TrackDialog.java | 7 ++- 8 files changed, 103 insertions(+), 84 deletions(-) rename app/schemas/com.fongmi.android.tv.db.AppDatabase/{34.json => 35.json} (95%) create mode 100644 app/src/main/java/com/fongmi/android/tv/player/exo/TrackUtil.java diff --git a/app/schemas/com.fongmi.android.tv.db.AppDatabase/34.json b/app/schemas/com.fongmi.android.tv.db.AppDatabase/35.json similarity index 95% rename from app/schemas/com.fongmi.android.tv.db.AppDatabase/34.json rename to app/schemas/com.fongmi.android.tv.db.AppDatabase/35.json index 8bc3b819a..a88d97377 100644 --- a/app/schemas/com.fongmi.android.tv.db.AppDatabase/34.json +++ b/app/schemas/com.fongmi.android.tv.db.AppDatabase/35.json @@ -1,8 +1,8 @@ { "formatVersion": 1, "database": { - "version": 34, - "identityHash": "f6dff07c7842200b0224662b90261e07", + "version": 35, + "identityHash": "8191bb223b1cde184fbb43d20d39d851", "entities": [ { "tableName": "Keep", @@ -120,7 +120,7 @@ }, { "tableName": "Track", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type` INTEGER NOT NULL, `group` INTEGER NOT NULL, `track` INTEGER NOT NULL, `key` TEXT, `name` TEXT, `selected` INTEGER NOT NULL)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type` INTEGER NOT NULL, `key` TEXT, `name` TEXT, `format` TEXT, `selected` INTEGER NOT NULL)", "fields": [ { "fieldPath": "id", @@ -134,18 +134,6 @@ "affinity": "INTEGER", "notNull": true }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "track", - "columnName": "track", - "affinity": "INTEGER", - "notNull": true - }, { "fieldPath": "key", "columnName": "key", @@ -156,6 +144,11 @@ "columnName": "name", "affinity": "TEXT" }, + { + "fieldPath": "format", + "columnName": "format", + "affinity": "TEXT" + }, { "fieldPath": "selected", "columnName": "selected", @@ -410,7 +403,7 @@ ], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f6dff07c7842200b0224662b90261e07')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8191bb223b1cde184fbb43d20d39d851')" ] } } \ No newline at end of file diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Track.java b/app/src/main/java/com/fongmi/android/tv/bean/Track.java index 2eda1a707..ede45879f 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Track.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Track.java @@ -2,7 +2,6 @@ package com.fongmi.android.tv.bean; import android.text.TextUtils; -import androidx.annotation.NonNull; import androidx.room.Entity; import androidx.room.Index; import androidx.room.PrimaryKey; @@ -18,15 +17,15 @@ public class Track { @PrimaryKey(autoGenerate = true) private int id; private int type; - private int group; - private int track; private String key; private String name; + private String format; private boolean selected; - public Track(int type, String name) { + public Track(int type, String name, String format) { this.type = type; this.name = name; + this.format = format; } public int getId() { @@ -45,27 +44,11 @@ public class Track { this.type = type; } - public int getGroup() { - return group; - } - - public void setGroup(int group) { - this.group = group; - } - - public int getTrack() { - return track; - } - - public void setTrack(int track) { - this.track = track; - } - public String getKey() { return key; } - public void setKey(@NonNull String key) { + public void setKey(String key) { this.key = key; } @@ -77,6 +60,14 @@ public class Track { this.name = name; } + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + public boolean isSelected() { return selected; } diff --git a/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java b/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java index 6ad833c6a..bf849cc30 100644 --- a/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java +++ b/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java @@ -35,7 +35,7 @@ import java.util.Locale; @Database(entities = {Keep.class, Site.class, Live.class, Track.class, Config.class, Device.class, History.class}, version = AppDatabase.VERSION) public abstract class AppDatabase extends RoomDatabase { - public static final int VERSION = 34; + public static final int VERSION = 35; public static final String NAME = "tv"; public static final String SYMBOL = "@@@"; @@ -95,6 +95,7 @@ public abstract class AppDatabase extends RoomDatabase { .addMigrations(Migrations.MIGRATION_31_32) .addMigrations(Migrations.MIGRATION_32_33) .addMigrations(Migrations.MIGRATION_33_34) + .addMigrations(Migrations.MIGRATION_34_35) .fallbackToDestructiveMigration(true) .allowMainThreadQueries().build(); } diff --git a/app/src/main/java/com/fongmi/android/tv/db/Migrations.java b/app/src/main/java/com/fongmi/android/tv/db/Migrations.java index 97057ecb2..f6744c840 100644 --- a/app/src/main/java/com/fongmi/android/tv/db/Migrations.java +++ b/app/src/main/java/com/fongmi/android/tv/db/Migrations.java @@ -40,4 +40,13 @@ public class Migrations { database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_Track_key_type` ON `Track` (`key`, `type`)"); } }; + + public static final Migration MIGRATION_34_35 = new Migration(34, 35) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("DROP TABLE Track"); + database.execSQL("CREATE TABLE Track (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type` INTEGER NOT NULL, `key` TEXT, `name` TEXT, `format` TEXT, `selected` INTEGER NOT NULL)"); + database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_Track_key_type` ON `Track` (`key`, `type`)"); + } + }; } 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 08a76c72b..17b98bed1 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 @@ -53,6 +53,7 @@ import com.fongmi.android.tv.impl.SessionCallback; import com.fongmi.android.tv.player.danmaku.DanPlayer; import com.fongmi.android.tv.player.exo.ErrorMsgProvider; import com.fongmi.android.tv.player.exo.ExoUtil; +import com.fongmi.android.tv.player.exo.TrackUtil; import com.fongmi.android.tv.server.Server; import com.fongmi.android.tv.utils.FileUtil; import com.fongmi.android.tv.utils.ImgUtil; @@ -104,6 +105,7 @@ public class Players implements Player.Listener, ParseCallback { private Drm drm; private Sub sub; + private boolean initTrack; private int decode; private int retry; @@ -203,6 +205,7 @@ public class Players implements Player.Listener, ParseCallback { public void reset() { removeTimeoutCheck(); + initTrack = false; retry = 0; } @@ -252,7 +255,7 @@ public class Players implements Player.Listener, ParseCallback { } public boolean haveTrack(int type) { - return exoPlayer != null && ExoUtil.haveTrack(exoPlayer.getCurrentTracks(), type); + return exoPlayer != null && TrackUtil.count(exoPlayer.getCurrentTracks(), type) > 0; } public boolean haveDanmaku() { @@ -502,19 +505,13 @@ public class Players implements Player.Listener, ParseCallback { } public void resetTrack() { - if (exoPlayer != null) ExoUtil.resetTrack(exoPlayer); + if (exoPlayer != null) TrackUtil.reset(exoPlayer); } public void setTrack(List tracks) { - for (Track track : tracks) setTrack(track); - } - - private void setTrack(Track item) { - if (item.isSelected()) { - ExoUtil.selectTrack(exoPlayer, item.getGroup(), item.getTrack()); - } else { - ExoUtil.deselectTrack(exoPlayer, item.getGroup(), item.getTrack()); - } + if (initTrack) return; + if (exoPlayer != null && !tracks.isEmpty()) TrackUtil.setTrackSelection(exoPlayer, tracks); + initTrack = true; } private void setPlaybackState(int state) { diff --git a/app/src/main/java/com/fongmi/android/tv/player/exo/ExoUtil.java b/app/src/main/java/com/fongmi/android/tv/player/exo/ExoUtil.java index 3d9f296ed..c93155dee 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/exo/ExoUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/player/exo/ExoUtil.java @@ -10,11 +10,8 @@ import android.view.accessibility.CaptioningManager; import androidx.media3.common.MediaItem; import androidx.media3.common.MimeTypes; import androidx.media3.common.PlaybackException; -import androidx.media3.common.TrackSelectionOverride; -import androidx.media3.common.Tracks; import androidx.media3.common.util.Util; import androidx.media3.exoplayer.DefaultLoadControl; -import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.LoadControl; import androidx.media3.exoplayer.RenderersFactory; import androidx.media3.exoplayer.source.MediaSource; @@ -70,16 +67,6 @@ public class ExoUtil { return Setting.isCaption() ? CaptionStyleCompat.createFromCaptionStyle(((CaptioningManager) App.get().getSystemService(Context.CAPTIONING_SERVICE)).getUserStyle()) : new CaptionStyleCompat(Color.WHITE, Color.TRANSPARENT, Color.TRANSPARENT, CaptionStyleCompat.EDGE_TYPE_OUTLINE, Color.BLACK, null); } - public static boolean haveTrack(Tracks tracks, int type) { - int count = 0; - for (Tracks.Group trackGroup : tracks.getGroups()) if (trackGroup.getType() == type) count += trackGroup.length; - return count > 0; - } - - public static void resetTrack(ExoPlayer player) { - player.setTrackSelectionParameters(player.getTrackSelectionParameters().buildUpon().clearOverrides().build()); - } - public static void setSubtitleView(PlayerView exo) { exo.getSubtitleView().setStyle(getCaptionStyle()); exo.getSubtitleView().setApplyEmbeddedFontSizes(false); @@ -126,23 +113,4 @@ public class ExoUtil { if (subs != null) for (Sub sub : subs) configs.add(sub.config()); return configs; } - - public static void selectTrack(ExoPlayer player, int groupIndex, int trackIndex) { - Tracks currentTracks = player.getCurrentTracks(); - if (groupIndex >= currentTracks.getGroups().size()) return; - Tracks.Group trackGroupInfo = currentTracks.getGroups().get(groupIndex); - if (trackIndex < 0 || trackIndex >= trackGroupInfo.length) return; - TrackSelectionOverride override = new TrackSelectionOverride(trackGroupInfo.getMediaTrackGroup(), trackIndex); - player.setTrackSelectionParameters(player.getTrackSelectionParameters().buildUpon().setOverrideForType(override).build()); - } - - public static void deselectTrack(ExoPlayer player, int groupIndex, int trackIndex) { - Tracks currentTracks = player.getCurrentTracks(); - if (groupIndex >= currentTracks.getGroups().size()) return; - Tracks.Group trackGroupInfo = currentTracks.getGroups().get(groupIndex); - List trackIndices = new ArrayList<>(); - for (int i = 0; i < trackGroupInfo.length; i++) if (i != trackIndex && trackGroupInfo.isTrackSelected(i)) trackIndices.add(i); - TrackSelectionOverride override = new TrackSelectionOverride(trackGroupInfo.getMediaTrackGroup(), trackIndices); - player.setTrackSelectionParameters(player.getTrackSelectionParameters().buildUpon().setOverrideForType(override).build()); - } } diff --git a/app/src/main/java/com/fongmi/android/tv/player/exo/TrackUtil.java b/app/src/main/java/com/fongmi/android/tv/player/exo/TrackUtil.java new file mode 100644 index 000000000..c6b6f6853 --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/player/exo/TrackUtil.java @@ -0,0 +1,59 @@ +package com.fongmi.android.tv.player.exo; + +import androidx.media3.common.TrackGroup; +import androidx.media3.common.TrackSelectionOverride; +import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; +import androidx.media3.exoplayer.ExoPlayer; + +import com.fongmi.android.tv.bean.Track; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TrackUtil { + + private record TrackInfo(Tracks.Group trackGroup, int trackIndex) { + } + + public static int count(Tracks tracks, int type) { + return tracks.getGroups().stream().filter(trackGroup -> trackGroup.getType() == type).mapToInt(trackGroup -> trackGroup.length).sum(); + } + + public static void reset(ExoPlayer player) { + player.setTrackSelectionParameters(player.getTrackSelectionParameters().buildUpon().clearOverrides().build()); + } + + private static TrackInfo find(ExoPlayer player, Track track) { + Tracks currentTracks = player.getCurrentTracks(); + for (Tracks.Group trackGroup : currentTracks.getGroups()) { + if (trackGroup.getType() != track.getType()) continue; + for (int i = 0; i < trackGroup.length; i++) { + if (track.getFormat().equals(trackGroup.getTrackFormat(i).id)) { + return new TrackInfo(trackGroup, i); + } + } + } + return null; + } + + public static void setTrackSelection(ExoPlayer player, List tracks) { + Map mediaGroupMapByType = new HashMap<>(); + Map selectedIndexMapByType = new HashMap<>(); + for (Track track : tracks) { + TrackInfo info = find(player, track); + if (info == null) continue; + int type = info.trackGroup.getType(); + mediaGroupMapByType.put(type, info.trackGroup.getMediaTrackGroup()); + if (track.isSelected()) selectedIndexMapByType.put(type, info.trackIndex); + } + TrackSelectionParameters.Builder builder = player.getTrackSelectionParameters().buildUpon(); + mediaGroupMapByType.forEach((type, mediaGroup) -> { + Integer selectedIndex = selectedIndexMapByType.get(type); + List indices = selectedIndex != null ? List.of(selectedIndex) : List.of(); + builder.setOverrideForType(new TrackSelectionOverride(mediaGroup, indices)); + }); + player.setTrackSelectionParameters(builder.build()); + } +} diff --git a/app/src/main/java/com/fongmi/android/tv/ui/dialog/TrackDialog.java b/app/src/main/java/com/fongmi/android/tv/ui/dialog/TrackDialog.java index bb832ef26..295290d14 100644 --- a/app/src/main/java/com/fongmi/android/tv/ui/dialog/TrackDialog.java +++ b/app/src/main/java/com/fongmi/android/tv/ui/dialog/TrackDialog.java @@ -13,6 +13,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.media3.common.C; +import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; import androidx.media3.common.Tracks; import androidx.media3.ui.DefaultTrackNameProvider; @@ -115,10 +116,10 @@ public final class TrackDialog extends BaseDialog implements TrackAdapter.OnClic Tracks.Group trackGroup = groups.get(i); if (trackGroup.getType() != type) continue; for (int j = 0; j < trackGroup.length; j++) { - Track item = new Track(type, provider.getTrackName(trackGroup.getTrackFormat(j))); + Format format = trackGroup.getTrackFormat(j); + String name = provider.getTrackName(format); + Track item = new Track(type, name, format.id); item.setSelected(trackGroup.isTrackSelected(j)); - item.setGroup(i); - item.setTrack(j); items.add(item); } }