Skip to content

Commit

Permalink
fix(YouTube - Spoof format stream data): Check audio tags first
Browse files Browse the repository at this point in the history
  • Loading branch information
anddea committed May 16, 2024
1 parent 5a066dd commit 5589897
Showing 1 changed file with 33 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.utils.compatibility.Constants
import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.FormatStreamModelConstructorFingerprint
import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.PlaybackStartFingerprint
Expand All @@ -15,6 +16,7 @@ import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHoo
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.getReference
import app.revanced.util.getStringInstructionIndex
import app.revanced.util.getTargetIndex
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
Expand Down Expand Up @@ -56,31 +58,46 @@ object SpoofFormatStreamDataPatch : BaseBytecodePatch(
private const val STREAMING_DATA_OUTER_CLASS =
"Lcom/google/protos/youtube/api/innertube/StreamingDataOuterClass\$StreamingData;"

private lateinit var hookMethod: MutableMethod

private fun MutableMethod.replaceFieldName(
index: Int,
replaceFieldString: String
) {
val reference = getInstruction<ReferenceInstruction>(index).reference
val fieldName = (reference as FieldReference).name

hookMethod.apply {
val stringIndex = getStringInstructionIndex(replaceFieldString)
val stringRegister = getInstruction<OneRegisterInstruction>(stringIndex).registerA

replaceInstruction(
stringIndex,
"const-string v$stringRegister, \"$fieldName\""
)
}
}

override fun execute(context: BytecodeContext) {

// Hook player response video id, to start loading format stream data sooner in the background.
VideoIdPatch.hookPlayerResponseVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")

hookMethod = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!
.mutableClass.methods.find { method -> method.name == INTEGRATIONS_METHOD_DESCRIPTOR }
?: throw PatchException("SpoofFormatStreamDataPatch not found")

FormatStreamModelConstructorFingerprint.resultOrThrow().let {
it.mutableMethod.apply {

// Find the field name that will be used for reflection.
val streamDataIndex = it.scanResult.patternScanResult!!.startIndex
val streamDataReference = getInstruction<ReferenceInstruction>(streamDataIndex).reference
val streamDataFieldName = (streamDataReference as FieldReference).name

// Found field name is reflected in the integration.
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!
.mutableClass.methods.find { method -> method.name == INTEGRATIONS_METHOD_DESCRIPTOR }
?.apply {
val index = getStringInstructionIndex("replaceMeWithFieldName")
val register = getInstruction<OneRegisterInstruction>(index).registerA

replaceInstruction(
index,
"const-string v$register, \"$streamDataFieldName\""
)
} ?: throw PatchException("SpoofFormatStreamDataPatch not found")
val urlIndex = it.scanResult.patternScanResult!!.startIndex
val itagIndex = getTargetIndex(urlIndex + 1, Opcode.IGET)
val audioCodecParameterIndex = getTargetIndex(urlIndex + 1, Opcode.IGET_OBJECT)

replaceFieldName(urlIndex, "replaceMeWithUrlFieldName")
replaceFieldName(itagIndex, "replaceMeWithITagFieldName")
replaceFieldName(audioCodecParameterIndex, "replaceMeWithAudioCodecParameterFieldName")
}
}

Expand Down

0 comments on commit 5589897

Please sign in to comment.