Skip to content

Commit 529e016

Browse files
committed
fix(YouTube - Player components): Speed overlay value only works when set to 1.0 or higher inotia00/ReVanced_Extended#2849
1 parent fd32e4a commit 529e016

File tree

4 files changed

+81
-16
lines changed

4 files changed

+81
-16
lines changed

extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,12 @@ public static float speedOverlayValue(float original) {
518518
return SPEED_OVERLAY_VALUE;
519519
}
520520

521+
public static float speedOverlayRelativeValue(float original) {
522+
return SPEED_OVERLAY_VALUE != 2.0f
523+
? 0f
524+
: original;
525+
}
526+
521527
public static boolean hideChannelWatermark(boolean original) {
522528
return !Settings.HIDE_CHANNEL_WATERMARK.get() && original;
523529
}

patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ internal val speedOverlayFingerprint = legacyFingerprint(
8888
literals = listOf(SPEED_OVERLAY_FEATURE_FLAG),
8989
)
9090

91+
internal const val SPEED_OVERLAY_LEGACY_FEATURE_FLAG = 45411328L
92+
9193
/**
9294
* This value is the key for the playback speed overlay value.
9395
* Deprecated in YouTube v19.18.41+.
@@ -97,7 +99,7 @@ internal val speedOverlayFloatValueFingerprint = legacyFingerprint(
9799
returnType = "V",
98100
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
99101
opcodes = listOf(Opcode.DOUBLE_TO_FLOAT),
100-
literals = listOf(45411328L),
102+
literals = listOf(SPEED_OVERLAY_LEGACY_FEATURE_FLAG),
101103
)
102104

103105
internal val speedOverlayTextValueFingerprint = legacyFingerprint(

patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ import app.revanced.patches.youtube.utils.engagement.engagementPanelIdRegister
2424
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
2525
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
2626
import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH
27+
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
2728
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch
2829
import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS
2930
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
31+
import app.revanced.patches.youtube.utils.playservice.is_19_18_or_greater
3032
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
3133
import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater
3234
import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater
@@ -45,23 +47,27 @@ import app.revanced.patches.youtube.video.information.videoInformationPatch
4547
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
4648
import app.revanced.util.Utils.printWarn
4749
import app.revanced.util.findMethodOrThrow
50+
import app.revanced.util.findMutableMethodOf
4851
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
4952
import app.revanced.util.fingerprint.injectLiteralInstructionViewCall
5053
import app.revanced.util.fingerprint.matchOrThrow
5154
import app.revanced.util.fingerprint.methodOrThrow
5255
import app.revanced.util.fingerprint.mutableClassOrThrow
53-
import app.revanced.util.fingerprint.resolvable
5456
import app.revanced.util.getReference
5557
import app.revanced.util.getWalkerMethod
5658
import app.revanced.util.indexOfFirstInstruction
5759
import app.revanced.util.indexOfFirstInstructionOrThrow
5860
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
5961
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
62+
import app.revanced.util.or
63+
import com.android.tools.smali.dexlib2.AccessFlags
6064
import com.android.tools.smali.dexlib2.Opcode
65+
import com.android.tools.smali.dexlib2.iface.Method
6166
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
6267
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
6368
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
6469
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
70+
import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction
6571
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
6672
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
6773
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@@ -70,7 +76,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
7076
private val speedOverlayPatch = bytecodePatch(
7177
description = "speedOverlayPatch"
7278
) {
73-
dependsOn(sharedResourceIdPatch)
79+
dependsOn(
80+
sharedExtensionPatch,
81+
sharedResourceIdPatch,
82+
versionCheckPatch,
83+
)
7484

7585
execute {
7686
fun MutableMethod.hookSpeedOverlay(
@@ -87,11 +97,19 @@ private val speedOverlayPatch = bytecodePatch(
8797
)
8898
}
8999

90-
val resolvable = restoreSlideToSeekBehaviorFingerprint.resolvable() &&
91-
speedOverlayFingerprint.resolvable() &&
92-
speedOverlayFloatValueFingerprint.resolvable()
100+
fun MutableMethod.hookRelativeSpeedValue(startIndex: Int) {
101+
val relativeIndex = indexOfFirstInstructionOrThrow(startIndex, Opcode.CMPL_FLOAT)
102+
val relativeRegister = getInstruction<ThreeRegisterInstruction>(relativeIndex).registerB
93103

94-
if (resolvable) {
104+
addInstructions(
105+
relativeIndex, """
106+
invoke-static {v$relativeRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayRelativeValue(F)F
107+
move-result v$relativeRegister
108+
"""
109+
)
110+
}
111+
112+
if (!is_19_18_or_greater) {
95113
// Used on YouTube 18.29.38 ~ YouTube 19.17.41
96114

97115
// region patch for Disable speed overlay (Enable slide to seek)
@@ -110,17 +128,51 @@ private val speedOverlayPatch = bytecodePatch(
110128

111129
// region patch for Custom speed overlay float value
112130

113-
speedOverlayFloatValueFingerprint.matchOrThrow().let {
114-
it.method.apply {
115-
val index = it.patternMatch!!.startIndex
116-
val register = getInstruction<TwoRegisterInstruction>(index).registerA
131+
val speedFieldReference = with (speedOverlayFloatValueFingerprint.methodOrThrow()) {
132+
val literalIndex = indexOfFirstLiteralInstructionOrThrow(SPEED_OVERLAY_LEGACY_FEATURE_FLAG)
133+
val floatIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.DOUBLE_TO_FLOAT)
134+
val floatRegister = getInstruction<TwoRegisterInstruction>(floatIndex).registerA
117135

118-
addInstructions(
119-
index + 1, """
120-
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F
121-
move-result v$register
136+
addInstructions(
137+
floatIndex + 1, """
138+
invoke-static {v$floatRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F
139+
move-result v$floatRegister
122140
"""
123-
)
141+
)
142+
143+
val speedFieldIndex = indexOfFirstInstructionOrThrow(literalIndex) {
144+
opcode == Opcode.IPUT &&
145+
getReference<FieldReference>()?.type == "F"
146+
}
147+
148+
getInstruction<ReferenceInstruction>(speedFieldIndex).reference.toString()
149+
}
150+
151+
fun indexOfFirstSpeedFieldInstruction(method: Method) =
152+
method.indexOfFirstInstruction {
153+
opcode == Opcode.IGET &&
154+
getReference<FieldReference>()?.toString() == speedFieldReference
155+
}
156+
157+
val isSyntheticMethod: Method.() -> Boolean = {
158+
name == "run" &&
159+
accessFlags == AccessFlags.PUBLIC or AccessFlags.FINAL &&
160+
parameterTypes.isEmpty() &&
161+
indexOfFirstSpeedFieldInstruction(this) >= 0 &&
162+
indexOfFirstInstruction(Opcode.CMPL_FLOAT) >= 0
163+
}
164+
165+
classes.forEach { classDef ->
166+
classDef.methods.forEach { method ->
167+
if (method.isSyntheticMethod()) {
168+
proxy(classDef)
169+
.mutableClass
170+
.findMutableMethodOf(method)
171+
.apply {
172+
val speedFieldIndex = indexOfFirstSpeedFieldInstruction(this)
173+
hookRelativeSpeedValue(speedFieldIndex)
174+
}
175+
}
124176
}
125177
}
126178

@@ -241,6 +293,8 @@ private val speedOverlayPatch = bytecodePatch(
241293
move-result v$speedOverlayFloatValueRegister
242294
"""
243295
)
296+
297+
hookRelativeSpeedValue(speedOverlayFloatValueIndex)
244298
}
245299

246300
// Removed in YouTube 20.03+

patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ var is_19_16_or_greater = false
3131
private set
3232
var is_19_17_or_greater = false
3333
private set
34+
var is_19_18_or_greater = false
35+
private set
3436
var is_19_23_or_greater = false
3537
private set
3638
var is_19_25_or_greater = false
@@ -97,6 +99,7 @@ val versionCheckPatch = resourcePatch(
9799
is_19_15_or_greater = 241602000 <= playStoreServicesVersion
98100
is_19_16_or_greater = 241702000 <= playStoreServicesVersion
99101
is_19_17_or_greater = 241802000 <= playStoreServicesVersion
102+
is_19_18_or_greater = 241902000 <= playStoreServicesVersion
100103
is_19_23_or_greater = 242402000 <= playStoreServicesVersion
101104
is_19_25_or_greater = 242599000 <= playStoreServicesVersion
102105
is_19_26_or_greater = 242705000 <= playStoreServicesVersion

0 commit comments

Comments
 (0)