Skip to content

Commit 31e0c42

Browse files
committed
Update video quality handling in Unobfuscator and MediaQuality features.
1 parent 89416fe commit 31e0c42

File tree

2 files changed

+107
-32
lines changed

2 files changed

+107
-32
lines changed

app/src/main/java/com/wmods/wppenhacer/xposed/core/devkit/Unobfuscator.java

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -499,10 +499,18 @@ public synchronized static HashMap<String, Field> loadMediaQualityVideoFields(Cl
499499
var usingFields = Objects.requireNonNull(methodData).getUsingFields();
500500
var usingStrings = Objects.requireNonNull(methodData).getUsingStrings();
501501
var result = new HashMap<String, Field>();
502-
for (int i = 0; i < usingStrings.size(); i++) {
503-
if (i == usingFields.size()) break;
504-
var field = usingFields.get(i).getField().getFieldInstance(classLoader);
505-
result.put(usingStrings.get(i), field);
502+
var idxStrings = 0;
503+
var idxFields = 0;
504+
while (idxStrings < usingStrings.size()) {
505+
if (idxFields == usingFields.size()) break;
506+
if (usingStrings.get(idxStrings).equals("outputAspectRatio")) {
507+
idxStrings++;
508+
continue;
509+
}
510+
var field = usingFields.get(idxFields).getField().getFieldInstance(classLoader);
511+
result.put(usingStrings.get(idxStrings), field);
512+
idxStrings++;
513+
idxFields++;
506514
}
507515
return result;
508516
});
@@ -530,6 +538,56 @@ public synchronized static HashMap<String, Field> loadMediaQualityOriginalVideoF
530538
});
531539
}
532540

541+
public synchronized static Class<?> loadProcessVideoQualityClass(ClassLoader classLoader) throws Exception {
542+
return UnobfuscatorCache.getInstance().getClass(classLoader, () -> {
543+
var clazz = findFirstClassUsingStrings(classLoader, StringMatchType.Contains, "ProcessVideoQuality(");
544+
if (clazz == null) throw new Exception("ProcessVideoQuality method not found");
545+
return clazz;
546+
});
547+
}
548+
549+
550+
public synchronized static HashMap<String, Field> loadProcessVideoQualityFields(ClassLoader classLoader) throws Exception {
551+
return UnobfuscatorCache.getInstance().getMapField(classLoader, () -> {
552+
var clazz = loadProcessVideoQualityClass(classLoader);
553+
Method methodString;
554+
try {
555+
methodString = clazz.getDeclaredMethod("toString");
556+
} catch (Exception e) {
557+
return new HashMap<>();
558+
}
559+
var methodData = dexkit.getMethodData(methodString);
560+
var usingFields = Objects.requireNonNull(methodData).getUsingFields();
561+
var usingStrings = Objects.requireNonNull(methodData).getUsingStrings();
562+
var result = new HashMap<String, Field>();
563+
var idxFields = 0;
564+
for (int i = 0; i < usingStrings.size(); i++) {
565+
if (idxFields == usingFields.size()) break;
566+
var raw = usingStrings.get(i);
567+
if (raw == null) continue;
568+
var string = raw.strip();
569+
if (string.isEmpty()) continue;
570+
int eq = string.lastIndexOf('=');
571+
if (eq < 0) continue;
572+
int start = 0;
573+
for (int j = eq - 1; j >= 0; j--) {
574+
char c = string.charAt(j);
575+
if (c == '\'' || c == ',' || c == ' ' || c == '(' || c == ')' || c == ':' || c == '{' || c == '}') {
576+
start = j + 1;
577+
break;
578+
}
579+
}
580+
if (start >= eq) continue;
581+
var name = string.substring(start, eq);
582+
if (name.isEmpty()) continue;
583+
var field = usingFields.get(idxFields).getField().getFieldInstance(classLoader);
584+
result.put(name, field);
585+
idxFields++;
586+
}
587+
return result;
588+
});
589+
}
590+
533591
// TODO: Classes and methods to ShareLimit
534592

535593

app/src/main/java/com/wmods/wppenhacer/xposed/features/media/MediaQuality.java

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import org.json.JSONObject;
1515

16-
import java.util.concurrent.atomic.AtomicReference;
16+
import java.lang.reflect.Field;
1717

