Skip to content

Commit 8d5c5e8

Browse files
committed
Refactored AV1 packetize
1 parent 5d344e9 commit 8d5c5e8

File tree

3 files changed

+73
-155
lines changed

3 files changed

+73
-155
lines changed

io/src/main/java/org/red5/io/obu/OBUParser.java

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,63 +2044,4 @@ public static boolean obuHasSize(byte obuHeader) {
20442044
return (obuHeader & OBU_SIZE_PRESENT_BIT) != 0;
20452045
}
20462046

2047-
public static int readUVarint(ByteBuffer buffer) {
2048-
int value = 0;
2049-
int shift = 0;
2050-
while (buffer.hasRemaining()) {
2051-
byte b = buffer.get();
2052-
value |= (b & 0x7F) << shift;
2053-
if ((b & LEB128.MSB_BITMASK) == 0) {
2054-
return value;
2055-
}
2056-
shift += 7;
2057-
if (shift >= 64) {
2058-
return -1; // overflow
2059-
}
2060-
}
2061-
return -1; // incomplete
2062-
}
2063-
2064-
public static int[] readUVarint(byte[] buffer) {
2065-
// index 0 is the value, index 1 is the number of bytes read
2066-
int[] result = new int[] { 0, -1 };
2067-
int shift = 0;
2068-
for (int i = 0; i < buffer.length; i++) {
2069-
byte b = buffer[i];
2070-
// value entry
2071-
result[0] |= (b & 0x7F) << shift;
2072-
if ((b & LEB128.MSB_BITMASK) == 0) {
2073-
result[1] = i + 1;
2074-
break;
2075-
}
2076-
shift += 7;
2077-
if (shift >= 64) {
2078-
result[1] = -1; // overflow
2079-
break;
2080-
}
2081-
}
2082-
return result; // if index 1 == -1 we're incomplete or overflowed
2083-
}
2084-
2085-
public static int[] readUVarint(byte[] buffer, int offset) {
2086-
// index 0 is the value, index 1 is the number of bytes read
2087-
int[] result = new int[] { 0, -1 };
2088-
int shift = 0;
2089-
for (int i = offset; i < buffer.length; i++) {
2090-
byte b = buffer[i];
2091-
// value entry
2092-
result[0] |= (b & 0x7F) << shift;
2093-
if ((b & LEB128.MSB_BITMASK) == 0) {
2094-
result[1] = i + 1;
2095-
break;
2096-
}
2097-
shift += 7;
2098-
if (shift >= 64) {
2099-
result[1] = -1; // overflow
2100-
break;
2101-
}
2102-
}
2103-
return result; // if index 1 == -1 we're incomplete or overflowed
2104-
}
2105-
21062047
}

io/src/main/java/org/red5/io/rtp/AV1Packetizer.java

Lines changed: 40 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -191,60 +191,6 @@ public int depacketize(byte[] payload) throws Exception {
191191
return OBUElements.size();
192192
}
193193

