mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 19:42:45 +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.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
import com.limelight.nvstream.StreamConfiguration;
|
import com.limelight.nvstream.StreamConfiguration;
|
||||||
|
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
public static final int[] UNKNOWN_CONFIG =
|
public static final ConfigTuple[] CONFIG_720_60 =
|
||||||
{
|
{
|
||||||
70151,
|
new IntConfigTuple((short)0x1206, 1),
|
||||||
68291329,
|
new ByteConfigTuple((short)0x1207, (byte)1),
|
||||||
1280,
|
new IntConfigTuple((short)0x120b, 7),
|
||||||
68291584,
|
new IntConfigTuple((short)0x120c, 7),
|
||||||
1280,
|
new IntConfigTuple((short)0x120d, 60),
|
||||||
68291840,
|
new IntConfigTuple((short)0x120e, 100),
|
||||||
15360,
|
new IntConfigTuple((short)0x120f, 5),
|
||||||
68292096,
|
new IntConfigTuple((short)0x1210, 4),
|
||||||
25600,
|
new IntConfigTuple((short)0x1202, 1024),
|
||||||
68292352,
|
new ByteConfigTuple((short)0x1203, (byte)0),
|
||||||
2048,
|
new ByteConfigTuple((short)0x1201, (byte)0),
|
||||||
68292608,
|
new ByteConfigTuple((short)0x1234, (byte)0),
|
||||||
1024,
|
new ByteConfigTuple((short)0x1248, (byte)0),
|
||||||
68289024,
|
new ByteConfigTuple((short)0x1208, (byte)1),
|
||||||
262144,
|
new ByteConfigTuple((short)0x1209, (byte)0),
|
||||||
17957632,
|
new IntConfigTuple((short)0x1212, 3000),
|
||||||
302055424,
|
new IntConfigTuple((short)0x1238, 10000),
|
||||||
134217729,
|
new ByteConfigTuple((short)0x1211, (byte)0),
|
||||||
16777490,
|
new ByteConfigTuple((short)0x1213, (byte)1),
|
||||||
70153,
|
new IntConfigTuple((short)0x1214, 50),
|
||||||
68293120,
|
new IntConfigTuple((short)0x1215, 60),
|
||||||
768000,
|
new IntConfigTuple((short)0x1216, 20),
|
||||||
17961216,
|
new IntConfigTuple((short)0x1217, 0),
|
||||||
303235072,
|
new IntConfigTuple((short)0x1218, 8),
|
||||||
335609857,
|
new IntConfigTuple((short)0x1219, 10),
|
||||||
838861842,
|
new IntConfigTuple((short)0x121a, 311),
|
||||||
352321536,
|
new IntConfigTuple((short)0x121b, 10000),
|
||||||
1006634002,
|
new IntConfigTuple((short)0x121c, 2000),
|
||||||
369098752,
|
new IntConfigTuple((short)0x121d, 50),
|
||||||
335545362,
|
new IntConfigTuple((short)0x121e, 3000),
|
||||||
385875968,
|
new IntConfigTuple((short)0x121f, 2),
|
||||||
1042,
|
new IntConfigTuple((short)0x122a, 5000),
|
||||||
402653184,
|
new IntConfigTuple((short)0x122b, 500),
|
||||||
134218770,
|
new IntConfigTuple((short)0x1220, 75),
|
||||||
419430400,
|
new IntConfigTuple((short)0x1221, 25),
|
||||||
167773202,
|
new IntConfigTuple((short)0x1222, 10),
|
||||||
436207616,
|
new IntConfigTuple((short)0x1223, 60),
|
||||||
855638290,
|
new IntConfigTuple((short)0x1224, 30),
|
||||||
266779,
|
new IntConfigTuple((short)0x1225, 3),
|
||||||
10000,
|
new IntConfigTuple((short)0x1226, 1000),
|
||||||
266780,
|
new IntConfigTuple((short)0x1227, 5000),
|
||||||
2000,
|
new IntConfigTuple((short)0x1228, 5000),
|
||||||
266781,
|
new IntConfigTuple((short)0x124e, 110),
|
||||||
50,
|
new IntConfigTuple((short)0x1237, 10),
|
||||||
266782,
|
new IntConfigTuple((short)0x1236, 6),
|
||||||
3000,
|
new IntConfigTuple((short)0x1235, 4),
|
||||||
266783,
|
new IntConfigTuple((short)0x1242, 20000),
|
||||||
2,
|
new IntConfigTuple((short)0x1244, 100),
|
||||||
266794,
|
new IntConfigTuple((short)0x1245, 1000),
|
||||||
5000,
|
new IntConfigTuple((short)0x1246, 720),
|
||||||
266795,
|
new IntConfigTuple((short)0x1247, 480),
|
||||||
500,
|
new IntConfigTuple((short)0x1229, 5000),
|
||||||
266784,
|
new ByteConfigTuple((short)0x122e, (byte)7),
|
||||||
75,
|
new IntConfigTuple((short)0x1231, 40),
|
||||||
266785,
|
new IntConfigTuple((short)0x1232, 25),
|
||||||
25,
|
new IntConfigTuple((short)0x1233, 3000),
|
||||||
266786,
|
new IntConfigTuple((short)0x122c, 3),
|
||||||
10,
|
new IntConfigTuple((short)0x122d, 10),
|
||||||
266787,
|
new IntConfigTuple((short)0x123b, 12),
|
||||||
60,
|
new IntConfigTuple((short)0x123c, 3),
|
||||||
266788,
|
new IntConfigTuple((short)0x1249, 0),
|
||||||
30,
|
new IntConfigTuple((short)0x124a, 4000),
|
||||||
266789,
|
new IntConfigTuple((short)0x124b, 5000),
|
||||||
3,
|
new IntConfigTuple((short)0x124c, 6000),
|
||||||
266790,
|
new IntConfigTuple((short)0x124d, 1000),
|
||||||
1000,
|
new IntConfigTuple((short)0x122f, 0),
|
||||||
266791,
|
new ShortConfigTuple((short)0x1230, (short)0),
|
||||||
5000,
|
new IntConfigTuple((short)0x1239, 0),
|
||||||
266792,
|
new IntConfigTuple((short)0x123a, 0),
|
||||||
5000,
|
new IntConfigTuple((short)0x123d, 96000),
|
||||||
266793,
|
new IntConfigTuple((short)0x123e, 5),
|
||||||
5000,
|
new IntConfigTuple((short)0x123f, 1),
|
||||||
70190,
|
new IntConfigTuple((short)0x1243, 100)
|
||||||
68301063,
|
|
||||||
10240,
|
|
||||||
68301312,
|
|
||||||
6400,
|
|
||||||
68301568,
|
|
||||||
768000,
|
|
||||||
68299776,
|
|
||||||
768,
|
|
||||||
68300032,
|
|
||||||
2560,
|
|
||||||
68300544,
|
|
||||||
0,
|
|
||||||
34746368,
|
|
||||||
(int)0xFE000000
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
private StreamConfiguration streamConfig;
|
||||||
|
|
||||||
@ -106,37 +117,69 @@ public class Config {
|
|||||||
this.streamConfig = streamConfig;
|
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() {
|
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
|
for (ConfigTuple t : tupleSet)
|
||||||
bb.putShort((short) 0x1204);
|
{
|
||||||
bb.putShort((short) 0x0004);
|
bb.put(t.toWire());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config tail
|
// Config tail
|
||||||
bb.putShort((short) 0x0013);
|
bb.putShort((short) 0x13fe);
|
||||||
bb.put((byte) 0x00);
|
bb.putShort((short) 0x00);
|
||||||
|
|
||||||
return bb.array();
|
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