Skip to content

Commit

Permalink
support switch soft-decode or hard-decode
Browse files Browse the repository at this point in the history
  • Loading branch information
lizongying committed Dec 27, 2024
1 parent 41e502c commit 0838af0
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 105 deletions.
4 changes: 4 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## 更新日誌

### v1.3.8.13

* 支持切換軟解/硬解

### v1.3.8.12

* 在觸屏設備上可以調節聲音和亮度
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ adb install my-tv-0.apk

## TODO

* 軟解
* 支持回看
* 詳細EPG
* 淺色菜單
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/lizongying/mytv0/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,14 @@ class MainActivity : AppCompatActivity() {
}
}

fun switchSoftDecode() {
if (!playerFragment.isAdded || playerFragment.isHidden) {
return
}

playerFragment.updatePlayer()
}

fun settingActive() {
handler.removeCallbacks(hideSetting)
handler.postDelayed(hideSetting, delayHideSetting)
Expand Down
196 changes: 97 additions & 99 deletions app/src/main/java/com/lizongying/mytv0/PlayerFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.annotation.OptIn
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
Expand Down Expand Up @@ -39,117 +38,117 @@ class PlayerFragment : Fragment() {
private val handler = Handler(Looper.myLooper()!!)
private val delayHideVolume = 2 * 1000L

private lateinit var mainActivity: MainActivity

@Deprecated("Deprecated in Java")
override fun onActivityCreated(savedInstanceState: Bundle?) {
mainActivity = activity as MainActivity
super.onActivityCreated(savedInstanceState)
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = PlayerBinding.inflate(inflater, container, false)
val playerView = _binding!!.playerView

playerView.viewTreeObserver?.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
@OptIn(UnstableApi::class)
override fun onGlobalLayout() {
playerView.viewTreeObserver.removeOnGlobalLayoutListener(this)

val renderersFactory = context?.let { DefaultRenderersFactory(it) }
val playerMediaCodecSelector = PlayerMediaCodecSelector()
renderersFactory?.setMediaCodecSelector(playerMediaCodecSelector)
renderersFactory?.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)

player = context?.let {
ExoPlayer.Builder(it)
.setRenderersFactory(renderersFactory!!)
.build()
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
updatePlayer()
(activity as MainActivity).ready(TAG)
}

@OptIn(UnstableApi::class)
fun updatePlayer() {
val playerView = binding.playerView

val renderersFactory = context?.let { DefaultRenderersFactory(it) }
val playerMediaCodecSelector = PlayerMediaCodecSelector()
renderersFactory?.setMediaCodecSelector(playerMediaCodecSelector)
renderersFactory?.setExtensionRendererMode(
if (SP.softDecode) DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER else DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF
)

if (player != null) {
player?.release()
}

player = context?.let {
ExoPlayer.Builder(it)
.setRenderersFactory(renderersFactory!!)
.build()
}
player?.repeatMode = REPEAT_MODE_ALL
player?.playWhenReady = true
player?.addListener(object : Player.Listener {
override fun onVideoSizeChanged(videoSize: VideoSize) {
val ratio = playerView.measuredWidth.div(playerView.measuredHeight)
val layoutParams = playerView.layoutParams
if (ratio < aspectRatio) {
layoutParams?.height =
(playerView.measuredWidth.div(aspectRatio)).toInt()
playerView.layoutParams = layoutParams
} else if (ratio > aspectRatio) {
layoutParams?.width =
(playerView.measuredHeight.times(aspectRatio)).toInt()
playerView.layoutParams = layoutParams
}
playerView.player = player
player?.repeatMode = REPEAT_MODE_ALL
player?.playWhenReady = true
player?.addListener(object : Player.Listener {
override fun onVideoSizeChanged(videoSize: VideoSize) {
val ratio = playerView.measuredWidth.div(playerView.measuredHeight)
val layoutParams = playerView.layoutParams
if (ratio < aspectRatio) {
layoutParams?.height =
(playerView.measuredWidth.div(aspectRatio)).toInt()
playerView.layoutParams = layoutParams
} else if (ratio > aspectRatio) {
layoutParams?.width =
(playerView.measuredHeight.times(aspectRatio)).toInt()
playerView.layoutParams = layoutParams
}
}
}

override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
if (isPlaying) {
tvModel?.confirmSourceType()
tvModel?.setErrInfo("")
tvModel!!.retryTimes = 0
} else {
Log.i(TAG, "${tvModel?.tv?.title} 播放停止")
override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
if (isPlaying) {
tvModel?.confirmSourceType()
tvModel?.setErrInfo("")
tvModel!!.retryTimes = 0
} else {
Log.i(TAG, "${tvModel?.tv?.title} 播放停止")
// tvModel?.setErrInfo("播放停止")
}
}
}
}

override fun onPlaybackStateChanged(playbackState: Int) {
Log.d(TAG, "playbackState $playbackState")
super.onPlaybackStateChanged(playbackState)
}
override fun onPlaybackStateChanged(playbackState: Int) {
Log.d(TAG, "playbackState $playbackState")
super.onPlaybackStateChanged(playbackState)
}


override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo,
newPosition: Player.PositionInfo,
reason: Int
) {
if (reason == DISCONTINUITY_REASON_AUTO_TRANSITION) {
mainActivity.onPlayEnd()
}
super.onPositionDiscontinuity(oldPosition, newPosition, reason)
}
override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo,
newPosition: Player.PositionInfo,
reason: Int
) {
if (reason == DISCONTINUITY_REASON_AUTO_TRANSITION) {
(activity as MainActivity).onPlayEnd()
}
super.onPositionDiscontinuity(oldPosition, newPosition, reason)
}

override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
tvModel?.setErrInfo(R.string.play_error.getString())

if (tvModel!!.retryTimes < tvModel!!.retryMaxTimes) {
var last = true
if (tvModel?.getSourceTypeDefault() == SourceType.UNKNOWN) {
last = tvModel!!.nextSourceType()
}
tvModel?.setReady()
if (last) {
tvModel!!.retryTimes++
}
Log.i(
TAG,
"retry ${tvModel!!.videoIndex.value} ${tvModel!!.getSourceTypeCurrent()} ${tvModel!!.retryTimes}/${tvModel!!.retryMaxTimes}"
)
} else {
if (!tvModel!!.isLastVideo()) {
tvModel!!.nextVideo()
tvModel?.setReady()
tvModel!!.retryTimes = 0
}
}
}
})
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
tvModel?.setErrInfo(R.string.play_error.getString())

(activity as MainActivity).ready(TAG)
Log.i(TAG, "player ready")
if (tvModel!!.retryTimes < tvModel!!.retryMaxTimes) {
var last = true
if (tvModel?.getSourceTypeDefault() == SourceType.UNKNOWN) {
last = tvModel!!.nextSourceType()
}
tvModel?.setReady()
if (last) {
tvModel!!.retryTimes++
}
Log.i(
TAG,
"retry ${tvModel!!.videoIndex.value} ${tvModel!!.getSourceTypeCurrent()} ${tvModel!!.retryTimes}/${tvModel!!.retryMaxTimes}"
)
} else {
if (!tvModel!!.isLastVideo()) {
tvModel!!.nextVideo()
tvModel?.setReady()
tvModel!!.retryTimes = 0
}
}
}
})

