gpt4 book ai didi

java - 强制 Java Android Socket 立即发送数据

转载 作者:行者123 更新时间:2023-11-30 01:15:02 25 4
gpt4 key购买 nike

作为一个业余爱好项目,我正在编写一个 android voip 客户端。将语音数据写入套接字 (Vars.mediaSocket) 时,很多时候,数据不会立即通过 wifi 发送出去,而是会暂停,然后它会立即发送 20 秒的语音。然后它会再次停顿并等待 30 秒,然后发送 30 秒的语音。等待不一致,但过一段时间后会立即连续发送语音数据。我尝试了所有方法,从使用 DataOutputStream 到设置套接字输出缓冲区大小,将发送缓冲区大小设置为大、小,最后,将语音数据从其 32 字节 block 缓冲到 128 字节到 32kb 之间的任何大小。

        Utils.logcat(Const.LOGD, encTag, "MediaCodec encoder thread has started");
isEncoding = true;
byte[] amrbuffer = new byte[32];
short[] wavbuffer = new short[160];
int outputCounter = 0;

//setup the wave audio recorder. since it is released and restarted, it needs to be setup here and not onCreate
wavRecorder = null; //remove pointer to the old recorder for safety
wavRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLESWAV, AudioFormat.CHANNEL_IN_MONO, FORMAT, 160);
wavRecorder.startRecording();
AmrEncoder.init(0);

while(!micMute)
{
int totalRead = 0, dataRead;
while(totalRead < 160)
{//although unlikely to be necessary, buffer the mic input
dataRead = wavRecorder.read(wavbuffer, totalRead, 160 - totalRead);
totalRead = totalRead + dataRead;
}
int encodeLength = AmrEncoder.encode(AmrEncoder.Mode.MR122.ordinal(), wavbuffer, amrbuffer);

try
{
Vars.mediaSocket.getOutputStream().write(amrbuffer);
Vars.mediaSocket.getOutputStream().flush();
}
catch (IOException i)
{
Utils.logcat(Const.LOGE, encTag, "Cannot send amr out the media socket");
Utils.dumpException(tag, i);
}

有什么我想念的吗?为了模拟第二部手机,我有另一个客户端,它只是简单地读取语音数据,将其丢弃,然后循环再次读取。我可以在模拟的第二部手机中确认当真实的手机停止发送语音时,模拟的 socket.read 挂起,直到真实的手机再次开始发送语音。

我真的希望不必为套接字编写 jni,因为我对此一无所知,希望我可以将应用程序编写为标准的 Java 应用程序。

CASE CLOSED:原来是服务器端错误,但简化回归基础的建议仍然是个好主意。

最佳答案

您通过在写入任何数据之前读取大量数据来自己增加大部分延迟。您应该只使用标准的 Java 复制循环:

byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}

您需要调整它以合并您的编解码器步骤。请注意,您不需要整个输入大小的缓冲区。您可以调整它的大小以适合自己,但 8192 是一个很好的起点。您可以将其增加到 32k,但不要减少它。如果您的编解码器需要固定大小块中的数据,请使用该大小的缓冲区和 DataInputStream.readFully()。但缓冲区越大,延迟越多。

编辑您的代码的具体问题:

byte[] amrbuffer = new byte[AMRBUFFERSIZE];
byte[] outputbuffer = new byte [outputBufferSize];

删除(见下文)。

short[] wavbuffer = new short[WAVBUFFERSIZE];
int outputCounter = 0;

移除outputCounter

        //setup the wave audio recorder. since it is released and restarted, it needs to be setup here and not onCreate
wavRecorder = null; //remove pointer to the old recorder for safety

毫无意义。删除。

        wavRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLESWAV, AudioFormat.CHANNEL_IN_MONO, FORMAT, WAVBUFFERSIZE);
wavRecorder.startRecording();
AmrEncoder.init(0);

好的。

        try
{
Vars.mediaSocket.setSendBufferSize(outputBufferSize);
}
catch (SocketException e)
{
e.printStackTrace();
}

毫无意义。消除。套接字发送缓冲区应尽可能大。除非您知道它的默认大小是 <outputBufferSize,否则这样做没有任何好处。无论如何,我们要完全摆脱 outputBuffer

        while(!micMute)
{
int totalRead = 0, dataRead;
while(totalRead < WAVBUFFERSIZE)
{//although unlikely to be necessary, buffer the mic input
dataRead = wavRecorder.read(wavbuffer, totalRead, WAVBUFFERSIZE - totalRead);
totalRead = totalRead + dataRead;
}
int encodeLength = AmrEncoder.encode(AmrEncoder.Mode.MR122.ordinal(), wavbuffer, amrbuffer);

好的。

            if(outputCounter == outputBufferSize)
{
Utils.logcat(Const.LOGD, encTag, "Sending output buffer");
try
{
Vars.mediaSocket.getOutputStream().write(outputbuffer);
Vars.mediaSocket.getOutputStream().flush();
}
catch (IOException i)
{
Utils.logcat(Const.LOGE, encTag, "Cannot send amr out the media socket");
Utils.dumpException(tag, i);
}
outputCounter = 0;
}
System.arraycopy(amrbuffer, 0, outputbuffer, outputCounter, encodeLength);
outputCounter = outputCounter + encodeLength;
Utils.logcat(Const.LOGD, encTag, "Output buffer fill: " + outputCounter);

删除以上所有内容并替换

        Vars.mediaSocket.getOutputStream().write(amrbuffer, 0, encodeLength);

这也意味着您可以像 promise 的那样摆脱“outputBuffer”。

注意不要刷新内部循环。事实上,刷新套接字输出流没有任何作用,但一般原则仍然成立。

关于java - 强制 Java Android Socket 立即发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37981934/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com