fix(YouTube - Player components): Speed overlay value only works when set to 1.0 or higher https://github.com/inotia00/ReVanced_Extended/issues/2849

This commit is contained in:
inotia00
2025-03-24 21:23:46 +09:00
parent fd32e4a854
commit 529e0163cc
4 changed files with 81 additions and 16 deletions

View File

@ -518,6 +518,12 @@ public class PlayerPatch {
return SPEED_OVERLAY_VALUE; return SPEED_OVERLAY_VALUE;
} }
public static float speedOverlayRelativeValue(float original) {
return SPEED_OVERLAY_VALUE != 2.0f
? 0f
: original;
}
public static boolean hideChannelWatermark(boolean original) { public static boolean hideChannelWatermark(boolean original) {
return !Settings.HIDE_CHANNEL_WATERMARK.get() && original; return !Settings.HIDE_CHANNEL_WATERMARK.get() && original;
} }

View File

@ -88,6 +88,8 @@ internal val speedOverlayFingerprint = legacyFingerprint(
literals = listOf(SPEED_OVERLAY_FEATURE_FLAG), literals = listOf(SPEED_OVERLAY_FEATURE_FLAG),
) )
internal const val SPEED_OVERLAY_LEGACY_FEATURE_FLAG = 45411328L
/** /**
* This value is the key for the playback speed overlay value. * This value is the key for the playback speed overlay value.
* Deprecated in YouTube v19.18.41+. * Deprecated in YouTube v19.18.41+.
@ -97,7 +99,7 @@ internal val speedOverlayFloatValueFingerprint = legacyFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
opcodes = listOf(Opcode.DOUBLE_TO_FLOAT), opcodes = listOf(Opcode.DOUBLE_TO_FLOAT),
literals = listOf(45411328L), literals = listOf(SPEED_OVERLAY_LEGACY_FEATURE_FLAG),
) )
internal val speedOverlayTextValueFingerprint = legacyFingerprint( internal val speedOverlayTextValueFingerprint = legacyFingerprint(

View File

@ -24,9 +24,11 @@ import app.revanced.patches.youtube.utils.engagement.engagementPanelIdRegister
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch
import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.utils.playservice.is_19_18_or_greater
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater
import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater
@ -45,23 +47,27 @@ import app.revanced.patches.youtube.video.information.videoInformationPatch
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.util.Utils.printWarn import app.revanced.util.Utils.printWarn
import app.revanced.util.findMethodOrThrow import app.revanced.util.findMethodOrThrow
import app.revanced.util.findMutableMethodOf
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
import app.revanced.util.fingerprint.injectLiteralInstructionViewCall import app.revanced.util.fingerprint.injectLiteralInstructionViewCall
import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.fingerprint.mutableClassOrThrow import app.revanced.util.fingerprint.mutableClassOrThrow
import app.revanced.util.fingerprint.resolvable
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@ -70,7 +76,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private val speedOverlayPatch = bytecodePatch( private val speedOverlayPatch = bytecodePatch(
description = "speedOverlayPatch" description = "speedOverlayPatch"
) { ) {
dependsOn(sharedResourceIdPatch) dependsOn(
sharedExtensionPatch,
sharedResourceIdPatch,
versionCheckPatch,
)
execute { execute {
fun MutableMethod.hookSpeedOverlay( fun MutableMethod.hookSpeedOverlay(
@ -87,11 +97,19 @@ private val speedOverlayPatch = bytecodePatch(
) )
} }
val resolvable = restoreSlideToSeekBehaviorFingerprint.resolvable() && fun MutableMethod.hookRelativeSpeedValue(startIndex: Int) {
speedOverlayFingerprint.resolvable() && val relativeIndex = indexOfFirstInstructionOrThrow(startIndex, Opcode.CMPL_FLOAT)
speedOverlayFloatValueFingerprint.resolvable() val relativeRegister = getInstruction<ThreeRegisterInstruction>(relativeIndex).registerB
if (resolvable) { addInstructions(
relativeIndex, """
invoke-static {v$relativeRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayRelativeValue(F)F
move-result v$relativeRegister
"""
)
}
if (!is_19_18_or_greater) {
// Used on YouTube 18.29.38 ~ YouTube 19.17.41 // Used on YouTube 18.29.38 ~ YouTube 19.17.41
// region patch for Disable speed overlay (Enable slide to seek) // region patch for Disable speed overlay (Enable slide to seek)
@ -110,17 +128,51 @@ private val speedOverlayPatch = bytecodePatch(
// region patch for Custom speed overlay float value // region patch for Custom speed overlay float value
speedOverlayFloatValueFingerprint.matchOrThrow().let { val speedFieldReference = with (speedOverlayFloatValueFingerprint.methodOrThrow()) {
it.method.apply { val literalIndex = indexOfFirstLiteralInstructionOrThrow(SPEED_OVERLAY_LEGACY_FEATURE_FLAG)
val index = it.patternMatch!!.startIndex val floatIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.DOUBLE_TO_FLOAT)
val register = getInstruction<TwoRegisterInstruction>(index).registerA val floatRegister = getInstruction<TwoRegisterInstruction>(floatIndex).registerA
addInstructions( addInstructions(
index + 1, """ floatIndex + 1, """
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F invoke-static {v$floatRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F
move-result v$register move-result v$floatRegister
""" """
) )
val speedFieldIndex = indexOfFirstInstructionOrThrow(literalIndex) {
opcode == Opcode.IPUT &&
getReference<FieldReference>()?.type == "F"
}
getInstruction<ReferenceInstruction>(speedFieldIndex).reference.toString()
}
fun indexOfFirstSpeedFieldInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.IGET &&
getReference<FieldReference>()?.toString() == speedFieldReference
}
val isSyntheticMethod: Method.() -> Boolean = {
name == "run" &&
accessFlags == AccessFlags.PUBLIC or AccessFlags.FINAL &&
parameterTypes.isEmpty() &&
indexOfFirstSpeedFieldInstruction(this) >= 0 &&
indexOfFirstInstruction(Opcode.CMPL_FLOAT) >= 0
}
classes.forEach { classDef ->
classDef.methods.forEach { method ->
if (method.isSyntheticMethod()) {
proxy(classDef)
.mutableClass
.findMutableMethodOf(method)
.apply {
val speedFieldIndex = indexOfFirstSpeedFieldInstruction(this)
hookRelativeSpeedValue(speedFieldIndex)
}
}
} }
} }
@ -241,6 +293,8 @@ private val speedOverlayPatch = bytecodePatch(
move-result v$speedOverlayFloatValueRegister move-result v$speedOverlayFloatValueRegister
""" """
) )
hookRelativeSpeedValue(speedOverlayFloatValueIndex)
} }
// Removed in YouTube 20.03+ // Removed in YouTube 20.03+

View File

@ -31,6 +31,8 @@ var is_19_16_or_greater = false
private set private set
var is_19_17_or_greater = false var is_19_17_or_greater = false
private set private set
var is_19_18_or_greater = false
private set
var is_19_23_or_greater = false var is_19_23_or_greater = false
private set private set
var is_19_25_or_greater = false var is_19_25_or_greater = false
@ -97,6 +99,7 @@ val versionCheckPatch = resourcePatch(
is_19_15_or_greater = 241602000 <= playStoreServicesVersion is_19_15_or_greater = 241602000 <= playStoreServicesVersion
is_19_16_or_greater = 241702000 <= playStoreServicesVersion is_19_16_or_greater = 241702000 <= playStoreServicesVersion
is_19_17_or_greater = 241802000 <= playStoreServicesVersion is_19_17_or_greater = 241802000 <= playStoreServicesVersion
is_19_18_or_greater = 241902000 <= playStoreServicesVersion
is_19_23_or_greater = 242402000 <= playStoreServicesVersion is_19_23_or_greater = 242402000 <= playStoreServicesVersion
is_19_25_or_greater = 242599000 <= playStoreServicesVersion is_19_25_or_greater = 242599000 <= playStoreServicesVersion
is_19_26_or_greater = 242705000 <= playStoreServicesVersion is_19_26_or_greater = 242705000 <= playStoreServicesVersion