Skip to content

Commit

Permalink
refactor(core): improve ByteBuffer extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibaultBee committed Oct 15, 2023
1 parent 85f8f9a commit 996b146
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ import io.github.thibaultbee.streampack.data.Config
import io.github.thibaultbee.streampack.error.StreamPackError
import io.github.thibaultbee.streampack.internal.data.Frame
import io.github.thibaultbee.streampack.internal.events.EventHandler
import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray
import io.github.thibaultbee.streampack.internal.utils.extensions.isAudio
import io.github.thibaultbee.streampack.internal.utils.extensions.slices
import io.github.thibaultbee.streampack.internal.utils.extensions.startsWith
import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray
import io.github.thibaultbee.streampack.logger.Logger
import io.github.thibaultbee.streampack.utils.TAG
import java.nio.ByteBuffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ package io.github.thibaultbee.streampack.internal.muxers.flv.packet
import android.media.MediaFormat
import io.github.thibaultbee.streampack.data.VideoConfig
import io.github.thibaultbee.streampack.internal.utils.av.video.avc.AVCDecoderConfigurationRecord
import io.github.thibaultbee.streampack.internal.utils.av.video.getStartCodeSize
import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCDecoderConfigurationRecord
import io.github.thibaultbee.streampack.internal.utils.av.video.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.put
import io.github.thibaultbee.streampack.internal.utils.extensions.putInt24
import io.github.thibaultbee.streampack.internal.utils.extensions.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.startCodeSize
import java.io.IOException
import java.nio.ByteBuffer

