diff --git a/app/build.gradle b/app/build.gradle
index e46fec9a6..c8e43568f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,7 +14,7 @@ android {
//noinspection ExpiredTargetSdkVersion
targetSdk 28
versionCode 237
- versionName "0604"
+ versionName "0607"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
@@ -121,6 +121,7 @@ dependencies {
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'androidx.room:room-runtime:2.6.1'
implementation 'androidx.media:media:1.7.0'
+ implementation ('com.github.anilbeesetti.nextlib:nextlib-media3ext:0.7.1') { exclude group: 'androidx.media3', module: 'media3-exoplayer' }
implementation 'cat.ereza:customactivityoncrash:2.4.0'
implementation 'com.github.bassaer:materialdesigncolors:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.16.0'
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
index f51815d6f..8b6bb1110 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
@@ -69,7 +69,7 @@ public class CastActivity extends BaseActivity implements CustomKeyDownCast.List
private int scale;
private PlayerView getExo() {
- return Setting.getRender() == 0 ? mBinding.surface : mBinding.texture;
+ return mBinding.exo;
}
private IjkVideoView getIjk() {
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 ab36fcfd6..6cdd828b8 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
@@ -105,7 +105,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP
}
private PlayerView getExo() {
- return Setting.getRender() == 0 ? mBinding.surface : mBinding.texture;
+ return mBinding.exo;
}
private IjkVideoView getIjk() {
@@ -756,7 +756,6 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP
setMetadata();
hideProgress();
mPlayers.reset();
- setSpeedVisible();
setTrackVisible(true);
mBinding.widget.size.setText(mPlayers.getSizeText());
break;
@@ -766,12 +765,9 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP
}
}
- private void setSpeedVisible() {
- mBinding.control.speed.setVisibility(mPlayers.isVod() ? View.VISIBLE : View.GONE);
- }
-
private void setTrackVisible(boolean visible) {
mBinding.control.text.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_TEXT) ? View.VISIBLE : View.GONE);
+ mBinding.control.speed.setVisibility(visible && mPlayers.isVod() ? View.VISIBLE : View.GONE);
mBinding.control.audio.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_AUDIO) ? View.VISIBLE : View.GONE);
mBinding.control.video.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_VIDEO) ? View.VISIBLE : View.GONE);
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
index 09bd544f7..a6ded15bf 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
@@ -31,6 +31,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
private String[] scale;
private String[] http;
private String[] flag;
+ private String[] rtsp;
public static void start(Activity activity) {
activity.startActivity(new Intent(activity, SettingPlayerActivity.class));
@@ -53,6 +54,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.tunnelText.setText(getSwitch(Setting.isTunnel()));
mBinding.bufferText.setText(String.valueOf(Setting.getBuffer()));
mBinding.subtitleText.setText(String.valueOf(Setting.getSubtitle()));
+ mBinding.rtspText.setText((rtsp = ResUtil.getStringArray(R.array.select_rtsp))[Setting.getRtsp()]);
mBinding.flagText.setText((flag = ResUtil.getStringArray(R.array.select_flag))[Setting.getFlag()]);
mBinding.httpText.setText((http = ResUtil.getStringArray(R.array.select_exo_http))[Setting.getHttp()]);
mBinding.scaleText.setText((scale = ResUtil.getStringArray(R.array.select_scale))[Setting.getScale()]);
@@ -65,6 +67,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
@Override
protected void initEvent() {
mBinding.ua.setOnClickListener(this::onUa);
+ mBinding.rtsp.setOnClickListener(this::setRtsp);
mBinding.http.setOnClickListener(this::setHttp);
mBinding.flag.setOnClickListener(this::setFlag);
mBinding.scale.setOnClickListener(this::setScale);
@@ -95,6 +98,12 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
Setting.putUa(ua);
}
+ private void setRtsp(View view) {
+ int index = Setting.getRtsp();
+ Setting.putRtsp(index = index == rtsp.length - 1 ? 0 : ++index);
+ mBinding.rtspText.setText(rtsp[index]);
+ }
+
private void setHttp(View view) {
int index = Setting.getHttp();
Setting.putHttp(index = index == http.length - 1 ? 0 : ++index);
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
index 7e1fd73a4..e217fbe0d 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
@@ -280,7 +280,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
}
private PlayerView getExo() {
- return Setting.getRender() == 0 ? mBinding.surface : mBinding.texture;
+ return mBinding.exo;
}
private IjkVideoView getIjk() {
diff --git a/app/src/leanback/res/layout/activity_cast.xml b/app/src/leanback/res/layout/activity_cast.xml
index 8786dd095..14c219bc7 100644
--- a/app/src/leanback/res/layout/activity_cast.xml
+++ b/app/src/leanback/res/layout/activity_cast.xml
@@ -8,20 +8,11 @@
android:keepScreenOn="true">
-
-
+ app:surface_type="none" />
-
-
+ app:surface_type="none" />
+
+
+
+
+
+
+
+
-
-
+ app:surface_type="none" />
getHeaders() {
return headers == null ? new HashMap<>() : checkUa(headers);
}
@@ -280,6 +287,10 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic
return TextUtils.isEmpty(getUrl());
}
+ public boolean isLive() {
+ return getDuration() < 5 * 60 * 1000;
+ }
+
public boolean isVod() {
return getDuration() > 5 * 60 * 1000;
}
diff --git a/app/src/main/java/com/fongmi/android/tv/player/custom/NextRenderersFactory.java b/app/src/main/java/com/fongmi/android/tv/player/custom/NextRenderersFactory.java
new file mode 100644
index 000000000..f4d01fefa
--- /dev/null
+++ b/app/src/main/java/com/fongmi/android/tv/player/custom/NextRenderersFactory.java
@@ -0,0 +1,56 @@
+package com.fongmi.android.tv.player.custom;
+
+import android.content.Context;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.media3.common.util.Log;
+import androidx.media3.exoplayer.DefaultRenderersFactory;
+import androidx.media3.exoplayer.Renderer;
+import androidx.media3.exoplayer.audio.AudioRendererEventListener;
+import androidx.media3.exoplayer.audio.AudioSink;
+import androidx.media3.exoplayer.mediacodec.MediaCodecSelector;
+import androidx.media3.exoplayer.video.VideoRendererEventListener;
+
+import java.util.ArrayList;
+
+import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.FfmpegAudioRenderer;
+import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.FfmpegVideoRenderer;
+
+public class NextRenderersFactory extends DefaultRenderersFactory {
+
+ private static final String TAG = NextRenderersFactory.class.getSimpleName();
+
+ public NextRenderersFactory(@NonNull Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void buildAudioRenderers(@NonNull Context context, int extensionRendererMode, @NonNull MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, @NonNull AudioSink audioSink, @NonNull Handler eventHandler, @NonNull AudioRendererEventListener eventListener, @NonNull ArrayList out) {
+ super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, audioSink, eventHandler, eventListener, out);
+ int extensionRendererIndex = out.size();
+ if (extensionRendererMode == EXTENSION_RENDERER_MODE_PREFER) {
+ extensionRendererIndex--;
+ }
+ try {
+ Renderer renderer = new FfmpegAudioRenderer(eventHandler, eventListener, audioSink);
+ out.add(extensionRendererIndex++, renderer);
+ Log.i(TAG, "Loaded FfmpegAudioRenderer.");
+ } catch (Exception e) {
+ throw new RuntimeException("Error instantiating Ffmpeg extension", e);
+ }
+ }
+
+ @Override
+ protected void buildVideoRenderers(@NonNull Context context, int extensionRendererMode, @NonNull MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, @NonNull Handler eventHandler, @NonNull VideoRendererEventListener eventListener, long allowedVideoJoiningTimeMs, @NonNull ArrayList out) {
+ super.buildVideoRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, eventHandler, eventListener, allowedVideoJoiningTimeMs, out);
+ int extensionRendererIndex = out.size();
+ try {
+ Renderer renderer = new FfmpegVideoRenderer(allowedVideoJoiningTimeMs, eventHandler, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
+ out.add(extensionRendererIndex++, renderer);
+ Log.i(TAG, "Loaded FfmpegVideoRenderer.");
+ } catch (Exception e) {
+ throw new RuntimeException("Error instantiating Ffmpeg extension", e);
+ }
+ }
+}
diff --git a/app/src/main/java/com/fongmi/android/tv/player/TrackNameProvider.java b/app/src/main/java/com/fongmi/android/tv/player/custom/TrackNameProvider.java
similarity index 99%
rename from app/src/main/java/com/fongmi/android/tv/player/TrackNameProvider.java
rename to app/src/main/java/com/fongmi/android/tv/player/custom/TrackNameProvider.java
index 4a15a7995..4c01bb7d3 100644
--- a/app/src/main/java/com/fongmi/android/tv/player/TrackNameProvider.java
+++ b/app/src/main/java/com/fongmi/android/tv/player/custom/TrackNameProvider.java
@@ -1,4 +1,4 @@
-package com.fongmi.android.tv.player;
+package com.fongmi.android.tv.player.custom;
import android.content.res.Resources;
import android.text.TextUtils;
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 689a229c5..f1cbb6d0c 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
@@ -20,7 +20,7 @@ import com.fongmi.android.tv.bean.Sub;
import com.fongmi.android.tv.bean.Track;
import com.fongmi.android.tv.databinding.DialogTrackBinding;
import com.fongmi.android.tv.player.Players;
-import com.fongmi.android.tv.player.TrackNameProvider;
+import com.fongmi.android.tv.player.custom.TrackNameProvider;
import com.fongmi.android.tv.ui.adapter.TrackAdapter;
import com.fongmi.android.tv.ui.custom.SpaceItemDecoration;
import com.fongmi.android.tv.utils.FileChooser;
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index faaa04711..7a4e096fc 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -1,7 +1,7 @@
- 影视
+ OK影视
再按一次返回键退出
@@ -122,6 +122,7 @@
隧道模式
连线方式
缓冲时间
+ RTSP 通道
User-Agent
@@ -309,4 +310,9 @@
- 选择字幕
+
+ - UDP
+ - TCP
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index af89bb2f5..e6ff78d0a 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -1,7 +1,7 @@
- 影視
+ OK影視
再按一次返回鍵退出
@@ -122,6 +122,7 @@
隧道模式
連線方式
緩衝時間
+ RTSP 通道
User-Agent
@@ -310,4 +311,9 @@
- 選擇字幕
+
+ - UDP
+ - TCP
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c4ab9337e..5ada77697 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,7 +1,7 @@
- TV
+ OKTV
Press back again to exit
@@ -122,6 +122,7 @@
Tunnel mode
HTTP method
Buffer time
+ RTSP channel
User-Agent
@@ -314,4 +315,9 @@
- Select subtitle track
+
+ - UDP
+ - TCP
+
+
\ No newline at end of file
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 a33ddaf7d..92a696a08 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
@@ -117,7 +117,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
}
private PlayerView getExo() {
- return Setting.getRender() == 0 ? mBinding.surface : mBinding.texture;
+ return mBinding.exo;
}
private IjkVideoView getIjk() {
@@ -819,7 +819,6 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
resetToggle();
hideProgress();
mPlayers.reset();
- setSpeedVisible();
setTrackVisible(true);
checkPlayImg(mPlayers.isPlaying());
mBinding.control.size.setText(mPlayers.getSizeText());
@@ -831,12 +830,9 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
}
}
- private void setSpeedVisible() {
- mBinding.control.action.speed.setVisibility(mPlayers.isVod() ? View.VISIBLE : View.GONE);
- }
-
private void setTrackVisible(boolean visible) {
mBinding.control.action.text.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_TEXT) ? View.VISIBLE : View.GONE);
+ mBinding.control.action.speed.setVisibility(visible && mPlayers.isVod() ? View.VISIBLE : View.GONE);
mBinding.control.action.audio.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_AUDIO) ? View.VISIBLE : View.GONE);
mBinding.control.action.video.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_VIDEO) ? View.VISIBLE : View.GONE);
}
@@ -1143,7 +1139,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
super.onUserLeaveHint();
if (isRedirect()) return;
if (isLock()) App.post(this::onLock, 500);
- if (mPlayers.haveTrack(C.TRACK_TYPE_VIDEO)) mPiP.enter(this, Setting.getLiveScale() == 2);
+ if (mPlayers.haveTrack(C.TRACK_TYPE_VIDEO)) mPiP.enter(this, mPlayers.getVideoSize(), Setting.getLiveScale());
}
@Override
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 a150294f3..0e86fc6a5 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
@@ -249,7 +249,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
}
private PlayerView getExo() {
- return Setting.getRender() == 0 ? mBinding.surface : mBinding.texture;
+ return mBinding.exo;
}
private IjkVideoView getIjk() {
@@ -1700,7 +1700,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
super.onUserLeaveHint();
if (isRedirect()) return;
if (isLock()) App.post(this::onLock, 500);
- if (mPlayers.haveTrack(C.TRACK_TYPE_VIDEO)) mPiP.enter(this, getScale() == 2);
+ if (mPlayers.haveTrack(C.TRACK_TYPE_VIDEO)) mPiP.enter(this, mPlayers.getVideoSize(), getScale());
}
@Override
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java
index cdae5eeee..328d927f4 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java
@@ -36,6 +36,7 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
private String[] scale;
private String[] http;
private String[] flag;
+ private String[] rtsp;
public static SettingPlayerFragment newInstance() {
return new SettingPlayerFragment();
@@ -59,6 +60,7 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
mBinding.bufferText.setText(String.valueOf(Setting.getBuffer()));
mBinding.subtitleText.setText(String.valueOf(Setting.getSubtitle()));
mBinding.danmuLoadText.setText(getSwitch(Setting.isDanmuLoad()));
+ mBinding.rtspText.setText((rtsp = ResUtil.getStringArray(R.array.select_rtsp))[Setting.getRtsp()]);
mBinding.flagText.setText((flag = ResUtil.getStringArray(R.array.select_flag))[Setting.getFlag()]);
mBinding.httpText.setText((http = ResUtil.getStringArray(R.array.select_exo_http))[Setting.getHttp()]);
mBinding.scaleText.setText((scale = ResUtil.getStringArray(R.array.select_scale))[Setting.getScale()]);
@@ -72,6 +74,7 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
@Override
protected void initEvent() {
mBinding.ua.setOnClickListener(this::onUa);
+ mBinding.rtsp.setOnClickListener(this::setRtsp);
mBinding.http.setOnClickListener(this::setHttp);
mBinding.flag.setOnClickListener(this::setFlag);
mBinding.scale.setOnClickListener(this::onScale);
@@ -104,6 +107,12 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
Setting.putUa(ua);
}
+ private void setRtsp(View view) {
+ int index = Setting.getRtsp();
+ Setting.putRtsp(index = index == rtsp.length - 1 ? 0 : ++index);
+ mBinding.rtspText.setText(rtsp[index]);
+ }
+
private void setHttp(View view) {
int index = Setting.getHttp();
Setting.putHttp(index = index == http.length - 1 ? 0 : ++index);
diff --git a/app/src/mobile/java/com/fongmi/android/tv/utils/PiP.java b/app/src/mobile/java/com/fongmi/android/tv/utils/PiP.java
index e3392fe3e..2ba4d333c 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/utils/PiP.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/utils/PiP.java
@@ -13,6 +13,7 @@ import android.view.View;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
+import androidx.media3.common.VideoSize;
import androidx.media3.ui.R;
import com.fongmi.android.tv.App;
@@ -71,15 +72,27 @@ public class PiP {
}
}
- public void enter(Activity activity, boolean four) {
+ public void enter(Activity activity, VideoSize size, int scale) {
try {
if (noPiP() || activity.isInPictureInPictureMode() || !Setting.isBackgroundPiP()) return;
- builder.setAspectRatio(new Rational(four ? 4 : 16, four ? 3 : 9));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) builder.setAutoEnterEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) builder.setSeamlessResizeEnabled(true);
+ if (scale == 1) builder.setAspectRatio(new Rational(16, 9));
+ else if (scale == 2) builder.setAspectRatio(new Rational(4, 3));
+ else builder.setAspectRatio(getRational(size));
activity.enterPictureInPictureMode(builder.build());
} catch (Exception e) {
e.printStackTrace();
}
}
+
+ private Rational getRational(VideoSize size) {
+ Rational limitWide = new Rational(239, 100);
+ Rational limitTall = new Rational(100, 239);
+ Rational rational = new Rational(size.width, size.height);
+ if (rational.isInfinite()) return new Rational(16, 9);
+ if (rational.floatValue() > limitWide.floatValue()) return limitWide;
+ if (rational.floatValue() < limitTall.floatValue()) return limitTall;
+ return rational;
+ }
}
diff --git a/app/src/mobile/res/layout-sw600dp/activity_video.xml b/app/src/mobile/res/layout-sw600dp/activity_video.xml
index 277392001..96b0a5333 100644
--- a/app/src/mobile/res/layout-sw600dp/activity_video.xml
+++ b/app/src/mobile/res/layout-sw600dp/activity_video.xml
@@ -22,20 +22,11 @@
android:focusable="true">
-
-
+ app:surface_type="none" />
-
-
+ app:surface_type="none" />
-
-
+ app:surface_type="none" />
+
+
+
+
+
+
+
+