我有一个Nexus 5X,它有间歇性的接收问题。我已经能够在华硕平板电脑,两个三星平板电脑和Kindle Fire上运行代码,没有任何问题。代码基于此存储库: https://github.com/moonlight-stream/moonlight-common/blob/master/src/com/limelight/nvstream/av/video/VideoStream.java
以下是相关代码:
WifiManager wifiMgr = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Player");
wifiLock.setReferenceCounted(false);
wifiLock.acquire();
rtp = new DatagramSocket(RTP_PORT);
rtp.setReceiveBufferSize(256*1024);
// Receive thread
Thread t = new Thread() {
@Override
public void run() {
while (!isInterrupted())
{
try {
// Pull the next buffer in the ring and reset it
buffer = ring[ringIndex].getBuffer();
// Read the video data off the network
packet.setData(buffer, 0, buffer.length);
rtp.receive(packet);
// Do processing here
} catch (IOException e) {
return;
}
}
}
};
threads.add(t);
t.setName("Video - Receive");
t.setPriority(Thread.MAX_PRIORITY - 1);
t.start();
我确信我可以正确地将UDP流发送到设备。大多数数据包都是正确接收的。但是,我在方法跟踪中注意到了
rtp.receive(packet);
可以阻止100s-1000s毫秒。当在完全相同的架构中的不同设备上运行时,我看到基本上100%的数据包成功,最大块可能是60ms。
我在2.4G和5G上尝试过多个路由器。问题出在设备上。
正在发送的数据包是UDP直接到设备。网络上没有IP冲突。
对可能出现的问题有任何疑问?非常感谢你!
编辑:我应该注意CPU使用率约为2%,内存使用量约为10MB
编辑2:我创建了一个简单的应用程序来简单地调查此问题。我看到了同样的结果。我会在几台设备上看到30,000多个连续数据包而没有一个丢包。我会在Nexus 5X上每隔几秒丢弃一系列数据包。我有人在他们的Nexus 5X上远程运行这个测试应用程序,并且他们报告没有丢弃数据包。据我所知,所有迹象都指向司机/无线电问题......
package com.udp_receiver_test;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.ByteBuffer;
public class MainActivity extends AppCompatActivity {
private WifiManager.WifiLock wifiLock;
Thread t;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Player");
wifiLock.setReferenceCounted(false);
wifiLock.acquire();
// Use sustained performance mode on N+ to ensure consistent
// CPU availability
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
getWindow().setSustainedPerformanceMode(true);
}
startListenThread();
}
private void startListenThread()
{
t = new Thread() {
@Override
public void run()
{
DatagramSocket socket;
int nextSequenceNumber = 0;
ByteBuffer byteBuffer;
int BufferSize = 1292;
int NumRingElements = 784;
long correctPacketCounter = 0;
byte ring[][] = new byte[NumRingElements][1292];
try {
socket = new DatagramSocket(12345);
socket.setReceiveBufferSize(256 * 1024);
} catch (Exception e) {
e.printStackTrace();
return;
}
byte[] buffer;
int ringCounter = 0;
DatagramPacket packet = new DatagramPacket(new byte[1], 1);
//short rtpSequenceNumber;
int sequenceNumber;
while (!isInterrupted()) {
try {
buffer = ring[ringCounter];
packet.setData(buffer, 0, buffer.length);
socket.receive(packet);
if (packet.getLength() > 20) {
// Read the RTP sequence number field (big endian)
byteBuffer = ByteBuffer.wrap(buffer);
byteBuffer.position(16);
sequenceNumber = (byteBuffer.getInt() >> 8) & 0xFFFFFF;
if (sequenceNumber != nextSequenceNumber) {
Log.d("TAG", "Not next sequence number - Got:" + sequenceNumber + " Expected:" + nextSequenceNumber);
} else {
if (((++correctPacketCounter) % 100) == 0)
{
Log.d("TAG", "Correct packets = " + correctPacketCounter);
}
}
nextSequenceNumber = (sequenceNumber + 256) % 65535;
} else {
Log.d("TAG", "Message too short");
}
ringCounter = (ringCounter + 1) % NumRingElements;
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
};
t.setName("Receiver");
t.setPriority(Thread.MAX_PRIORITY - 1);
t.start();
}
@Override
public void onStop()
{
super.onStop();
wifiLock.release();
if (t.isAlive()) {
t.interrupt();
}
}
}