оно работает с rtp через udp и некоторое время использует TCP для отправки SSP и PPS.
Я использую MideaCodec для кодирования и декодирования.
Это приложение может действовать как отправитель видео или видеоприемник.
Сначала я тестирую это приложение на одном устройстве oneplus и vivo.
oneplus в качестве отправителя ----> и vivo в качестве получателя
все работает нормально. нет задержек, нет проблем.
но я меняю oneplus в качестве получателя и vivo в качестве отправителя. На этот раз видео на стороне получателя пикселизируется и тормозит.
Я проверяю свое приложение на другом устройстве.
- oneplus на vivo --> хорошо
- vivo на oneplus --> пикселизация и задержка
- vivo на redmi --> пикселизация и задержка
- redmi на vivo --> нормально
- redmi на oneplus --> пикселизация и задержка
ниже я прикрепляю кое-что важное части моего кода.
Этот код на стороне отправителя
Код: Выделить всё
private final int WIGHT = 320;
private final int HEIGHT = 240;
private void ensureEncoder() {
synchronized(encoderLock){
if (encoderInitialized) return;
MediaFormat format = MediaFormat.createVideoFormat("video/avc" , WIGHT , HEIGHT);
format.setInteger(MediaFormat.KEY_BIT_RATE , 500000);
format.setInteger(MediaFormat.KEY_FRAME_RATE , 24);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL , 1);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT , MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel31);
try {
encoder = MediaCodec.createEncoderByType("video/avc");
encoder.configure(format , null , null ,MediaCodec.CONFIGURE_FLAG_ENCODE);
encoderInputSurface = encoder.createInputSurface();
encoder.start();
encoderInitialized = true;
logger.log("Encoder initialized successfully");
startEncoderOutputReader();
} catch (IOException e) {
logger.error(e.toString());
}
}
}
private void startEncoderOutputReader(){
isEncoderReaderRunning = true;
executeTagged("Start Encoder Output Reader",()->{
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
boolean configSent = false;
while (isEncoderReaderRunning){
int outputIndex = encoder.dequeueOutputBuffer(bufferInfo , 10000);
if (outputIndex >= 0){
ByteBuffer encodedData = encoder.getOutputBuffer(outputIndex);
if (encodedData != null && bufferInfo.size > 0){
encodedData.position(bufferInfo.offset);
encodedData.limit(bufferInfo.offset + bufferInfo.size);
byte[] data = new byte[bufferInfo.size];
encodedData.get(data);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 && !configSent){
logger.error("..............extract SPS PPS...............................");
extractSpsPps(data);
sendParameterSet(spsBytes, ppsBytes);
configSent = true;
}else {
long startTime = System.nanoTime();
// Your network sending code here
sendRtpFrame(data);
long networkTime = System.nanoTime() - startTime;
logger.log("🌐 Network send time: " + (networkTime / 1000000) + "ms");
}
}
encoder.releaseOutputBuffer(outputIndex , false);
}
}
});
}
Код: Выделить всё
private void startReceiving() {
executorService.execute(() -> {
log.log("start Receiving rtp packets....");
try {
udpSocket = new DatagramSocket(connectionData.udpVideo);
byte[] buffer = new byte[1500];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (isReceiving) {
udpSocket.receive(packet);
if (connectionData != null && connectionData.ip == null){
connectionData.ip = packet.getAddress().getHostAddress();
log.log("Sender IP saved");
}
byte[] rtpPacket = Arrays.copyOf(packet.getData(), packet.getLength());
processRtpPacket(rtpPacket);
}
} catch (IOException e) {
log.error("Error receiving RTP: " + e);
}
});
}
private void processRtpPacket(byte[] rtpPacket) {
// log.log("Sequence Number is : " + extractSequenceNumber(rtpPacket));
int seq = ((rtpPacket[2] & 0xFF) = 0) {
ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputIndex);
inputBuffer.clear();
inputBuffer.put(nalUnit);
long pts = System.nanoTime() / 1000;
mediaCodec.queueInputBuffer(inputIndex, 0, nalUnit.length, pts, 0);
}else{
log.error("inputIndex not >= 0");
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
if (outputIndex >= 0) {
mediaCodec.releaseOutputBuffer(outputIndex, true);
}
} catch (Exception e) {
log.error("Decoder error: " + e);
}
long totalTime = System.nanoTime() - startTime;
Log.d("TIMING", "feedToDecoder took: " + (totalTime / 1000000) + "ms");
}
Думаю, это связано с настройками кодировщика или возможностями оборудования.
Я проанализировал множество журналов, но не смог найти проблему.
Решение, пожалуйста!
Подробнее здесь: https://stackoverflow.com/questions/797 ... xelation-a
Мобильная версия