mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Updated config code for artifact-free 1080p60 streaming
This commit is contained in:
parent
26809c4b6b
commit
c93812179f
@ -0,0 +1,17 @@
|
||||
package com.limelight.nvstream.control;
|
||||
|
||||
public class ByteConfigTuple extends ConfigTuple {
|
||||
public static final short PAYLOAD_LENGTH = 1;
|
||||
|
||||
public byte payload;
|
||||
|
||||
public ByteConfigTuple(short packetType, byte payload) {
|
||||
super(packetType, PAYLOAD_LENGTH);
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] payloadToWire() {
|
||||
return new byte[] {payload};
|
||||
}
|
||||
}
|
@ -2,103 +2,114 @@ package com.limelight.nvstream.control;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.limelight.nvstream.StreamConfiguration;
|
||||
|
||||
public class Config {
|
||||
|
||||
public static final int[] UNKNOWN_CONFIG =
|
||||
public static final ConfigTuple[] CONFIG_720_60 =
|
||||
{
|
||||
70151,
|
||||
68291329,
|
||||
1280,
|
||||
68291584,
|
||||
1280,
|
||||
68291840,
|
||||
15360,
|
||||
68292096,
|
||||
25600,
|
||||
68292352,
|
||||
2048,
|
||||
68292608,
|
||||
1024,
|
||||
68289024,
|
||||
262144,
|
||||
17957632,
|
||||
302055424,
|
||||
134217729,
|
||||
16777490,
|
||||
70153,
|
||||
68293120,
|
||||
768000,
|
||||
17961216,
|
||||
303235072,
|
||||
335609857,
|
||||
838861842,
|
||||
352321536,
|
||||
1006634002,
|
||||
369098752,
|
||||
335545362,
|
||||
385875968,
|
||||
1042,
|
||||
402653184,
|
||||
134218770,
|
||||
419430400,
|
||||
167773202,
|
||||
436207616,
|
||||
855638290,
|
||||
266779,
|
||||
10000,
|
||||
266780,
|
||||
2000,
|
||||
266781,
|
||||
50,
|
||||
266782,
|
||||
3000,
|
||||
266783,
|
||||
2,
|
||||
266794,
|
||||
5000,
|
||||
266795,
|
||||
500,
|
||||
266784,
|
||||
75,
|
||||
266785,
|
||||
25,
|
||||
266786,
|
||||
10,
|
||||
266787,
|
||||
60,
|
||||
266788,
|
||||
30,
|
||||
266789,
|
||||
3,
|
||||
266790,
|
||||
1000,
|
||||
266791,
|
||||
5000,
|
||||
266792,
|
||||
5000,
|
||||
266793,
|
||||
5000,
|
||||
70190,
|
||||
68301063,
|
||||
10240,
|
||||
68301312,
|
||||
6400,
|
||||
68301568,
|
||||
768000,
|
||||
68299776,
|
||||
768,
|
||||
68300032,
|
||||
2560,
|
||||
68300544,
|
||||
0,
|
||||
34746368,
|
||||
(int)0xFE000000
|
||||
new IntConfigTuple((short)0x1206, 1),
|
||||
new ByteConfigTuple((short)0x1207, (byte)1),
|
||||
new IntConfigTuple((short)0x120b, 7),
|
||||
new IntConfigTuple((short)0x120c, 7),
|
||||
new IntConfigTuple((short)0x120d, 60),
|
||||
new IntConfigTuple((short)0x120e, 100),
|
||||
new IntConfigTuple((short)0x120f, 5),
|
||||
new IntConfigTuple((short)0x1210, 4),
|
||||
new IntConfigTuple((short)0x1202, 1024),
|
||||
new ByteConfigTuple((short)0x1203, (byte)0),
|
||||
new ByteConfigTuple((short)0x1201, (byte)0),
|
||||
new ByteConfigTuple((short)0x1234, (byte)0),
|
||||
new ByteConfigTuple((short)0x1248, (byte)0),
|
||||
new ByteConfigTuple((short)0x1208, (byte)1),
|
||||
new ByteConfigTuple((short)0x1209, (byte)0),
|
||||
new IntConfigTuple((short)0x1212, 3000),
|
||||
new IntConfigTuple((short)0x1238, 10000),
|
||||
new ByteConfigTuple((short)0x1211, (byte)0),
|
||||
new ByteConfigTuple((short)0x1213, (byte)1),
|
||||
new IntConfigTuple((short)0x1214, 50),
|
||||
new IntConfigTuple((short)0x1215, 60),
|
||||
new IntConfigTuple((short)0x1216, 20),
|
||||
new IntConfigTuple((short)0x1217, 0),
|
||||
new IntConfigTuple((short)0x1218, 8),
|
||||
new IntConfigTuple((short)0x1219, 10),
|
||||
new IntConfigTuple((short)0x121a, 311),
|
||||
new IntConfigTuple((short)0x121b, 10000),
|
||||
new IntConfigTuple((short)0x121c, 2000),
|
||||
new IntConfigTuple((short)0x121d, 50),
|
||||
new IntConfigTuple((short)0x121e, 3000),
|
||||
new IntConfigTuple((short)0x121f, 2),
|
||||
new IntConfigTuple((short)0x122a, 5000),
|
||||
new IntConfigTuple((short)0x122b, 500),
|
||||
new IntConfigTuple((short)0x1220, 75),
|
||||
new IntConfigTuple((short)0x1221, 25),
|
||||
new IntConfigTuple((short)0x1222, 10),
|
||||
new IntConfigTuple((short)0x1223, 60),
|
||||
new IntConfigTuple((short)0x1224, 30),
|
||||
new IntConfigTuple((short)0x1225, 3),
|
||||
new IntConfigTuple((short)0x1226, 1000),
|
||||
new IntConfigTuple((short)0x1227, 5000),
|
||||
new IntConfigTuple((short)0x1228, 5000),
|
||||
new IntConfigTuple((short)0x124e, 110),
|
||||
new IntConfigTuple((short)0x1237, 10),
|
||||
new IntConfigTuple((short)0x1236, 6),
|
||||
new IntConfigTuple((short)0x1235, 4),
|
||||
new IntConfigTuple((short)0x1242, 20000),
|
||||
new IntConfigTuple((short)0x1244, 100),
|
||||
new IntConfigTuple((short)0x1245, 1000),
|
||||
new IntConfigTuple((short)0x1246, 720),
|
||||
new IntConfigTuple((short)0x1247, 480),
|
||||
new IntConfigTuple((short)0x1229, 5000),
|
||||
new ByteConfigTuple((short)0x122e, (byte)7),
|
||||
new IntConfigTuple((short)0x1231, 40),
|
||||
new IntConfigTuple((short)0x1232, 25),
|
||||
new IntConfigTuple((short)0x1233, 3000),
|
||||
new IntConfigTuple((short)0x122c, 3),
|
||||
new IntConfigTuple((short)0x122d, 10),
|
||||
new IntConfigTuple((short)0x123b, 12),
|
||||
new IntConfigTuple((short)0x123c, 3),
|
||||
new IntConfigTuple((short)0x1249, 0),
|
||||
new IntConfigTuple((short)0x124a, 4000),
|
||||
new IntConfigTuple((short)0x124b, 5000),
|
||||
new IntConfigTuple((short)0x124c, 6000),
|
||||
new IntConfigTuple((short)0x124d, 1000),
|
||||
new IntConfigTuple((short)0x122f, 0),
|
||||
new ShortConfigTuple((short)0x1230, (short)0),
|
||||
new IntConfigTuple((short)0x1239, 0),
|
||||
new IntConfigTuple((short)0x123a, 0),
|
||||
new IntConfigTuple((short)0x123d, 96000),
|
||||
new IntConfigTuple((short)0x123e, 5),
|
||||
new IntConfigTuple((short)0x123f, 1),
|
||||
new IntConfigTuple((short)0x1243, 100)
|
||||
};
|
||||
|
||||
public static final int CONFIG_SIZE = ((8 + UNKNOWN_CONFIG.length) * 4) + 3;
|
||||
public static final ConfigTuple[] CONFIG_1080_30_DIFF =
|
||||
{
|
||||
new IntConfigTuple((short)0x120b, 10),
|
||||
new IntConfigTuple((short)0x120c, 10),
|
||||
new IntConfigTuple((short)0x121c, 4000),
|
||||
new IntConfigTuple((short)0x1245, 3000),
|
||||
new IntConfigTuple((short)0x1246, 1280),
|
||||
new IntConfigTuple((short)0x1247, 720),
|
||||
new IntConfigTuple((short)0x124a, 5000),
|
||||
new IntConfigTuple((short)0x124c, 7000),
|
||||
};
|
||||
|
||||
public static final ConfigTuple[] CONFIG_1080_60_DIFF =
|
||||
{
|
||||
new IntConfigTuple((short)0x120b, 30),
|
||||
new IntConfigTuple((short)0x120c, 30),
|
||||
new IntConfigTuple((short)0x120f, 4),
|
||||
new IntConfigTuple((short)0x121b, 30000),
|
||||
new IntConfigTuple((short)0x121c, 25000),
|
||||
new IntConfigTuple((short)0x1245, 3000),
|
||||
new IntConfigTuple((short)0x1246, 1280),
|
||||
new IntConfigTuple((short)0x1247, 720),
|
||||
new IntConfigTuple((short)0x124a, 5000),
|
||||
new IntConfigTuple((short)0x124c, 7000),
|
||||
};
|
||||
|
||||
private StreamConfiguration streamConfig;
|
||||
|
||||
@ -106,37 +117,69 @@ public class Config {
|
||||
this.streamConfig = streamConfig;
|
||||
}
|
||||
|
||||
private void updateSetWithConfig(HashSet<ConfigTuple> set, ConfigTuple[] config)
|
||||
{
|
||||
for (ConfigTuple tuple : config)
|
||||
{
|
||||
// Remove any existing tuple of this type
|
||||
set.remove(tuple);
|
||||
|
||||
set.add(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
private int getConfigOnWireSize(HashSet<ConfigTuple> tupleSet)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
for (ConfigTuple t : tupleSet)
|
||||
{
|
||||
size += ConfigTuple.HEADER_LENGTH + t.payloadLength;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
private HashSet<ConfigTuple> generateTupleSet() {
|
||||
HashSet<ConfigTuple> tupleSet = new HashSet<ConfigTuple>();
|
||||
|
||||
// Start with the initial config for 720p60
|
||||
updateSetWithConfig(tupleSet, CONFIG_720_60);
|
||||
|
||||
if (streamConfig.getWidth() >= 1920 &&
|
||||
streamConfig.getHeight() >= 1080)
|
||||
{
|
||||
if (streamConfig.getRefreshRate() >= 60)
|
||||
{
|
||||
// Update the initial set with the changed 1080p60 options
|
||||
updateSetWithConfig(tupleSet, CONFIG_1080_60_DIFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the initial set with the changed 1080p30 options
|
||||
updateSetWithConfig(tupleSet, CONFIG_1080_30_DIFF);
|
||||
}
|
||||
}
|
||||
|
||||
tupleSet.add(new IntConfigTuple((short)0x1204, streamConfig.getWidth()));
|
||||
tupleSet.add(new IntConfigTuple((short)0x1205, streamConfig.getHeight()));
|
||||
tupleSet.add(new IntConfigTuple((short)0x120A, streamConfig.getRefreshRate()));
|
||||
|
||||
return tupleSet;
|
||||
}
|
||||
|
||||
public byte[] toWire() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(CONFIG_SIZE).order(ByteOrder.LITTLE_ENDIAN);
|
||||
HashSet<ConfigTuple> tupleSet = generateTupleSet();
|
||||
ByteBuffer bb = ByteBuffer.allocate(getConfigOnWireSize(tupleSet) + 4).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
// Width
|
||||
bb.putShort((short) 0x1204);
|
||||
bb.putShort((short) 0x0004);
|
||||
bb.putInt(streamConfig.getWidth());
|
||||
|
||||
// Height
|
||||
bb.putShort((short) 0x1205);
|
||||
bb.putShort((short) 0x0004);
|
||||
bb.putInt(streamConfig.getHeight());
|
||||
|
||||
// Unknown
|
||||
bb.putShort((short) 0x1206);
|
||||
bb.putShort((short) 0x0004);
|
||||
bb.putInt(1);
|
||||
|
||||
// Refresh rate
|
||||
bb.putShort((short) 0x120A);
|
||||
bb.putShort((short) 0x0004);
|
||||
bb.putInt(streamConfig.getRefreshRate());
|
||||
|
||||
// The rest are hardcoded
|
||||
for (int i : UNKNOWN_CONFIG) {
|
||||
bb.putInt(i);
|
||||
for (ConfigTuple t : tupleSet)
|
||||
{
|
||||
bb.put(t.toWire());
|
||||
}
|
||||
|
||||
// Config tail
|
||||
bb.putShort((short) 0x0013);
|
||||
bb.put((byte) 0x00);
|
||||
bb.putShort((short) 0x13fe);
|
||||
bb.putShort((short) 0x00);
|
||||
|
||||
return bb.array();
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
package com.limelight.nvstream.control;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public abstract class ConfigTuple {
|
||||
public short packetType;
|
||||
public short payloadLength;
|
||||
|
||||
public static final short HEADER_LENGTH = 4;
|
||||
|
||||
public ConfigTuple(short packetType, short payloadLength)
|
||||
{
|
||||
this.packetType = packetType;
|
||||
this.payloadLength = payloadLength;
|
||||
}
|
||||
|
||||
public abstract byte[] payloadToWire();
|
||||
|
||||
public byte[] toWire()
|
||||
{
|
||||
byte[] payload = payloadToWire();
|
||||
ByteBuffer bb = ByteBuffer.allocate(HEADER_LENGTH + (payload != null ? payload.length : 0))
|
||||
.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
bb.putShort(packetType);
|
||||
bb.putShort(payloadLength);
|
||||
|
||||
if (payload != null) {
|
||||
bb.put(payload);
|
||||
}
|
||||
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return packetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
// We only compare the packet types on purpose
|
||||
if (o instanceof ConfigTuple) {
|
||||
return ((ConfigTuple)o).packetType == packetType;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.limelight.nvstream.control;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class IntConfigTuple extends ConfigTuple {
|
||||
|
||||
public static final short PAYLOAD_LENGTH = 4;
|
||||
|
||||
public int payload;
|
||||
|
||||
public IntConfigTuple(short packetType, int payload) {
|
||||
super(packetType, PAYLOAD_LENGTH);
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] payloadToWire() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(PAYLOAD_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
|
||||
bb.putInt(payload);
|
||||
return bb.array();
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.limelight.nvstream.control;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class ShortConfigTuple extends ConfigTuple {
|
||||
|
||||
public static final short PAYLOAD_LENGTH = 2;
|
||||
|
||||
public short payload;
|
||||
|
||||
public ShortConfigTuple(short packetType, short payload) {
|
||||
super(packetType, PAYLOAD_LENGTH);
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] payloadToWire() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(PAYLOAD_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
|
||||
bb.putShort(payload);
|
||||
return bb.array();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user