From 08141bb1b1f0333def2e43c8e9a366267c79c404 Mon Sep 17 00:00:00 2001 From: pedroSG94 Date: Thu, 23 Jul 2026 20:23:51 +0200 Subject: [PATCH 1/2] refactor srt h26x packet and remove duplicated code --- .../main/java/com/pedro/common/Extensions.kt | 12 ++ .../java/com/pedro/common/ExtensionTest.kt | 30 +++ .../pedro/rtmp/flv/video/packet/H264Packet.kt | 20 +- .../pedro/rtmp/flv/video/packet/H265Packet.kt | 20 +- .../com/pedro/rtsp/rtp/packets/H264Packet.kt | 2 +- .../com/pedro/rtsp/rtp/packets/H265Packet.kt | 2 +- .../rtsp/rtsp/commands/CommandsManager.kt | 2 +- .../java/com/pedro/rtsp/utils/Extensions.kt | 22 --- .../com/pedro/rtsp/utils/ExtensionsTest.kt | 29 --- .../pedro/srt/mpeg2ts/packets/H26XPacket.kt | 173 ++++++------------ .../main/java/com/pedro/srt/srt/SrtSender.kt | 2 +- .../java/com/pedro/srt/utils/Extensions.kt | 7 - udp/src/main/java/com/pedro/udp/UdpSender.kt | 2 +- .../com/pedro/whip/webrtc/CommandsManager.kt | 2 +- 14 files changed, 113 insertions(+), 212 deletions(-) diff --git a/common/src/main/java/com/pedro/common/Extensions.kt b/common/src/main/java/com/pedro/common/Extensions.kt index 4d56b0566..1113b1d86 100644 --- a/common/src/main/java/com/pedro/common/Extensions.kt +++ b/common/src/main/java/com/pedro/common/Extensions.kt @@ -341,4 +341,16 @@ fun ByteBuffer.put(buffer: ByteBuffer, offset: Int, length: Int) { */ fun InetAddress.addressToString(): String { return (hostAddress ?: hostName).substringBefore("%") +} + +fun ByteBuffer.getData(): ByteArray = removeHeader().toByteArray() + +fun ByteBuffer.removeHeader(): ByteBuffer { + val startCodeSize = this.getStartCodeSize() + this.position(startCodeSize) + return this.slice() +} + +fun ByteArray.writeUInt32(offset: Int, value: Int) { + value.toUInt32().copyInto(this, offset) } \ No newline at end of file diff --git a/common/src/test/java/com/pedro/common/ExtensionTest.kt b/common/src/test/java/com/pedro/common/ExtensionTest.kt index 75a04f860..4e0d1a9be 100644 --- a/common/src/test/java/com/pedro/common/ExtensionTest.kt +++ b/common/src/test/java/com/pedro/common/ExtensionTest.kt @@ -17,6 +17,7 @@ package com.pedro.common import com.pedro.common.frame.MediaFrame +import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Test import java.nio.ByteBuffer @@ -55,4 +56,33 @@ class ExtensionTest { val md5Hash = fakeBuffer.getMd5Hash() assertEquals(expectedResult, md5Hash) } + + @Test + fun `GIVEN ByteBuffer WHEN start code has 3 bytes THEN return 3`() { + val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x0, 0x0, 0x1, 0x0)) + val index = fakeBuffer.getStartCodeSize() + assertEquals(3, index) + } + + @Test + fun `GIVEN ByteBuffer WHEN start code has 4 bytes THEN return 4`() { + val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x0, 0x0, 0x0, 0x1, 0x0)) + val index = fakeBuffer.getStartCodeSize() + assertEquals(4, index) + } + + @Test + fun `GIVEN ByteBuffer WHEN start code not found THEN return 0`() { + val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x0, 0x0, 0x0, 0x0, 0x0)) + val index = fakeBuffer.getStartCodeSize() + assertEquals(0, index) + } + + @Test + fun `GIVEN a ByteBuffer WHEN get data THEN get bytearray without start code`() { + val fakeByteBuffer = ByteBuffer.wrap(byteArrayOf(0x00, 0x00, 0x00, 0x01, 0x01)) + val expectedResult = byteArrayOf(0x01) + val result = fakeByteBuffer.getData() + assertArrayEquals(expectedResult, result) + } } \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H264Packet.kt b/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H264Packet.kt index 1a874eb1b..bfa6d7b87 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H264Packet.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H264Packet.kt @@ -21,8 +21,10 @@ import com.pedro.common.VideoCodec import com.pedro.common.frame.MediaFrame import com.pedro.common.getStartCodeSize import com.pedro.common.nal.NalReader +import com.pedro.common.removeHeader import com.pedro.common.removeInfo import com.pedro.common.toByteArray +import com.pedro.common.writeUInt32 import com.pedro.rtmp.flv.BasePacket import com.pedro.rtmp.flv.FlvPacket import com.pedro.rtmp.flv.FlvType @@ -54,7 +56,7 @@ class H264Packet: BasePacket() { } fun sendVideoInfo(sps: ByteBuffer, pps: ByteBuffer) { - videoInfo = listOf(removeHeader(sps), removeHeader(pps)) + videoInfo = listOf(sps.removeHeader(), pps.removeHeader()) } override suspend fun createFlvPacket( @@ -111,7 +113,7 @@ class H264Packet: BasePacket() { var offset = header.size nals.forEach { val nalSize = it.capacity() - writeNaluSize(buffer, offset, nalSize) + buffer.writeUInt32(offset, nalSize) it.get(buffer, offset + naluSize, nalSize) offset += naluSize + nalSize } @@ -119,20 +121,6 @@ class H264Packet: BasePacket() { callback(FlvPacket(buffer, ts, buffer.size, FlvType.VIDEO)) } - //naluSize = UInt32 - private fun writeNaluSize(buffer: ByteArray, offset: Int, size: Int) { - buffer[offset] = (size ushr 24).toByte() - buffer[offset + 1] = (size ushr 16).toByte() - buffer[offset + 2] = (size ushr 8).toByte() - buffer[offset + 3] = size.toByte() - } - - private fun removeHeader(byteBuffer: ByteBuffer, size: Int = -1): ByteBuffer { - val position = if (size == -1) byteBuffer.getStartCodeSize() else size - byteBuffer.position(position) - return byteBuffer.slice() - } - override fun reset(resetInfo: Boolean) { if (resetInfo) videoInfo = null configSend = false diff --git a/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H265Packet.kt b/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H265Packet.kt index 278b461ef..27bc0d11e 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H265Packet.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/flv/video/packet/H265Packet.kt @@ -21,8 +21,10 @@ import com.pedro.common.VideoCodec import com.pedro.common.frame.MediaFrame import com.pedro.common.getStartCodeSize import com.pedro.common.nal.NalReader +import com.pedro.common.removeHeader import com.pedro.common.removeInfo import com.pedro.common.toByteArray +import com.pedro.common.writeUInt32 import com.pedro.rtmp.flv.BasePacket import com.pedro.rtmp.flv.FlvPacket import com.pedro.rtmp.flv.FlvType @@ -49,7 +51,7 @@ class H265Packet: BasePacket() { private var videoInfo: List? = null fun sendVideoInfo(sps: ByteBuffer, pps: ByteBuffer, vps: ByteBuffer) { - this.videoInfo = listOf(removeHeader(sps), removeHeader(pps), removeHeader(vps)) + this.videoInfo = listOf(sps.removeHeader(), pps.removeHeader(), vps.removeHeader()) } override suspend fun createFlvPacket( @@ -111,7 +113,7 @@ class H265Packet: BasePacket() { var offset = header.size nals.forEach { val nalSize = it.capacity() - writeNaluSize(buffer, offset, nalSize) + buffer.writeUInt32(offset, nalSize) it.get(buffer, offset + naluSize, nalSize) offset += naluSize + nalSize } @@ -119,20 +121,6 @@ class H265Packet: BasePacket() { callback(FlvPacket(buffer, ts, buffer.size, FlvType.VIDEO)) } - //naluSize = UInt32 - private fun writeNaluSize(buffer: ByteArray, offset: Int, size: Int) { - buffer[offset] = (size ushr 24).toByte() - buffer[offset + 1] = (size ushr 16).toByte() - buffer[offset + 2] = (size ushr 8).toByte() - buffer[offset + 3] = size.toByte() - } - - private fun removeHeader(byteBuffer: ByteBuffer, size: Int = -1): ByteBuffer { - val position = if (size == -1) byteBuffer.getStartCodeSize() else size - byteBuffer.position(position) - return byteBuffer.slice() - } - override fun reset(resetInfo: Boolean) { if (resetInfo) videoInfo = null configSend = false diff --git a/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H264Packet.kt b/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H264Packet.kt index e68515df8..92c1bed62 100644 --- a/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H264Packet.kt +++ b/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H264Packet.kt @@ -18,11 +18,11 @@ package com.pedro.rtsp.rtp.packets import com.pedro.common.VideoCodec import com.pedro.common.frame.MediaFrame +import com.pedro.common.getData import com.pedro.common.nal.NalReader import com.pedro.common.removeInfo import com.pedro.rtsp.rtsp.RtpFrame import com.pedro.rtsp.utils.RtpConstants -import com.pedro.rtsp.utils.getData import java.nio.ByteBuffer import kotlin.experimental.and import kotlin.experimental.or diff --git a/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H265Packet.kt b/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H265Packet.kt index 4ca9d6ada..0ff2c7cbf 100644 --- a/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H265Packet.kt +++ b/rtsp/src/main/java/com/pedro/rtsp/rtp/packets/H265Packet.kt @@ -18,11 +18,11 @@ package com.pedro.rtsp.rtp.packets import com.pedro.common.VideoCodec import com.pedro.common.frame.MediaFrame +import com.pedro.common.getData import com.pedro.common.nal.NalReader import com.pedro.common.removeInfo import com.pedro.rtsp.rtsp.RtpFrame import com.pedro.rtsp.utils.RtpConstants -import com.pedro.rtsp.utils.getData import java.nio.ByteBuffer import kotlin.experimental.or diff --git a/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt b/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt index e7d8f4dfe..32774ba52 100644 --- a/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt +++ b/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt @@ -20,6 +20,7 @@ import android.util.Log import com.pedro.common.AudioCodec import com.pedro.common.TimeUtils import com.pedro.common.VideoCodec +import com.pedro.common.getData import com.pedro.common.getMd5Hash import com.pedro.common.socket.base.TcpStreamSocket import com.pedro.rtsp.rtsp.Protocol @@ -31,7 +32,6 @@ import com.pedro.rtsp.rtsp.commands.SdpBody.createH265Body import com.pedro.rtsp.rtsp.commands.SdpBody.createOpusBody import com.pedro.rtsp.utils.RtpTracks import com.pedro.rtsp.utils.encodeToString -import com.pedro.rtsp.utils.getData import java.io.IOException import java.net.DatagramSocket import java.nio.ByteBuffer diff --git a/rtsp/src/main/java/com/pedro/rtsp/utils/Extensions.kt b/rtsp/src/main/java/com/pedro/rtsp/utils/Extensions.kt index cb09755a4..7c16a4d4b 100644 --- a/rtsp/src/main/java/com/pedro/rtsp/utils/Extensions.kt +++ b/rtsp/src/main/java/com/pedro/rtsp/utils/Extensions.kt @@ -25,32 +25,10 @@ fun ByteArray.encodeToString(): String { return Base64.encode(this) } -fun ByteBuffer.getData(): ByteArray { - val startCodeSize = this.getVideoStartCodeSize() - val bytes = ByteArray(this.capacity() - startCodeSize) - this.position(startCodeSize) - this.get(bytes, 0, bytes.size) - return bytes -} - fun ByteArray.setLong(n: Long, begin: Int, end: Int) { var value = n for (i in end - 1 downTo begin step 1) { this[i] = (value % 256).toByte() value = value shr 8 } -} - -fun ByteBuffer.getVideoStartCodeSize(): Int { - var startCodeSize = 0 - if (this.get(0).toInt() == 0x00 && this.get(1).toInt() == 0x00 - && this.get(2).toInt() == 0x00 && this.get(3).toInt() == 0x01) { - //match 00 00 00 01 - startCodeSize = 4 - } else if (this.get(0).toInt() == 0x00 && this.get(1).toInt() == 0x00 - && this.get(2).toInt() == 0x01) { - //match 00 00 01 - startCodeSize = 3 - } - return startCodeSize } \ No newline at end of file diff --git a/rtsp/src/test/java/com/pedro/rtsp/utils/ExtensionsTest.kt b/rtsp/src/test/java/com/pedro/rtsp/utils/ExtensionsTest.kt index 9698b50b0..79cdfeeab 100644 --- a/rtsp/src/test/java/com/pedro/rtsp/utils/ExtensionsTest.kt +++ b/rtsp/src/test/java/com/pedro/rtsp/utils/ExtensionsTest.kt @@ -34,14 +34,6 @@ class ExtensionsTest { assertEquals(expectedString, result) } - @Test - fun `GIVEN a ByteBuffer WHEN get data THEN get bytearray without startVideoCode`() { - val fakeByteBuffer = ByteBuffer.wrap(byteArrayOf(0x00, 0x00, 0x00, 0x01, 0x01)) - val expectedResult = byteArrayOf(0x01) - val result = fakeByteBuffer.getData() - assertArrayEquals(expectedResult, result) - } - @Test fun `GIVEN ByteArray WHEN set long value in a position with a limit THEN get array with long put`() { val fakeBuffer = byteArrayOf(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) @@ -50,25 +42,4 @@ class ExtensionsTest { fakeBuffer.setLong(value, 0, 4) assertArrayEquals(expectedResult, fakeBuffer) } - - @Test - fun `GIVEN ByteBuffer WHEN video start code has 3 bytes THEN return 3`() { - val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x0, 0x0, 0x1, 0x0)) - val index = fakeBuffer.getVideoStartCodeSize() - assertEquals(3, index) - } - - @Test - fun `GIVEN ByteBuffer WHEN video start code has 4 bytes THEN return 4`() { - val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x0, 0x0, 0x0, 0x1, 0x0)) - val index = fakeBuffer.getVideoStartCodeSize() - assertEquals(4, index) - } - - @Test - fun `GIVEN ByteBuffer WHEN video start code not found THEN return 0`() { - val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x0, 0x0, 0x0, 0x0, 0x0)) - val index = fakeBuffer.getVideoStartCodeSize() - assertEquals(0, index) - } } \ No newline at end of file diff --git a/srt/src/main/java/com/pedro/srt/mpeg2ts/packets/H26XPacket.kt b/srt/src/main/java/com/pedro/srt/mpeg2ts/packets/H26XPacket.kt index aaf17c6b5..5cf2f4e3d 100644 --- a/srt/src/main/java/com/pedro/srt/mpeg2ts/packets/H26XPacket.kt +++ b/srt/src/main/java/com/pedro/srt/mpeg2ts/packets/H26XPacket.kt @@ -17,11 +17,11 @@ package com.pedro.srt.mpeg2ts.packets import android.util.Log +import com.pedro.common.VideoCodec import com.pedro.common.frame.MediaFrame -import com.pedro.common.getStartCodeSize +import com.pedro.common.getData +import com.pedro.common.nal.NalReader import com.pedro.common.removeInfo -import com.pedro.common.toByteArray -import com.pedro.srt.mpeg2ts.Codec import com.pedro.srt.mpeg2ts.MpegTsPacket import com.pedro.srt.mpeg2ts.MpegType import com.pedro.srt.mpeg2ts.Pes @@ -29,7 +29,6 @@ import com.pedro.srt.mpeg2ts.PesType import com.pedro.srt.mpeg2ts.psi.PsiManager import com.pedro.srt.srt.packets.data.PacketPosition import com.pedro.srt.utils.chunkPackets -import com.pedro.srt.utils.startWith import java.nio.ByteBuffer /** @@ -44,42 +43,36 @@ class H26XPacket( private val TAG = "H26XPacket" - private var sps: ByteArray? = null - private var pps: ByteArray? = null - private var vps: ByteArray? = null - private var codec = Codec.AVC - private var configSend = false + private var sps: ByteBuffer? = null + private var pps: ByteBuffer? = null + private var vps: ByteBuffer? = null + private var codec = VideoCodec.H264 override suspend fun createAndSendPacket( mediaFrame: MediaFrame, callback: suspend (List) -> Unit ) { val fixedBuffer = mediaFrame.data.removeInfo(mediaFrame.info) - val length = fixedBuffer.remaining() - if (length < 0) return val isKeyFrame = mediaFrame.info.isKeyFrame + val nals = NalReader.extractNals(fixedBuffer, codec, false) + if (nals.isEmpty()) return - if (codec == Codec.HEVC) { - val sps = this.sps - val pps = this.pps - val vps = this.vps - if (sps == null || pps == null || vps == null) { - Log.e(TAG, "waiting for a valid sps, pps and vps") - return - } - } else { - val sps = this.sps - val pps = this.pps - if (sps == null || pps == null) { - Log.e(TAG, "waiting for a valid sps and pps") - return - } + val sps = this.sps + val pps = this.pps + val vps = this.vps + if (sps == null || pps == null || (codec == VideoCodec.H265 && vps == null)) { + Log.e(TAG, "waiting for a valid video info") + return + } + + if (isKeyFrame) { + if (!nals.contains(pps)) nals.add(0, pps.duplicate()) + if (!nals.contains(sps)) nals.add(0, sps.duplicate()) + if (vps != null) if (!nals.contains(vps)) nals.add(0, vps.duplicate()) } - val validBuffer = fixHeader(fixedBuffer, isKeyFrame) - val payload = ByteArray(validBuffer.remaining()) - validBuffer.get(payload, 0, validBuffer.remaining()) - val pes = Pes(psiManager.getVideoPid().toInt(), isKeyFrame, PesType.VIDEO, mediaFrame.info.timestamp, ByteBuffer.wrap(payload)) + val payload = getPayload(nals, isKeyFrame) + val pes = Pes(psiManager.getVideoPid().toInt(), isKeyFrame, PesType.VIDEO, mediaFrame.info.timestamp, payload) val mpeg2tsPackets = mpegTsPacketizer.write(listOf(pes)).chunkPackets(chunkSize).map { buffer -> MpegTsPacket(buffer, MpegType.VIDEO, PacketPosition.SINGLE, isKeyFrame) } @@ -92,104 +85,52 @@ class H26XPacket( sps = null pps = null } - configSend = false } - fun setVideoCodec(codec: Codec) { + fun setVideoCodec(codec: VideoCodec) { + if (codec != VideoCodec.H265 && codec != VideoCodec.H264) { + throw IllegalArgumentException("This packet only support H264 and H265") + } this.codec = codec } fun sendVideoInfo(sps: ByteBuffer, pps: ByteBuffer?, vps: ByteBuffer?) { - this.sps = getVideoInfoData(sps) - this.pps = if (pps != null) getVideoInfoData(pps) else null - this.vps = if (vps != null) getVideoInfoData(vps) else null + this.sps = ByteBuffer.wrap(sps.getData()) + this.pps = pps?.let { ByteBuffer.wrap(pps.getData()) } + this.vps = vps?.let { ByteBuffer.wrap(vps.getData()) } } - /** - * Doing video header check sanity. - * - * Remove all header video info if necessary, make sure buffer start with prefix and add video info to first keyframe - */ - private fun fixHeader(byteBuffer: ByteBuffer, isKeyFrame: Boolean): ByteBuffer { - var noHeaderBuffer = removeHeader(byteBuffer, isKeyFrame) //remove video info header - val startCodeSize = noHeaderBuffer.getStartCodeSize() - if (startCodeSize == 0) { //make sure buffer start with prefix - val bufferWithPrefix = ByteBuffer.allocate(noHeaderBuffer.remaining() + 4) - bufferWithPrefix.putInt(0x00000001) - bufferWithPrefix.put(noHeaderBuffer) - noHeaderBuffer = bufferWithPrefix - } - return if (isKeyFrame) { //add video info to first keyframe - val vps = this.vps ?: byteArrayOf() - val sps = this.sps ?: byteArrayOf() - val pps = this.pps ?: byteArrayOf() - val codec = this.codec - val audSize = if (codec == Codec.AVC) 6 else 7 - val videoHeader = vps.plus(sps).plus(pps) - val noHeaderBytes = noHeaderBuffer.toByteArray() - val validBuffer = ByteBuffer.allocate(audSize + videoHeader.size + noHeaderBytes.size) - validBuffer.putInt(0x00000001) - if (codec == Codec.AVC) { - validBuffer.put(0x09.toByte()) - validBuffer.put(0xf0.toByte()) - } else { - validBuffer.put(0x46.toByte()) - validBuffer.put(0x01.toByte()) - validBuffer.put(0x50.toByte()) + private fun getPayload(nals: List, isKeyFrame: Boolean): ByteBuffer { + val nalsSize = nals.sumOf { it.remaining() } + val bufferSize = if (isKeyFrame) { + val audSize = when (codec) { + VideoCodec.H265 -> 7 + else -> 6 } - validBuffer.put(videoHeader) - validBuffer.put(noHeaderBytes) - validBuffer.rewind() - configSend = true - validBuffer - } else { - noHeaderBuffer.rewind() - noHeaderBuffer - } - } - - private fun getVideoInfoData(byteBuffer: ByteBuffer): ByteArray { - byteBuffer.rewind() - val startCodeSize = byteBuffer.getStartCodeSize() - return if (startCodeSize == 0) { //make sure video info start with prefix - val validBuffer = ByteBuffer.allocate(byteBuffer.remaining() + 4) - validBuffer.putInt(0x00000001) - validBuffer.put(byteBuffer) - validBuffer.toByteArray() - } else { - byteBuffer.toByteArray() - } - } + audSize + nalsSize + (nals.size * 4) + } else nalsSize + (nals.size * 4) - private fun removeHeader(byteBuffer: ByteBuffer, isKeyFrame: Boolean): ByteBuffer { - if (isKeyFrame) { - var validBuffer = byteBuffer - val vps = this.vps ?: byteArrayOf() - val sps = this.sps ?: byteArrayOf() - val pps = this.pps ?: byteArrayOf() - if (vps.isNotEmpty()) { - if (validBuffer.startWith(vps)) { - validBuffer.position(vps.size) - validBuffer = validBuffer.slice() - } + val payload = ByteBuffer.allocate(bufferSize) + //add AUD nal + if (isKeyFrame) { + payload.putInt(0x00000001) //annex-b header + when (codec) { + VideoCodec.H265 -> { + payload.put(0x46.toByte()) + payload.put(0x01.toByte()) + payload.put(0x50.toByte()) } - if (sps.isNotEmpty()) { - if (validBuffer.startWith(sps)) { - validBuffer.position(sps.size) - validBuffer = validBuffer.slice() - } + else -> { + payload.put(0x09.toByte()) + payload.put(0xf0.toByte()) } - if (pps.isNotEmpty()) { - if (validBuffer.startWith(pps)) { - validBuffer.position(pps.size) - validBuffer = validBuffer.slice() - } - } - validBuffer.rewind() - return validBuffer - } else { - byteBuffer.rewind() - return byteBuffer } + } + nals.forEach { + payload.putInt(0x00000001) //annex-b header + payload.put(it) + } + payload.flip() + return payload } } \ No newline at end of file diff --git a/srt/src/main/java/com/pedro/srt/srt/SrtSender.kt b/srt/src/main/java/com/pedro/srt/srt/SrtSender.kt index 28b16bc8d..ad8d5b3d7 100644 --- a/srt/src/main/java/com/pedro/srt/srt/SrtSender.kt +++ b/srt/src/main/java/com/pedro/srt/srt/SrtSender.kt @@ -75,7 +75,7 @@ class SrtSender( } override fun setVideoInfo(sps: ByteBuffer, pps: ByteBuffer?, vps: ByteBuffer?) { - videoPacket.setVideoCodec(commandsManager.videoCodec.toCodec()) + videoPacket.setVideoCodec(commandsManager.videoCodec) videoPacket.sendVideoInfo(sps, pps, vps) } diff --git a/srt/src/main/java/com/pedro/srt/utils/Extensions.kt b/srt/src/main/java/com/pedro/srt/utils/Extensions.kt index f3f9855e4..714bc8813 100644 --- a/srt/src/main/java/com/pedro/srt/utils/Extensions.kt +++ b/srt/src/main/java/com/pedro/srt/utils/Extensions.kt @@ -23,13 +23,6 @@ import com.pedro.srt.mpeg2ts.Codec import java.nio.ByteBuffer -fun ByteBuffer.startWith(byteArray: ByteArray): Boolean { - val startData = ByteArray(byteArray.size) - this.rewind() - this.get(startData) - return startData.contentEquals(byteArray) -} - fun Boolean.toInt(): Int { return if (this) 1 else 0 } diff --git a/udp/src/main/java/com/pedro/udp/UdpSender.kt b/udp/src/main/java/com/pedro/udp/UdpSender.kt index 18bf4b154..2ac40e990 100644 --- a/udp/src/main/java/com/pedro/udp/UdpSender.kt +++ b/udp/src/main/java/com/pedro/udp/UdpSender.kt @@ -71,7 +71,7 @@ class UdpSender( } override fun setVideoInfo(sps: ByteBuffer, pps: ByteBuffer?, vps: ByteBuffer?) { - videoPacket.setVideoCodec(commandManager.videoCodec.toCodec()) + videoPacket.setVideoCodec(commandManager.videoCodec) videoPacket.sendVideoInfo(sps, pps, vps) } diff --git a/whip/src/main/java/com/pedro/whip/webrtc/CommandsManager.kt b/whip/src/main/java/com/pedro/whip/webrtc/CommandsManager.kt index 82bc30ac8..e241cf8ec 100644 --- a/whip/src/main/java/com/pedro/whip/webrtc/CommandsManager.kt +++ b/whip/src/main/java/com/pedro/whip/webrtc/CommandsManager.kt @@ -13,7 +13,7 @@ import com.pedro.rtsp.rtsp.commands.SdpBody import com.pedro.rtsp.utils.RtpConstants import com.pedro.rtsp.utils.RtpTracks import com.pedro.rtsp.utils.encodeToString -import com.pedro.rtsp.utils.getData +import com.pedro.common.getData import com.pedro.whip.dtls.CryptoUtils import com.pedro.whip.dtls.DtlsCertificate import com.pedro.whip.utils.Constants From e00990aa1101731a607654314ae63e2b8a16c8b4 Mon Sep 17 00:00:00 2001 From: pedroSG94 Date: Thu, 23 Jul 2026 20:32:43 +0200 Subject: [PATCH 2/2] add tests --- .../java/com/pedro/common/ExtensionTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/common/src/test/java/com/pedro/common/ExtensionTest.kt b/common/src/test/java/com/pedro/common/ExtensionTest.kt index 4e0d1a9be..b3f227175 100644 --- a/common/src/test/java/com/pedro/common/ExtensionTest.kt +++ b/common/src/test/java/com/pedro/common/ExtensionTest.kt @@ -85,4 +85,26 @@ class ExtensionTest { val result = fakeByteBuffer.getData() assertArrayEquals(expectedResult, result) } + + @Test + fun `GIVEN a ByteBuffer with start code WHEN remove header THEN get a buffer without start code`() { + val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x00, 0x00, 0x00, 0x01, 0x65, 0x02)) + val result = fakeBuffer.removeHeader() + assertEquals(ByteBuffer.wrap(byteArrayOf(0x65, 0x02)), result) + } + + @Test + fun `GIVEN a ByteBuffer without start code WHEN remove header THEN get a buffer with the same data`() { + val fakeBuffer = ByteBuffer.wrap(byteArrayOf(0x65, 0x02, 0x03, 0x04)) + val result = fakeBuffer.removeHeader() + assertEquals(ByteBuffer.wrap(byteArrayOf(0x65, 0x02, 0x03, 0x04)), result) + } + + @Test + fun `GIVEN a ByteArray WHEN write uint32 in an offset THEN get array with value written in big endian`() { + val fakeBuffer = ByteArray(8) + fakeBuffer.writeUInt32(2, 0x01020304) + val expectedResult = byteArrayOf(0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00) + assertArrayEquals(expectedResult, fakeBuffer) + } } \ No newline at end of file