return _binding!!.root
playerView.player = player
if (tvModel != null) {
play(tvModel!!)
}
}

@OptIn(UnstableApi::class)
Expand Down Expand Up @@ -246,10 +245,9 @@ class PlayerFragment : Fragment() {
binding.volume.visibility = View.GONE
}

override fun onStart() {
super.onStart()
override fun onResume() {
super.onResume()
if (player?.isPlaying == false) {
Log.i(TAG, "replay")
player?.prepare()
player?.play()
}
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/lizongying/mytv0/SP.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ object SP {

private const val KEY_SOURCES = "sources"

private const val KEY_SOFT_DECODE = "soft_decode"

const val DEFAULT_CHANNEL_REVERSAL = false
const val DEFAULT_CONFIG_URL = ""
const val DEFAULT_CHANNEL_NUM = false
Expand All @@ -70,6 +72,7 @@ object SP {
const val DEFAULT_COMPACT_MENU = true
const val DEFAULT_DISPLAY_SECONDS = true
const val DEFAULT_LOG_TIMES = 10
const val DEFAULT_SOFT_DECODE = false

// 0 favorite; 1 all
const val DEFAULT_POSITION_GROUP = 1
Expand Down Expand Up @@ -169,6 +172,10 @@ object SP {
get() = sp.getBoolean(KEY_DISPLAY_SECONDS, DEFAULT_DISPLAY_SECONDS)
set(value) = sp.edit().putBoolean(KEY_DISPLAY_SECONDS, value).apply()

var softDecode: Boolean
get() = sp.getBoolean(KEY_SOFT_DECODE, DEFAULT_SOFT_DECODE)
set(value) = sp.edit().putBoolean(KEY_SOFT_DECODE, value).apply()

fun getLike(id: Int): Boolean {
val stringSet = sp.getStringSet(KEY_LIKE, emptySet())
return stringSet?.contains(id.toString()) ?: false
Expand Down
20 changes: 17 additions & 3 deletions app/src/main/java/com/lizongying/mytv0/SettingFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,15 @@ class SettingFragment : Fragment() {
val switchDisplaySeconds = _binding?.switchDisplaySeconds
switchDisplaySeconds?.isChecked = SP.displaySeconds

binding.qrcode.setOnClickListener {
val switchSoftDecode = _binding?.switchSoftDecode
switchSoftDecode?.isChecked = SP.softDecode
switchSoftDecode?.setOnCheckedChangeListener { _, isChecked ->
SP.softDecode = isChecked
mainActivity.switchSoftDecode()
mainActivity.settingActive()
}

binding.remoteSettings.setOnClickListener {
val imageModalFragment = ModalFragment()
val args = Bundle()
args.putString(KEY_URL, server)
Expand Down Expand Up @@ -186,7 +194,7 @@ class SettingFragment : Fragment() {
binding.versionName.textSize = txtTextSize

for (i in listOf(
binding.qrcode,
binding.remoteSettings,
binding.confirmConfig,
binding.clear,
binding.checkVersion,
Expand Down Expand Up @@ -245,6 +253,7 @@ class SettingFragment : Fragment() {
binding.switchShowAllChannels,
binding.switchCompactMenu,
binding.switchDisplaySeconds,
binding.switchSoftDecode,
)) {
i.textSize = textSizeSwitch
i.layoutParams = layoutParamsSwitch
Expand Down Expand Up @@ -297,6 +306,9 @@ class SettingFragment : Fragment() {
SP.configAutoLoad = SP.DEFAULT_CONFIG_AUTO_LOAD
SP.proxy = SP.DEFAULT_PROXY

// TODO update player
SP.softDecode = SP.DEFAULT_SOFT_DECODE

SP.configUrl = SP.DEFAULT_CONFIG_URL
Log.i(TAG, "config url: ${SP.configUrl}")
context.deleteFile(CACHE_FILE_NAME)
Expand Down Expand Up @@ -344,6 +356,8 @@ class SettingFragment : Fragment() {

mainActivity.settingActive()
}

binding.remoteSettings.requestFocus()
}

private fun confirmConfig() {
Expand Down Expand Up @@ -385,7 +399,7 @@ class SettingFragment : Fragment() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (_binding != null && !hidden) {
binding.qrcode.requestFocus()
binding.remoteSettings.requestFocus()
}
}

Expand Down
13 changes: 12 additions & 1 deletion app/src/main/res/layout/setting.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
android:orientation="horizontal"
>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/qrcode"
android:id="@+id/remote_settings"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:background="@color/description_blur"
Expand Down Expand Up @@ -242,6 +242,17 @@
app:thumbTint="@color/switch_thumb_color"
app:trackTint="@color/switch_track_color"
/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch_soft_decode"
android:text="@string/soft_decode"
android:textColor="@color/title_blur"
android:textSize="14sp"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:thumbTint="@color/switch_thumb_color"
app:trackTint="@color/switch_track_color"
/>
</LinearLayout>
</ScrollView>
</LinearLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@
<string name="compact_menu">紧凑的菜单</string>
<string name="display_seconds">时间显示秒</string>
<string name="no_video_source">暂无视频源</string>
<string name="soft_decode">软解</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@
<string name="compact_menu">緊湊的菜單</string>
<string name="display_seconds">時間顯示秒</string>
<string name="no_video_source">暫無視頻源</string>
<string name="soft_decode">軟解</string>
</resources>
Loading

0 comments on commit 0838af0

Please sign in to comment.