194-
/**
195-
* Packetizes a list of AV1 OBU elements.
196-
*
197-
* @param obuElements list of OBUInfo
198-
* @param mtu maximum transmission unit
199-
* @return list of packets
200-
*/
201-
public List<byte[]> packetize(List<OBUInfo> obuInfos, int mtu) {
202-
List<byte[]> payloads = new LinkedList<>();
203-
for (OBUInfo obuInfo : obuInfos) {
204-
// obuInfo.data does not include the OBU header
205-
byte[] payload = obuInfo.data.array();
206-
byte frameType = (byte) ((obuInfo.obuType.getValue() & OBU_FRAME_TYPE_MASK) >> OBU_FRAME_TYPE_BITSHIFT);
207-
if (frameType == OBU_FRAME_TYPE_SEQUENCE_HEADER) {
208-
sequenceHeader = payload;
209-
} else {
210-
int payloadDataIndex = 0;
211-
int payloadDataRemaining = payload.length;
212-
byte obuCount = 0;
213-
// no meta no need to add to metadata size
214-
int metadataSize = 0;
215-
if (sequenceHeader != null && sequenceHeader.length > 0) {
216-
// metadata size is small so 1 byte to hold its leb128 encoded length
217-
metadataSize += sequenceHeader.length + 1;
218-
obuCount++;
219-
}
220-
do {
221-
int outOffset = 1; // AV1_PAYLOADER_HEADER_SIZE
222-
byte[] out = new byte[Math.min(mtu, payloadDataRemaining + metadataSize)];
223-
out[0] = (byte) (obuCount << W_BITSHIFT);
224-
if (obuCount == 2) {
225-
out[0] ^= N_MASK;
226-
out[1] = (byte) LEB128.encode(sequenceHeader.length);
227-
System.arraycopy(sequenceHeader, 0, out, 2, sequenceHeader.length);
228-
outOffset += sequenceHeader.length + 1; // 1 byte for LEB128
229-
sequenceHeader = null;
230-
}
231-
int outBufferRemaining = out.length - outOffset;
232-
System.arraycopy(payload, payloadDataIndex, out, outOffset, outBufferRemaining);
233-
payloadDataRemaining -= outBufferRemaining;
234-
payloadDataIndex += outBufferRemaining;
235-
if (!payloads.isEmpty()) {
236-
out[0] ^= Z_MASK;
237-
}
238-
if (payloadDataRemaining != 0) {
239-
out[0] ^= Y_MASK;
240-
}
241-
payloads.add(out);
242-
} while (payloadDataRemaining > 0);
243-
}
244-
}
245-
return payloads;
246-
}
247-
248194
/**
249195
* Packetizes an AV1 payload.
250196
*
@@ -295,39 +241,49 @@ public List<byte[]> packetize(byte[] payload, int mtu) {
295241
return payloads;
296242
}
297243

298-
// Payload fragments a AV1 packet across one or more byte arrays
299-
// See AV1Packet for description of AV1 Payload Header
300-
public static LinkedList<byte[]> marshal(int mtu, byte[] payload) {
244+
/**
245+
* Packetizes a list of AV1 OBU, consisting of a sequence header and one or more OBU elements.
246+
*
247+
* @param obuElements list of OBUInfo
248+
* @param mtu maximum transmission unit
249+
* @return list of packets
250+
*/
251+
public List<byte[]> packetize(List<OBUInfo> obuInfos, int mtu) {
301252
LinkedList<byte[]> payloads = new LinkedList<>();
302253
int aggregationHeaderLength = 1;
303254
int maxFragmentSize = mtu - aggregationHeaderLength - 2;
304-
int payloadDataRemaining = payload.length;
305-
int payloadDataIndex = 0;
306-
// Make sure the fragment/payload size is correct
307-
if (Math.min(maxFragmentSize, payloadDataRemaining) > 0) {
308-
while (payloadDataRemaining > 0) {
309-
int currentFragmentSize = Math.min(maxFragmentSize, payloadDataRemaining);
310-
int leb128Size = 1;
311-
if (currentFragmentSize >= 127) {
312-
leb128Size = 2;
313-
}
314-
byte[] out = new byte[aggregationHeaderLength + leb128Size + currentFragmentSize];
315-
int leb128Value = LEB128.encode(currentFragmentSize);
316-
if (leb128Size == 1) {
317-
out[1] = (byte) leb128Value;
318-
} else {
319-
out[1] = (byte) (leb128Value >> 8);
320-
out[2] = (byte) leb128Value;
321-
}
322-
System.arraycopy(payload, payloadDataIndex, out, aggregationHeaderLength + leb128Size, currentFragmentSize);
323-
payloads.add(out);
324-
payloadDataRemaining -= currentFragmentSize;
325-
payloadDataIndex += currentFragmentSize;
326-
if (payloads.size() > 1) {
327-
out[0] ^= Z_MASK;
328-
}
329-
if (payloadDataRemaining != 0) {
330-
out[0] ^= Y_MASK;
255+
for (OBUInfo obuInfo : obuInfos) {
256+
// obuInfo.data does not include the OBU header
257+
byte frameType = (byte) ((obuInfo.obuType.getValue() & OBU_FRAME_TYPE_MASK) >> OBU_FRAME_TYPE_BITSHIFT);
258+
byte[] payload = obuInfo.data.array();
259+
int payloadDataRemaining = payload.length, payloadDataIndex = 0;
260+
logger.debug("Frame type: {}", frameType);
261+
// Make sure the fragment/payload size is correct
262+
if (Math.min(maxFragmentSize, payloadDataRemaining) > 0) {
263+
while (payloadDataRemaining > 0) {
264+
int currentFragmentSize = Math.min(maxFragmentSize, payloadDataRemaining);
265+
int leb128Value = LEB128.encode(currentFragmentSize);
266+
byte[] out;
267+
if (currentFragmentSize >= 127) { // leb takes at least 2 bytes
268+
int outLen = aggregationHeaderLength + 2 + currentFragmentSize;
269+
out = new byte[outLen];
270+
out[1] = (byte) (leb128Value >> 8);
271+
out[2] = (byte) leb128Value;
272+
System.arraycopy(payload, payloadDataIndex, out, aggregationHeaderLength + 2, currentFragmentSize);
273+
} else { // leb expected to be 1 byte
274+
out = new byte[aggregationHeaderLength + 1 + currentFragmentSize];
275+
out[1] = (byte) leb128Value;
276+
System.arraycopy(payload, payloadDataIndex, out, aggregationHeaderLength + 1, currentFragmentSize);
277+
}
278+
payloads.add(out);
279+
payloadDataRemaining -= currentFragmentSize;
280+
payloadDataIndex += currentFragmentSize;
281+
if (payloads.size() > 1) {
282+
out[0] ^= Z_MASK;
283+
}
284+
if (payloadDataRemaining != 0) {
285+
out[0] ^= Y_MASK;
286+
}
331287
}
332288
}
333289
}

0 commit comments

Comments
 (0)