Skip to content

Commit

Permalink
fix(YouTube): When clicking on timestamps in comments, playback speed…
Browse files Browse the repository at this point in the history
… sometimes changes to 1.0x (unpatched YouTube bug)
  • Loading branch information
inotia00 committed Dec 21, 2024
1 parent d89491e commit 20eaad5
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package app.revanced.extension.youtube.patches.utils;

import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.youtube.shared.PlayerType;

@SuppressWarnings("unused")
public class PlaybackSpeedWhilePlayingPatch {
private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f;

public static boolean playbackSpeedChanged(float playbackSpeed) {
if (playbackSpeed == DEFAULT_YOUTUBE_PLAYBACK_SPEED &&
PlayerType.getCurrent().isMaximizedOrFullscreen()) {

Logger.printDebug(() -> "Even though playback has already started and the user has not changed the playback speed, " +
"the app attempts to change the playback speed to 1.0x." +
"\nIgnore changing playback speed, as it is invalid request.");

return true;
}

return false;
}

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package app.revanced.patches.youtube.utils.fix.playbackspeed

import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionReversed
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.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.FieldReference

/**
* This fingerprint is compatible with YouTube 17.34.36 ~ 19.50.40.
*
* This method is usually used to set the initial speed (1.0x) when playback starts from the feed.
* For some reason, in the latest YouTube, it is invoked even after the video has already started.
*/
internal val playbackSpeedInFeedsFingerprint = legacyFingerprint(
name = "playbackSpeedInFeedsFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.IGET,
Opcode.MUL_INT_LIT16,
Opcode.IGET_WIDE,
Opcode.CONST_WIDE_16,
Opcode.CMP_LONG,
Opcode.IF_EQZ,
Opcode.IF_LEZ,
Opcode.SUB_LONG_2ADDR,
),
customFingerprint = { method, _ ->
indexOfGetPlaybackSpeedInstruction(method) >= 0
}
)

fun indexOfGetPlaybackSpeedInstruction(method: Method) =
method.indexOfFirstInstructionReversed {
opcode == Opcode.IGET &&
getReference<FieldReference>()?.type == "F"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package app.revanced.patches.youtube.utils.fix.playbackspeed

import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.utils.playservice.is_19_34_or_greater
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction

private const val EXTENSION_CLASS_DESCRIPTOR =
"$UTILS_PATH/PlaybackSpeedWhilePlayingPatch;"

val playbackSpeedWhilePlayingPatch = bytecodePatch(
description = "playbackSpeedWhilePlayingPatch"
) {
dependsOn(
sharedExtensionPatch,
playerTypeHookPatch,
versionCheckPatch,
)

execute {
if (!is_19_34_or_greater) {
return@execute
}

/**
* There is an issue where sometimes when you click on a comment in a video and press the back button or click on the timestamp of the comment, the playback speed will change to 1.0x.
*
* This can be reproduced on unpatched YouTube 19.34.42+ by following these steps:
* 1. After the video starts, manually change the playback speed to something other than 1.0x.
* 2. If enough time has passed since the video started, open the comments panel.
* 3. Click on a comment and press the back button, or click on the timestamp of the comment.
* 4. Sometimes the playback speed will change to 1.0x.
*
* This is an issue that Google should fix, but it is not that hard to fix, so it has been implemented in the patch.
*/
playbackSpeedInFeedsFingerprint.methodOrThrow().apply {
val freeRegister = implementation!!.registerCount - parameters.size - 2
val playbackSpeedIndex = indexOfGetPlaybackSpeedInstruction(this)
val playbackSpeedRegister = getInstruction<TwoRegisterInstruction>(playbackSpeedIndex).registerA
val jumpIndex = indexOfFirstInstructionOrThrow(playbackSpeedIndex, Opcode.RETURN_VOID)

addInstructionsWithLabels(
playbackSpeedIndex + 1, """
invoke-static { v$playbackSpeedRegister }, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedChanged(F)Z
move-result v$freeRegister
if-nez v$freeRegister, :do_not_change
""", ExternalLabel("do_not_change", getInstruction(jumpIndex))
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC
import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
import app.revanced.patches.youtube.utils.fix.cairo.cairoSettingsPatch
import app.revanced.patches.youtube.utils.fix.playbackspeed.playbackSpeedWhilePlayingPatch
import app.revanced.patches.youtube.utils.fix.splash.darkModeSplashScreenPatch
import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
import app.revanced.patches.youtube.utils.patch.PatchList.SETTINGS_FOR_YOUTUBE
Expand Down Expand Up @@ -122,6 +123,7 @@ val settingsPatch = resourcePatch(
settingsBytecodePatch,
cairoSettingsPatch,
darkModeSplashScreenPatch,
playbackSpeedWhilePlayingPatch,
)

val insertPosition = stringOption(
Expand Down

0 comments on commit 20eaad5

Please sign in to comment.