Expand Down Expand Up @@ -139,7 +139,7 @@ class VideoTag(
}
}
} else {
return buffers[0].remaining() - buffers[0].getStartCodeSize() + 4 // Replace start code with annex B
return buffers[0].remaining() - buffers[0].startCodeSize + 4 // Replace start code with annex B
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ import io.github.thibaultbee.streampack.internal.utils.av.descriptors.AudioSpeci
import io.github.thibaultbee.streampack.internal.utils.av.descriptors.ESDescriptor
import io.github.thibaultbee.streampack.internal.utils.av.descriptors.SLConfigDescriptor
import io.github.thibaultbee.streampack.internal.utils.av.video.avc.AVCDecoderConfigurationRecord
import io.github.thibaultbee.streampack.internal.utils.av.video.getStartCodeSize
import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCDecoderConfigurationRecord
import io.github.thibaultbee.streampack.internal.utils.av.video.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.clone
import io.github.thibaultbee.streampack.internal.utils.extensions.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.startCodeSize
import java.nio.ByteBuffer

/**
Expand Down Expand Up @@ -108,7 +108,7 @@ class TrackChunks(
MediaFormat.MIMETYPE_VIDEO_HEVC,
MediaFormat.MIMETYPE_VIDEO_AVC -> {
// Replace start code with size (from Annex B to AVCC)
4 + buffer.remaining() - buffer.getStartCodeSize()
4 + buffer.remaining() - buffer.startCodeSize
}

else -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,6 @@
*/
package io.github.thibaultbee.streampack.internal.utils.av.video

import java.nio.ByteBuffer

fun ByteBuffer.getStartCodeSize(): Int {
return if (this.get(0) == 0x00.toByte() && this.get(1) == 0x00.toByte()
&& this.get(2) == 0x00.toByte() && this.get(3) == 0x01.toByte()
) {
4
} else if (this.get(0) == 0x00.toByte() && this.get(1) == 0x00.toByte()
&& this.get(2) == 0x01.toByte()
) {
3
} else {
0
}
}

fun ByteBuffer.removeStartCode(): ByteBuffer {
val startCodeSize = this.getStartCodeSize()
this.position(startCodeSize)
return this.slice()
}

enum class ChromaFormat(val value: Byte) {
YUV400(0),
YUV420(1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
package io.github.thibaultbee.streampack.internal.utils.av.video.avc

import io.github.thibaultbee.streampack.internal.utils.av.video.ChromaFormat
import io.github.thibaultbee.streampack.internal.utils.av.video.getStartCodeSize
import io.github.thibaultbee.streampack.internal.utils.av.video.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.put
import io.github.thibaultbee.streampack.internal.utils.extensions.putShort
import io.github.thibaultbee.streampack.internal.utils.extensions.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.shl
import io.github.thibaultbee.streampack.internal.utils.extensions.startCodeSize
import java.nio.ByteBuffer

data class AVCDecoderConfigurationRecord(
Expand Down Expand Up @@ -105,12 +105,12 @@ data class AVCDecoderConfigurationRecord(
var size =
AVC_DECODER_CONFIGURATION_RECORD_SIZE
sps.forEach {
size += it.remaining() - it.getStartCodeSize()
size += it.remaining() - it.startCodeSize
}
pps.forEach {
size += it.remaining() - it.getStartCodeSize()
size += it.remaining() - it.startCodeSize
}
val spsStartCodeSize = sps[0].getStartCodeSize()
val spsStartCodeSize = sps[0].startCodeSize
val profileIdc = sps[0].get(spsStartCodeSize + 1).toInt()
if ((profileIdc == 100) || (profileIdc == 110) || (profileIdc == 122) || (profileIdc == 144)) {
size += 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
package io.github.thibaultbee.streampack.internal.utils.av.video.hevc

import io.github.thibaultbee.streampack.internal.utils.av.video.ChromaFormat
import io.github.thibaultbee.streampack.internal.utils.av.video.getStartCodeSize
import io.github.thibaultbee.streampack.internal.utils.av.video.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.put
import io.github.thibaultbee.streampack.internal.utils.extensions.putLong48
import io.github.thibaultbee.streampack.internal.utils.extensions.putShort
import io.github.thibaultbee.streampack.internal.utils.extensions.removeStartCode
import io.github.thibaultbee.streampack.internal.utils.extensions.shl
import io.github.thibaultbee.streampack.internal.utils.extensions.shr
import io.github.thibaultbee.streampack.internal.utils.extensions.startCodeSize
import java.nio.ByteBuffer

data class HEVCDecoderConfigurationRecord(
Expand Down Expand Up @@ -125,7 +125,7 @@ data class HEVCDecoderConfigurationRecord(
parameterSets: List<ByteBuffer>
): HEVCDecoderConfigurationRecord {
val nalUnitParameterSets = parameterSets.map {
val nalType = (it[it.getStartCodeSize()] shr 1 and 0x3F).toByte()
val nalType = (it[it.startCodeSize] shr 1 and 0x3F).toByte()
val type = NalUnit.Type.fromValue(nalType)
NalUnit(type, it)
}
Expand Down Expand Up @@ -168,13 +168,13 @@ data class HEVCDecoderConfigurationRecord(
var size =
HEVC_DECODER_CONFIGURATION_RECORD_SIZE
sps.forEach {
size += it.remaining() - it.getStartCodeSize() + HEVC_PARAMETER_SET_HEADER_SIZE
size += it.remaining() - it.startCodeSize + HEVC_PARAMETER_SET_HEADER_SIZE
}
pps.forEach {
size += it.remaining() - it.getStartCodeSize() + HEVC_PARAMETER_SET_HEADER_SIZE
size += it.remaining() - it.startCodeSize + HEVC_PARAMETER_SET_HEADER_SIZE
}
vps.forEach {
size += it.remaining() - it.getStartCodeSize() + HEVC_PARAMETER_SET_HEADER_SIZE
size += it.remaining() - it.startCodeSize + HEVC_PARAMETER_SET_HEADER_SIZE
}

return size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package io.github.thibaultbee.streampack.internal.utils.extensions

import io.github.thibaultbee.streampack.internal.utils.av.video.getStartCodeSize
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.charset.StandardCharsets
Expand Down Expand Up @@ -95,6 +94,23 @@ fun ByteBuffer.put(buffer: ByteBuffer, offset: Int, length: Int) {
buffer.limit(limit)
}

fun ByteBuffer.getString(size: Int = this.remaining()): String {
val bytes = ByteArray(size)
this.get(bytes)
return String(bytes, StandardCharsets.UTF_8)
}

fun ByteBuffer.getLong(isLittleEndian: Boolean): Long {
if (isLittleEndian) {
order(ByteOrder.LITTLE_ENDIAN)
}
val value = long
if (isLittleEndian) {
order(ByteOrder.BIG_ENDIAN)
}
return value
}

fun ByteBuffer.indicesOf(prefix: ByteArray): List<Int> {
if (prefix.isEmpty()) {
return emptyList()
Expand Down Expand Up @@ -175,12 +191,46 @@ fun ByteBuffer.toByteArray(): ByteArray {
}
}

fun ByteBuffer.clone(): ByteBuffer {
val clone = ByteBuffer.allocate(this.remaining())
return clone.put(this).apply { rewind() }
}

/**
* For AVC and HEVC
*/


/**
* Get start code size of [ByteBuffer].
*/
val ByteBuffer.startCodeSize: Int
get() {
return if (this.get(0) == 0x00.toByte() && this.get(1) == 0x00.toByte()
&& this.get(2) == 0x00.toByte() && this.get(3) == 0x01.toByte()
) {
4
} else if (this.get(0) == 0x00.toByte() && this.get(1) == 0x00.toByte()
&& this.get(2) == 0x01.toByte()
) {
3
} else {
0
}
}

fun ByteBuffer.removeStartCode(): ByteBuffer {
val startCodeSize = this.startCodeSize
this.position(startCodeSize)
return this.slice()
}

fun ByteBuffer.extractRbsp(headerLength: Int): ByteBuffer {
val rbsp = ByteBuffer.allocateDirect(this.remaining())

val indices = this.indicesOf(byteArrayOf(0x00, 0x00, 0x03))

rbsp.put(this, this.getStartCodeSize(), headerLength)
rbsp.put(this, this.startCodeSize, headerLength)

var previous = this.position()
indices.forEach {
Expand All @@ -193,27 +243,3 @@ fun ByteBuffer.extractRbsp(headerLength: Int): ByteBuffer {
rbsp.rewind()
return rbsp
}

fun ByteBuffer.clone(): ByteBuffer {
val clone = ByteBuffer.allocate(this.remaining())
return clone.put(this).apply { rewind() }
}

fun ByteBuffer.getString(size: Int = this.remaining()): String {
val bytes = ByteArray(size)
this.get(bytes)
return String(bytes, StandardCharsets.UTF_8)
}


fun ByteBuffer.getLong(isLittleEndian: Boolean): Long {
if (isLittleEndian) {
order(ByteOrder.LITTLE_ENDIAN)
}
val value = long
if (isLittleEndian) {
order(ByteOrder.BIG_ENDIAN)
}
return value
}

0 comments on commit 996b146

Please sign in to comment.