mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-29 05:10:20 +02:00
refactor(YouTube/Video information): change invoke method
- Different methods are invoked depending on whether the video being played is a regular video or Shorts. - The following information is invoked in VideoInformation: Channel Id, Channel Name, Video Title, Video Length, LiveStream, Playlist Id. - Also, video time is invoked every 100ms, not 1000ms.
This commit is contained in:
parent
a71d1870c4
commit
e5c180ba84
@ -4,7 +4,7 @@ import app.revanced.patcher.data.BytecodeContext
|
|||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -14,13 +14,13 @@ object AutoCaptionsPatch : BaseBytecodePatch(
|
|||||||
dependencies = setOf(
|
dependencies = setOf(
|
||||||
AutoCaptionsBytecodePatch::class,
|
AutoCaptionsBytecodePatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
VideoIdPatch::class
|
VideoInformationPatch::class
|
||||||
),
|
),
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE
|
compatiblePackages = COMPATIBLE_PACKAGE
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
VideoIdPatch.hookBackgroundPlayVideoId("$GENERAL_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
|
VideoInformationPatch.hookBackgroundPlay("$GENERAL_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add settings
|
* Add settings
|
||||||
|
@ -53,7 +53,7 @@ object SpoofPlayerParameterPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
// Hook the player parameters.
|
// Hook the player parameters.
|
||||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter(
|
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter(
|
||||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;"
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Force the seekbar time and chapters to always show up.
|
// Force the seekbar time and chapters to always show up.
|
||||||
|
@ -66,6 +66,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
|||||||
var ModernMiniPlayerForwardButton = -1L
|
var ModernMiniPlayerForwardButton = -1L
|
||||||
var ModernMiniPlayerRewindButton = -1L
|
var ModernMiniPlayerRewindButton = -1L
|
||||||
var MusicAppDeeplinkButtonView = -1L
|
var MusicAppDeeplinkButtonView = -1L
|
||||||
|
var NotificationBigPictureIconWidth = -1L
|
||||||
var PanelSubHeader = -1L
|
var PanelSubHeader = -1L
|
||||||
var PlayerCollapseButton = -1L
|
var PlayerCollapseButton = -1L
|
||||||
var PosterArtWidthDefault = -1L
|
var PosterArtWidthDefault = -1L
|
||||||
@ -152,6 +153,7 @@ object SharedResourceIdPatch : ResourcePatch() {
|
|||||||
ModernMiniPlayerForwardButton = getId(ID, "modern_miniplayer_forward_button")
|
ModernMiniPlayerForwardButton = getId(ID, "modern_miniplayer_forward_button")
|
||||||
ModernMiniPlayerRewindButton = getId(ID, "modern_miniplayer_rewind_button")
|
ModernMiniPlayerRewindButton = getId(ID, "modern_miniplayer_rewind_button")
|
||||||
MusicAppDeeplinkButtonView = getId(ID, "music_app_deeplink_button_view")
|
MusicAppDeeplinkButtonView = getId(ID, "music_app_deeplink_button_view")
|
||||||
|
NotificationBigPictureIconWidth = getId(DIMEN, "notification_big_picture_icon_width")
|
||||||
PanelSubHeader = getId(ID, "panel_subheader")
|
PanelSubHeader = getId(ID, "panel_subheader")
|
||||||
PlayerCollapseButton = getId(ID, "player_collapse_button")
|
PlayerCollapseButton = getId(ID, "player_collapse_button")
|
||||||
PosterArtWidthDefault = getId(DIMEN, "poster_art_width_default")
|
PosterArtWidthDefault = getId(DIMEN, "poster_art_width_default")
|
||||||
|
@ -18,7 +18,6 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Inset
|
|||||||
import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint
|
import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint
|
||||||
import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.SegmentPlaybackControllerFingerprint
|
import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.SegmentPlaybackControllerFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversed
|
import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversed
|
||||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||||
@ -35,7 +34,6 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
PlayerControlsPatch::class,
|
PlayerControlsPatch::class,
|
||||||
SharedResourceIdPatch::class,
|
SharedResourceIdPatch::class,
|
||||||
VideoIdPatch::class,
|
|
||||||
VideoInformationPatch::class
|
VideoInformationPatch::class
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -173,6 +171,6 @@ object SponsorBlockBytecodePatch : BytecodePatch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Set current video id
|
// Set current video id
|
||||||
VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
|
VideoInformationPatch.hook("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
@ -18,18 +19,27 @@ import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint
|
|||||||
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.ChannelIdFingerprint
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.ChannelNameFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.OnPlaybackSpeedItemClickFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.OnPlaybackSpeedItemClickFingerprint
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackInitializationFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackSpeedClassFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackSpeedClassFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.PlayerControllerSetTimeReferenceFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprint
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintBackgroundPlay
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintShorts
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoLengthFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoLengthFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityListFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityListFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityTextFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityTextFingerprint
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoTimeFingerprint
|
||||||
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoTitleFingerprint
|
||||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
||||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addFieldAndInstructions
|
||||||
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getTargetIndexReversed
|
import app.revanced.util.getTargetIndexReversed
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@ -37,6 +47,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
|||||||
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.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||||
@ -53,27 +64,54 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
|
|||||||
)
|
)
|
||||||
object VideoInformationPatch : BytecodePatch(
|
object VideoInformationPatch : BytecodePatch(
|
||||||
setOf(
|
setOf(
|
||||||
|
ChannelIdFingerprint,
|
||||||
|
ChannelNameFingerprint,
|
||||||
OnPlaybackSpeedItemClickFingerprint,
|
OnPlaybackSpeedItemClickFingerprint,
|
||||||
OrganicPlaybackContextModelFingerprint,
|
OrganicPlaybackContextModelFingerprint,
|
||||||
|
PlaybackInitializationFingerprint,
|
||||||
PlaybackSpeedClassFingerprint,
|
PlaybackSpeedClassFingerprint,
|
||||||
PlayerControllerSetTimeReferenceFingerprint,
|
|
||||||
VideoEndFingerprint,
|
VideoEndFingerprint,
|
||||||
|
VideoIdFingerprint,
|
||||||
|
VideoIdFingerprintBackgroundPlay,
|
||||||
|
VideoIdFingerprintShorts,
|
||||||
VideoLengthFingerprint,
|
VideoLengthFingerprint,
|
||||||
VideoQualityListFingerprint,
|
VideoQualityListFingerprint,
|
||||||
VideoQualityTextFingerprint
|
VideoQualityTextFingerprint,
|
||||||
|
VideoTitleFingerprint,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
"$SHARED_PATH/VideoInformation;"
|
"$SHARED_PATH/VideoInformation;"
|
||||||
|
|
||||||
|
private const val PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
||||||
|
"Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||||
|
|
||||||
|
private const val REGISTER_PLAYER_RESPONSE_MODEL = 8
|
||||||
|
|
||||||
|
private const val REGISTER_CHANNEL_ID = 0
|
||||||
|
private const val REGISTER_CHANNEL_NAME = 1
|
||||||
|
private const val REGISTER_VIDEO_ID = 2
|
||||||
|
private const val REGISTER_VIDEO_TITLE = 3
|
||||||
|
private const val REGISTER_VIDEO_LENGTH = 4
|
||||||
|
private const val REGISTER_VIDEO_LENGTH_DUMMY = 5
|
||||||
|
private const val REGISTER_VIDEO_IS_LIVE = 6
|
||||||
|
|
||||||
|
private lateinit var channelIdMethodCall: String
|
||||||
|
private lateinit var channelNameMethodCall: String
|
||||||
|
private lateinit var videoIdMethodCall: String
|
||||||
|
private lateinit var videoTitleMethodCall: String
|
||||||
|
private lateinit var videoLengthMethodCall: String
|
||||||
|
private lateinit var videoIsLiveMethodCall: String
|
||||||
|
|
||||||
|
private lateinit var videoInformationMethod: MutableMethod
|
||||||
|
private lateinit var backgroundVideoInformationMethod: MutableMethod
|
||||||
|
private lateinit var shortsVideoInformationMethod: MutableMethod
|
||||||
|
|
||||||
private lateinit var playerConstructorMethod: MutableMethod
|
private lateinit var playerConstructorMethod: MutableMethod
|
||||||
private var playerConstructorInsertIndex = 4
|
private var playerConstructorInsertIndex = 4
|
||||||
|
|
||||||
private lateinit var videoTimeConstructorMethod: MutableMethod
|
private lateinit var videoTimeMethod: MutableMethod
|
||||||
private var videoTimeConstructorInsertIndex = 2
|
private var videoTimeIndex = 1
|
||||||
|
|
||||||
private lateinit var videoCpnConstructorMethod: MutableMethod
|
|
||||||
private var videoCpnConstructorInsertIndex = 2
|
|
||||||
|
|
||||||
// Used by other patches.
|
// Used by other patches.
|
||||||
internal lateinit var speedSelectionInsertMethod: MutableMethod
|
internal lateinit var speedSelectionInsertMethod: MutableMethod
|
||||||
@ -83,6 +121,10 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
val videoInformationMutableClass = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
val videoInformationMutableClass = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
||||||
|
|
||||||
VideoEndFingerprint.resultOrThrow().let {
|
VideoEndFingerprint.resultOrThrow().let {
|
||||||
|
|
||||||
|
// resolve video time fingerprint
|
||||||
|
VideoTimeFingerprint.resolve(context, it.classDef)
|
||||||
|
|
||||||
playerConstructorMethod =
|
playerConstructorMethod =
|
||||||
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) }
|
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) }
|
||||||
|
|
||||||
@ -149,12 +191,84 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current video information
|
||||||
|
*/
|
||||||
|
channelIdMethodCall = ChannelIdFingerprint.getMethodName("Ljava/lang/String;")
|
||||||
|
channelNameMethodCall = ChannelNameFingerprint.getMethodName("Ljava/lang/String;")
|
||||||
|
videoIdMethodCall = VideoIdFingerprint.getMethodName("Ljava/lang/String;")
|
||||||
|
videoTitleMethodCall = VideoTitleFingerprint.getMethodName("Ljava/lang/String;")
|
||||||
|
videoLengthMethodCall = VideoLengthFingerprint.getMethodName("J")
|
||||||
|
videoIsLiveMethodCall = ChannelIdFingerprint.getMethodName("Z")
|
||||||
|
|
||||||
|
PlaybackInitializationFingerprint.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val targetIndex = indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_DIRECT
|
||||||
|
&& getReference<MethodReference>()?.returnType == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||||
|
} + 1
|
||||||
|
if (targetIndex == 0) throw PatchException("Could not find instruction index.")
|
||||||
|
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||||
|
|
||||||
|
addInstruction(
|
||||||
|
targetIndex + 1,
|
||||||
|
"invoke-direct {p0, v$targetRegister}, $definingClass->setVideoInformation($PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR)V"
|
||||||
|
)
|
||||||
|
|
||||||
|
videoInformationMethod = getVideoInformationMethod()
|
||||||
|
it.mutableClass.methods.add(videoInformationMethod)
|
||||||
|
|
||||||
|
hook("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoInformation(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoIdFingerprintBackgroundPlay.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val targetIndex = indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_INTERFACE
|
||||||
|
&& getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||||
|
}
|
||||||
|
if (targetIndex < 0) throw PatchException("Could not find instruction index.")
|
||||||
|
val targetRegister = getInstruction<FiveRegisterInstruction>(targetIndex).registerC
|
||||||
|
|
||||||
|
addInstruction(
|
||||||
|
targetIndex,
|
||||||
|
"invoke-direct {p0, v$targetRegister}, $definingClass->setVideoInformation($PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR)V"
|
||||||
|
)
|
||||||
|
|
||||||
|
backgroundVideoInformationMethod = getVideoInformationMethod()
|
||||||
|
it.mutableClass.methods.add(backgroundVideoInformationMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoIdFingerprintShorts.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val targetIndex = indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_INTERFACE
|
||||||
|
&& getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||||
|
}
|
||||||
|
if (targetIndex < 0) throw PatchException("Could not find instruction index.")
|
||||||
|
val targetRegister = getInstruction<FiveRegisterInstruction>(targetIndex).registerC
|
||||||
|
|
||||||
|
addInstruction(
|
||||||
|
targetIndex,
|
||||||
|
"invoke-direct {p0, v$targetRegister}, $definingClass->setVideoInformation($PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR)V"
|
||||||
|
)
|
||||||
|
|
||||||
|
shortsVideoInformationMethod = getVideoInformationMethod()
|
||||||
|
it.mutableClass.methods.add(shortsVideoInformationMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current video time method
|
* Set current video time method
|
||||||
*/
|
*/
|
||||||
PlayerControllerSetTimeReferenceFingerprint.resultOrThrow().let {
|
VideoTimeFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
videoTimeConstructorMethod =
|
videoTimeMethod = this
|
||||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
addInstruction(
|
||||||
|
0,
|
||||||
|
"move-wide/from16 v0, p5"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,40 +276,15 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
*/
|
*/
|
||||||
videoTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTime")
|
videoTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTime")
|
||||||
|
|
||||||
/**
|
|
||||||
* Set current video length
|
|
||||||
*/
|
|
||||||
VideoLengthFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
val primaryRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
|
|
||||||
val secondaryRegister = primaryRegister + 1
|
|
||||||
|
|
||||||
addInstruction(
|
|
||||||
startIndex + 2,
|
|
||||||
"invoke-static {v$primaryRegister, v$secondaryRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setVideoLength(J)V"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set current video is livestream
|
|
||||||
*/
|
|
||||||
videoCpnConstructorMethod = OrganicPlaybackContextModelFingerprint.resultOrThrow().mutableMethod
|
|
||||||
cpnHook("$INTEGRATIONS_CLASS_DESCRIPTOR->setLiveStreamState(Ljava/lang/String;Z)V")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current video id
|
* Set current video id
|
||||||
*/
|
*/
|
||||||
val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V"
|
|
||||||
VideoIdPatch.hookVideoId(videoIdMethodDescriptor)
|
|
||||||
VideoIdPatch.hookBackgroundPlayVideoId(videoIdMethodDescriptor)
|
|
||||||
VideoIdPatch.hookPlayerResponseVideoId(
|
VideoIdPatch.hookPlayerResponseVideoId(
|
||||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
||||||
// Call before any other video id hooks,
|
// Call before any other video id hooks,
|
||||||
// so they can use VideoInformation and check if the video id is for a Short.
|
// so they can use VideoInformation and check if the video id is for a Short.
|
||||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameterBeforeVideoId(
|
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameterBeforeVideoId(
|
||||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;")
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseParameter(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook current playback speed
|
* Hook current playback speed
|
||||||
@ -346,12 +435,6 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
|
|
||||||
addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
|
|
||||||
|
|
||||||
private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
|
|
||||||
insert(insertIndex, "p1, p2", descriptor)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook the player controller. Called when a video is opened or the current video is changed.
|
* Hook the player controller. Called when a video is opened or the current video is changed.
|
||||||
*
|
*
|
||||||
@ -375,15 +458,97 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
* @param targetMethodName The name of the static method to invoke when the player controller is created.
|
* @param targetMethodName The name of the static method to invoke when the player controller is created.
|
||||||
*/
|
*/
|
||||||
internal fun videoTimeHook(targetMethodClass: String, targetMethodName: String) =
|
internal fun videoTimeHook(targetMethodClass: String, targetMethodName: String) =
|
||||||
videoTimeConstructorMethod.insertTimeHook(
|
videoTimeMethod.addInstruction(
|
||||||
videoTimeConstructorInsertIndex++,
|
videoTimeIndex++,
|
||||||
"$targetMethodClass->$targetMethodName(J)V"
|
"invoke-static { v0, v1 }, $targetMethodClass->$targetMethodName(J)V"
|
||||||
)
|
)
|
||||||
|
|
||||||
internal fun cpnHook(descriptor: String) =
|
private fun MethodFingerprint.getMethodName(returnType : String) :String {
|
||||||
videoCpnConstructorMethod.insert(
|
resultOrThrow().mutableMethod.apply {
|
||||||
videoCpnConstructorInsertIndex++,
|
val targetIndex = indexOfFirstInstruction {
|
||||||
"p1, p2",
|
opcode == Opcode.INVOKE_INTERFACE
|
||||||
descriptor
|
&& getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||||
)
|
&& getReference<MethodReference>()?.returnType == returnType
|
||||||
|
}
|
||||||
|
if (targetIndex < 0) throw PatchException("Could not find instruction index.")
|
||||||
|
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
|
||||||
|
|
||||||
|
return "invoke-interface {v${REGISTER_PLAYER_RESPONSE_MODEL}}, $targetReference"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MutableMethod.getVideoInformationMethod(): MutableMethod =
|
||||||
|
ImmutableMethod(
|
||||||
|
definingClass,
|
||||||
|
"setVideoInformation",
|
||||||
|
listOf(ImmutableMethodParameter(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR, annotations, null)),
|
||||||
|
"V",
|
||||||
|
AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||||
|
annotations,
|
||||||
|
null,
|
||||||
|
ImmutableMethodImplementation(
|
||||||
|
9, """
|
||||||
|
$channelIdMethodCall
|
||||||
|
move-result-object v$REGISTER_CHANNEL_ID
|
||||||
|
$channelNameMethodCall
|
||||||
|
move-result-object v$REGISTER_CHANNEL_NAME
|
||||||
|
$videoIdMethodCall
|
||||||
|
move-result-object v$REGISTER_VIDEO_ID
|
||||||
|
$videoTitleMethodCall
|
||||||
|
move-result-object v$REGISTER_VIDEO_TITLE
|
||||||
|
$videoLengthMethodCall
|
||||||
|
move-result-wide v$REGISTER_VIDEO_LENGTH
|
||||||
|
$videoIsLiveMethodCall
|
||||||
|
move-result v$REGISTER_VIDEO_IS_LIVE
|
||||||
|
return-void
|
||||||
|
""".toInstructions(),
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
).toMutable()
|
||||||
|
|
||||||
|
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
|
||||||
|
addInstruction(insertIndex, "invoke-static/range { $register }, $descriptor")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is invoked on both regular videos and Shorts.
|
||||||
|
*/
|
||||||
|
internal fun hook(descriptor: String) =
|
||||||
|
videoInformationMethod.apply {
|
||||||
|
val index = implementation!!.instructions.size - 1
|
||||||
|
|
||||||
|
insert(
|
||||||
|
index,
|
||||||
|
"v${REGISTER_CHANNEL_ID} .. v${REGISTER_VIDEO_IS_LIVE}",
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is invoked only in regular videos.
|
||||||
|
*/
|
||||||
|
internal fun hookBackgroundPlay(descriptor: String) =
|
||||||
|
backgroundVideoInformationMethod.apply {
|
||||||
|
val index = implementation!!.instructions.size - 1
|
||||||
|
|
||||||
|
insert(
|
||||||
|
index,
|
||||||
|
"v${REGISTER_CHANNEL_ID} .. v${REGISTER_VIDEO_IS_LIVE}",
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is invoked only in shorts videos.
|
||||||
|
*/
|
||||||
|
internal fun hookShorts(descriptor: String) =
|
||||||
|
shortsVideoInformationMethod.apply {
|
||||||
|
val index = implementation!!.instructions.size - 1
|
||||||
|
|
||||||
|
insert(
|
||||||
|
index,
|
||||||
|
"v${REGISTER_CHANNEL_ID} .. v${REGISTER_VIDEO_IS_LIVE}",
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object ChannelIdFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("Ljava/lang/Object;"),
|
||||||
|
strings = listOf("com.google.android.apps.youtube.mdx.watch.LAST_MEALBAR_PROMOTED_LIVE_FEED_CHANNELS")
|
||||||
|
)
|
@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object ChannelNameFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
strings = listOf(
|
||||||
|
"setMetadata may only be called once",
|
||||||
|
"Person",
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object PlaybackInitializationFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = emptyList(),
|
||||||
|
strings = listOf("play() called when the player wasn\'t loaded.")
|
||||||
|
)
|
@ -1,12 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.video.information.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object PlayerControllerSetTimeReferenceFingerprint : MethodFingerprint(
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_DIRECT_RANGE,
|
|
||||||
Opcode.IGET_OBJECT
|
|
||||||
),
|
|
||||||
strings = listOf("Media progress reported outside media playback: ")
|
|
||||||
)
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object VideoIdFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = emptyList(),
|
||||||
|
strings = listOf("Failed to download video (IllegalStateException): %s")
|
||||||
|
)
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.video.videoid.fingerprints
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -0,0 +1,19 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fingerprint is compatible with all versions of YouTube starting from v18.29.38 to supported versions.
|
||||||
|
* This method is invoked only in Shorts.
|
||||||
|
* Accurate video information is invoked even when the user moves Shorts upward or downward.
|
||||||
|
*/
|
||||||
|
internal object VideoIdFingerprintShorts : LiteralValueFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT
|
||||||
|
),
|
||||||
|
literalSupplier = { 45365621 }
|
||||||
|
)
|
@ -1,18 +1,11 @@
|
|||||||
package app.revanced.patches.youtube.video.information.fingerprints
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object VideoLengthFingerprint : LiteralValueFingerprint(
|
internal object VideoLengthFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = emptyList(),
|
strings = listOf("Gaplessly transitioning away from an Ad before it ends.")
|
||||||
opcodes = listOf(
|
)
|
||||||
Opcode.MOVE_RESULT_WIDE,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.INVOKE_VIRTUAL
|
|
||||||
),
|
|
||||||
literalSupplier = { 45388753 }
|
|
||||||
)
|
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object VideoTimeFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("L", "I", "J", "J", "J", "J")
|
||||||
|
)
|
@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.video.information.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.NotificationBigPictureIconWidth
|
||||||
|
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object VideoTitleFingerprint : LiteralValueFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = emptyList(),
|
||||||
|
literalSupplier = { NotificationBigPictureIconWidth }
|
||||||
|
)
|
@ -67,7 +67,6 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
DeviceDimensionsModelToStringFingerprint,
|
DeviceDimensionsModelToStringFingerprint,
|
||||||
HDRCapabilityFingerprint,
|
HDRCapabilityFingerprint,
|
||||||
PlaybackSpeedChangedFromRecyclerViewFingerprint,
|
PlaybackSpeedChangedFromRecyclerViewFingerprint,
|
||||||
PlaybackSpeedInitializeFingerprint,
|
|
||||||
QualityChangedFromRecyclerViewFingerprint,
|
QualityChangedFromRecyclerViewFingerprint,
|
||||||
QualityMenuViewInflateFingerprint,
|
QualityMenuViewInflateFingerprint,
|
||||||
QualitySetterFingerprint,
|
QualitySetterFingerprint,
|
||||||
@ -163,7 +162,7 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoInformationPatch.cpnHook("$INTEGRATIONS_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Z)V")
|
VideoInformationPatch.hookBackgroundPlay("$INTEGRATIONS_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
|
|
||||||
context.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "RememberPlaybackSpeed")
|
context.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "RememberPlaybackSpeed")
|
||||||
|
|
||||||
@ -195,8 +194,8 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
} ?: throw PatchException("Failed to find onItemClick method")
|
} ?: throw PatchException("Failed to find onItemClick method")
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
|
VideoInformationPatch.hook("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_RELOAD_VIDEO_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V")
|
VideoInformationPatch.hookBackgroundPlay("$INTEGRATIONS_RELOAD_VIDEO_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
@ -212,7 +211,7 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
addInstruction(
|
addInstruction(
|
||||||
insertIndex + 1,
|
insertIndex + 1,
|
||||||
"invoke-static { v$insertRegister }, " +
|
"invoke-static { v$insertRegister }, " +
|
||||||
"$INTEGRATIONS_RESTORE_OLD_VIDEO_QUALITY_MENU_CLASS_DESCRIPTOR->showOldVideoQualityMenu(Landroid/widget/ListView;)V"
|
"$INTEGRATIONS_RESTORE_OLD_VIDEO_QUALITY_MENU_CLASS_DESCRIPTOR->restoreOldVideoQualityMenu(Landroid/widget/ListView;)V"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val onItemClickMethod =
|
val onItemClickMethod =
|
||||||
@ -229,7 +228,7 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
invoke-static {}, $INTEGRATIONS_RESTORE_OLD_VIDEO_QUALITY_MENU_CLASS_DESCRIPTOR->showOldVideoQualityMenu()Z
|
invoke-static {}, $INTEGRATIONS_RESTORE_OLD_VIDEO_QUALITY_MENU_CLASS_DESCRIPTOR->restoreOldVideoQualityMenu()Z
|
||||||
move-result v$insertRegister
|
move-result v$insertRegister
|
||||||
if-nez v$insertRegister, :show
|
if-nez v$insertRegister, :show
|
||||||
""", ExternalLabel("show", getInstruction(jumpIndex))
|
""", ExternalLabel("show", getInstruction(jumpIndex))
|
||||||
|
@ -57,12 +57,12 @@ object PlayerResponseMethodHookPatch :
|
|||||||
val instruction =
|
val instruction =
|
||||||
if (shouldApplyNewMethod)
|
if (shouldApplyNewMethod)
|
||||||
"""
|
"""
|
||||||
invoke-static {v$PARAMETER_VIDEO_ID, v$PARAMETER_PLAYER_PARAMETER, v$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
invoke-static {v$PARAMETER_VIDEO_ID, v$PARAMETER_PLAYER_PARAMETER, v$PARAMETER_PLAYLIST_ID, v$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
||||||
move-result-object p3
|
move-result-object p3
|
||||||
"""
|
"""
|
||||||
else
|
else
|
||||||
"""
|
"""
|
||||||
invoke-static {p$PARAMETER_VIDEO_ID, p$PARAMETER_PLAYER_PARAMETER, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
invoke-static {p$PARAMETER_VIDEO_ID, p$PARAMETER_PLAYER_PARAMETER, p$PARAMETER_PLAYLIST_ID, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
||||||
move-result-object p$PARAMETER_PLAYER_PARAMETER
|
move-result-object p$PARAMETER_PLAYER_PARAMETER
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -10,11 +10,8 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
||||||
import app.revanced.patches.youtube.video.videoid.fingerprints.VideoIdFingerprint
|
import app.revanced.patches.youtube.video.videoid.fingerprints.VideoIdFingerprint
|
||||||
import app.revanced.patches.youtube.video.videoid.fingerprints.VideoIdFingerprintBackgroundPlay
|
|
||||||
import app.revanced.patches.youtube.video.videoid.fingerprints.VideoIdParentFingerprint
|
import app.revanced.patches.youtube.video.videoid.fingerprints.VideoIdParentFingerprint
|
||||||
import app.revanced.util.getTargetIndex
|
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
@ -22,19 +19,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|||||||
dependencies = [PlayerResponseMethodHookPatch::class],
|
dependencies = [PlayerResponseMethodHookPatch::class],
|
||||||
)
|
)
|
||||||
object VideoIdPatch : BytecodePatch(
|
object VideoIdPatch : BytecodePatch(
|
||||||
setOf(
|
setOf(VideoIdParentFingerprint)
|
||||||
VideoIdParentFingerprint,
|
|
||||||
VideoIdFingerprintBackgroundPlay
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
private var videoIdRegister = 0
|
private var videoIdRegister = 0
|
||||||
private var videoIdInsertIndex = 0
|
private var videoIdInsertIndex = 0
|
||||||
private lateinit var videoIdMethod: MutableMethod
|
private lateinit var videoIdMethod: MutableMethod
|
||||||
|
|
||||||
private var backgroundPlaybackVideoIdRegister = 0
|
|
||||||
private var backgroundPlaybackInsertIndex = 0
|
|
||||||
private lateinit var backgroundPlaybackMethod: MutableMethod
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,14 +49,6 @@ object VideoIdPatch : BytecodePatch(
|
|||||||
videoIdInsertIndex = index
|
videoIdInsertIndex = index
|
||||||
videoIdRegister = register
|
videoIdRegister = register
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoIdFingerprintBackgroundPlay.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
backgroundPlaybackMethod = this
|
|
||||||
backgroundPlaybackInsertIndex = getTargetIndex(Opcode.INVOKE_INTERFACE) + 2
|
|
||||||
backgroundPlaybackVideoIdRegister = getInstruction<OneRegisterInstruction>(backgroundPlaybackInsertIndex - 1).registerA
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,23 +69,6 @@ object VideoIdPatch : BytecodePatch(
|
|||||||
"invoke-static {v$videoIdRegister}, $methodDescriptor"
|
"invoke-static {v$videoIdRegister}, $methodDescriptor"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternate hook that supports only regular videos, but hook supports changing to new video
|
|
||||||
* during background play when no video is visible.
|
|
||||||
*
|
|
||||||
* _Does not support Shorts_.
|
|
||||||
*
|
|
||||||
* Be aware, the hook can be called multiple times for the same video id.
|
|
||||||
*
|
|
||||||
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
|
|
||||||
*/
|
|
||||||
fun hookBackgroundPlayVideoId(
|
|
||||||
methodDescriptor: String
|
|
||||||
) = backgroundPlaybackMethod.addInstruction(
|
|
||||||
backgroundPlaybackInsertIndex++, // move-result-object offset
|
|
||||||
"invoke-static {v$backgroundPlaybackVideoIdRegister}, $methodDescriptor"
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hooks the video id of every video when loaded.
|
* Hooks the video id of every video when loaded.
|
||||||
* Supports all videos and functions in all situations.
|
* Supports all videos and functions in all situations.
|
||||||
@ -120,8 +85,7 @@ object VideoIdPatch : BytecodePatch(
|
|||||||
* It's common for multiple Shorts to load at once in preparation
|
* It's common for multiple Shorts to load at once in preparation
|
||||||
* for the user swiping to the next Short.
|
* for the user swiping to the next Short.
|
||||||
*
|
*
|
||||||
* For most use cases, you probably want to use
|
* For most use cases, you probably want to use [hookVideoId] instead.
|
||||||
* [hookVideoId] or [hookBackgroundPlayVideoId] instead.
|
|
||||||
*
|
*
|
||||||
* Be aware, this can be called multiple times for the same video id.
|
* Be aware, this can be called multiple times for the same video id.
|
||||||
*
|
*
|
||||||
|
@ -1041,7 +1041,7 @@ Limitation: Official headers in search results will be hidden."</string>
|
|||||||
<string name="revanced_skip_preloaded_buffer_title">Skip preloaded buffer</string>
|
<string name="revanced_skip_preloaded_buffer_title">Skip preloaded buffer</string>
|
||||||
<string name="revanced_skip_preloaded_buffer_summary">"Skip preloaded buffer at video start to bypass default video quality enforcement delay.
|
<string name="revanced_skip_preloaded_buffer_summary">"Skip preloaded buffer at video start to bypass default video quality enforcement delay.
|
||||||
|
|
||||||
• When the video starts, there is a delay of approximately 0.7 seconds, but the default video quality is applied immediately.
|
• When the video starts, there is a delay of approximately 0.3 seconds, but the default video quality is applied immediately.
|
||||||
• Does not apply to HDR videos, live stream videos, videos shorter than 15 seconds."</string>
|
• Does not apply to HDR videos, live stream videos, videos shorter than 15 seconds."</string>
|
||||||
<string name="revanced_skip_preloaded_buffer_toast_title">Show a toast when skipped</string>
|
<string name="revanced_skip_preloaded_buffer_toast_title">Show a toast when skipped</string>
|
||||||
<string name="revanced_skip_preloaded_buffer_toast_summary_on">Toast is shown.</string>
|
<string name="revanced_skip_preloaded_buffer_toast_summary_on">Toast is shown.</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user