1818
import de.robv.android.xposed.XC_MethodHook;
1919
import de.robv.android.xposed.XC_MethodReplacement;
@@ -49,33 +49,50 @@ public void doHook() throws Exception {
4949

5050
Others.propsBoolean.put(5549, true); // Use bitrate from json to force video high quality
5151

52-
var jsonProperty = Unobfuscator.loadPropsJsonMethod(classLoader);
52+
var processVideoQualityClass = Unobfuscator.loadProcessVideoQualityClass(classLoader);
53+
var processVideoQualityFields = Unobfuscator.loadProcessVideoQualityFields(classLoader);
5354

54-
AtomicReference<XC_MethodHook.Unhook> jsonPropertyHook = new AtomicReference<>();
55-
56-
var unhooked = XposedBridge.hookMethod(jsonProperty, new XC_MethodHook() {
55+
XposedBridge.hookAllConstructors(processVideoQualityClass, new XC_MethodHook() {
5756
@Override
5857
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
59-
var value = ReflectionUtils.getArg(param.args, Integer.class, 0);
60-
if (value == 5550) {
61-
JSONObject videoBitrateData = new JSONObject();
62-
String[] resolutions = {"360", "480", "720", "1080"};
63-
for (String resolution : resolutions) {
64-
JSONObject resolutionData = new JSONObject();
65-
resolutionData.put("min_bitrate", 3000);
66-
resolutionData.put("max_bitrate", 96000);
67-
resolutionData.put("null_bitrate", 96000);
68-
resolutionData.put("min_bandwidth", 1);
69-
resolutionData.put("max_bandwidth", 1);
70-
videoBitrateData.put(resolution, resolutionData);
71-
}
72-
param.setResult(videoBitrateData);
73-
} else if (value == 9705) {
74-
param.setResult(new JSONObject());
75-
}
58+
Field videoMaxEdge = processVideoQualityFields.get("videoMaxEdge");
59+
videoMaxEdge.setInt(param.thisObject, 8000);
60+
Field videoMaxBitrate = processVideoQualityFields.get("videoMaxBitrate");
61+
videoMaxBitrate.setInt(param.thisObject, 96000000);
7662
}
7763
});
78-
jsonPropertyHook.set(unhooked);
64+
65+
66+
// var jsonProperty = Unobfuscator.loadPropsJsonMethod(classLoader);
67+
//
68+
// AtomicReference<XC_MethodHook.Unhook> jsonPropertyHook = new AtomicReference<>();
69+
//
70+
// var unhooked = XposedBridge.hookMethod(jsonProperty, new XC_MethodHook() {
71+
// @Override
72+
// protected void afterHookedMethod(MethodHookParam param) throws Throwable {
73+
// var value = ReflectionUtils.getArg(param.args, Integer.class, 0);
74+
// if (value == 5550) {
75+
// JSONObject videoBitrateData = new JSONObject();
76+
// String[] resolutions = {"360", "480", "720", "1080"};
77+
// int[] minBitrates = {1500, 2500, 10000, 16000};
78+
// int[] maxBitrates = {2500, 4000, 16000, 24000};
79+
// for (int i = 0; i < resolutions.length; i++) {
80+
// String resolution = resolutions[i];
81+
// JSONObject resolutionData = new JSONObject();
82+
// resolutionData.put("min_bitrate", minBitrates[i]);
83+
// resolutionData.put("max_bitrate", maxBitrates[i]);
84+
// resolutionData.put("null_bitrate", maxBitrates[i]);
85+
// resolutionData.put("min_bandwidth", 1);
86+
// resolutionData.put("max_bandwidth", 1);
87+
// videoBitrateData.put(resolution, resolutionData);
88+
// }
89+
// param.setResult(videoBitrateData);
90+
// } else if (value == 9705) {
91+
// param.setResult(new JSONObject());
92+
// }
93+
// }
94+
// });
95+
// jsonPropertyHook.set(unhooked);
7996

8097
var videoMethod = Unobfuscator.loadMediaQualityVideoMethod2(classLoader);
8198
logDebug(Unobfuscator.getMethodDescriptor(videoMethod));
@@ -108,9 +125,9 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
108125

109126
if (mediaFields.isEmpty()) {
110127
if (isEnum) {
111-
width = intParams.get(0).second;
112-
height = intParams.get(1).second;
113-
rotationAngle = intParams.get(2).second;
128+
width = intParams.get(intParams.size() - 3).second;
129+
height = intParams.get(intParams.size() - 2).second;
130+
rotationAngle = intParams.get(intParams.size() - 1).second;
114131
} else {
115132
JSONObject mediaFields = (JSONObject) XposedHelpers.callMethod(param.args[0], "A00");
116133
width = mediaFields.getInt("widthPx");
@@ -131,13 +148,13 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
131148
targetWidthField.setInt(resizeVideo, inverted ? height : width);
132149

133150
}
134-
135151
}
136152
if (prefs.getBoolean("video_maxfps", false)) {
137153
var frameRateField = mediaTranscodeParams.get("frameRate");
138154
frameRateField.setInt(resizeVideo, 60);
139155
}
140156
}
157+
141158
});
142159

143160
// HD video must be sent in maximum resolution (up to 4K)
@@ -204,4 +221,4 @@ public String getPluginName() {
204221
return "Media Quality";
205222
}
206223

207-
}
224+
}

0 commit comments

Comments
 (0)