diff --git a/README.md b/README.md index e0f7802de3..412413ddd4 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,6 @@ dependencies { - [x] RTMPS (under TLS) - [x] RTMPT and RTMPTS (tunneled and tunneled under TLS) - [x] AMF0 -- [ ] AMF3 ### RTSP: diff --git a/common/src/main/java/com/pedro/common/Extensions.kt b/common/src/main/java/com/pedro/common/Extensions.kt index 06cdf9259b..4d56b05662 100644 --- a/common/src/main/java/com/pedro/common/Extensions.kt +++ b/common/src/main/java/com/pedro/common/Extensions.kt @@ -207,6 +207,10 @@ fun ByteArray.toUInt32(): Int { return this[0].toInt() and 0xff shl 24 or (this[1].toInt() and 0xff shl 16) or (this[2].toInt() and 0xff shl 8) or (this[3].toInt() and 0xff) } +fun ByteArray.toUInt64(): Long { + return (this[0].toLong() and 0xff shl 56) or (this[1].toLong() and 0xff shl 48) or (this[2].toLong() and 0xff shl 40) or (this[3].toLong() and 0xff shl 32) or (this[4].toLong() and 0xff shl 24) or (this[5].toLong() and 0xff shl 16) or (this[6].toLong() and 0xff shl 8) or (this[7].toLong() and 0xff) +} + fun ByteArray.toUInt32LittleEndian(): Int { return Integer.reverseBytes(toUInt32()) } diff --git a/library/src/main/java/com/pedro/library/util/FlvMuxerRecordController.kt b/library/src/main/java/com/pedro/library/util/FlvMuxerRecordController.kt index 319fd95227..87f08076a5 100644 --- a/library/src/main/java/com/pedro/library/util/FlvMuxerRecordController.kt +++ b/library/src/main/java/com/pedro/library/util/FlvMuxerRecordController.kt @@ -14,8 +14,8 @@ import com.pedro.encoder.video.VideoEncoderHelper import com.pedro.library.base.recording.AsyncBaseRecordController import com.pedro.library.base.recording.RecordController import com.pedro.library.base.recording.RecordController.RecordTracks -import com.pedro.rtmp.amf.v0.AmfEcmaArray -import com.pedro.rtmp.amf.v0.AmfString +import com.pedro.rtmp.amf.AmfEcmaArray +import com.pedro.rtmp.amf.AmfString import com.pedro.rtmp.flv.BasePacket import com.pedro.rtmp.flv.FlvPacket import com.pedro.rtmp.flv.FlvType diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfBoolean.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfBoolean.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfBoolean.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfBoolean.kt index 64bd0fd6ba..fd34dd973d 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfBoolean.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfBoolean.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import java.io.IOException import java.io.InputStream diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfData.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfData.kt similarity index 98% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfData.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfData.kt index fddfb23812..7fbd101916 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfData.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfData.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import java.io.IOException import java.io.InputStream diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfDate.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfDate.kt similarity index 95% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfDate.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfDate.kt index 896c47190d..7ee9a272b7 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfDate.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfDate.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.TimeUtils import com.pedro.common.readUntil @@ -36,7 +36,7 @@ class AmfDate(var date: Double = TimeUtils.getCurrentTimeMillis().toDouble()): A val bytes = ByteArray(getSize() - 2) input.readUntil(bytes) val value = ByteBuffer.wrap(bytes).long - date = Double.Companion.fromBits(value) + date = Double.fromBits(value) val timeZone = byteArrayOf(0x00, 0x00) input.readUntil(timeZone) } diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfEcmaArray.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfEcmaArray.kt similarity index 98% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfEcmaArray.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfEcmaArray.kt index d413b52f76..772dcbc128 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfEcmaArray.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfEcmaArray.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.readUInt32 import com.pedro.common.writeUInt32 diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfLongString.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfLongString.kt similarity index 98% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfLongString.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfLongString.kt index 9880f1e6e4..51bdfe9a3c 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfLongString.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfLongString.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.readUInt32 import com.pedro.common.readUntil diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfNull.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfNull.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfNull.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfNull.kt index 8224d45772..a43a8901b0 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfNull.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfNull.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import java.io.IOException import java.io.InputStream diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfNumber.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfNumber.kt similarity index 94% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfNumber.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfNumber.kt index ecabb4981d..df0682700d 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfNumber.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfNumber.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.readUntil import java.io.IOException @@ -34,7 +34,7 @@ class AmfNumber(var value: Double = 0.0): AmfData() { val bytes = ByteArray(getSize()) input.readUntil(bytes) val value = ByteBuffer.wrap(bytes).long - this.value = Double.Companion.fromBits(value) + this.value = Double.fromBits(value) } @Throws(IOException::class) diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfObject.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfObject.kt similarity index 99% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfObject.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfObject.kt index 931cd54a7e..0670eb2497 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfObject.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfObject.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import java.io.BufferedInputStream import java.io.IOException diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfObjectEnd.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfObjectEnd.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfObjectEnd.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfObjectEnd.kt index be28f7b58e..d1eb0641eb 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfObjectEnd.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfObjectEnd.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.readUntil import java.io.IOException diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfStrictArray.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfStrictArray.kt similarity index 98% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfStrictArray.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfStrictArray.kt index 0263f9d124..965fa79733 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfStrictArray.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfStrictArray.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.readUInt32 import com.pedro.common.writeUInt32 diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfString.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfString.kt similarity index 98% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfString.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfString.kt index 8b2ec564d2..6fde5ac1ab 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfString.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfString.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import com.pedro.common.readUInt16 import com.pedro.common.readUntil diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfType.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfType.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfType.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfType.kt index 4572783b21..2e07856bf7 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfType.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfType.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf /** * Created by pedro on 20/04/21. diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfUndefined.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfUndefined.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfUndefined.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfUndefined.kt index 97796656e1..d77fde9773 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfUndefined.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfUndefined.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import java.io.IOException import java.io.InputStream diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfUnsupported.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfUnsupported.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfUnsupported.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfUnsupported.kt index a39af3292a..9326a599d3 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfUnsupported.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfUnsupported.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import java.io.IOException import java.io.InputStream diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/AmfVersion.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfVersion.kt deleted file mode 100644 index 8300757f14..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/AmfVersion.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf - -/** - * Created by pedro on 8/04/21. - */ -enum class AmfVersion { - VERSION_0, VERSION_3 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfXmlDocument.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfXmlDocument.kt similarity index 97% rename from rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfXmlDocument.kt rename to rtmp/src/main/java/com/pedro/rtmp/amf/AmfXmlDocument.kt index 90e755e819..98e9f4a337 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v0/AmfXmlDocument.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/amf/AmfXmlDocument.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pedro.rtmp.amf.v0 +package com.pedro.rtmp.amf import org.w3c.dom.Document import org.xml.sax.InputSource diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Array.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Array.kt deleted file mode 100644 index 5b1f2e6602..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Array.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3Array(val items: MutableList = mutableListOf()): Amf3Data() { - - override fun readBody(input: InputStream) { - TODO("Not yet implemented") - } - - override fun writeBody(output: OutputStream) { - TODO("Not yet implemented") - } - - override fun getType(): Amf3Type = Amf3Type.ARRAY - - override fun getSize(): Int { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Data.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Data.kt deleted file mode 100644 index bbaec9a610..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Data.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 20/04/21. - */ -abstract class Amf3Data { - - companion object { - - /** - * Read unknown AmfData and convert it to specific class - */ - @Throws(IOException::class) - fun getAmf3Data(input: InputStream): Amf3Data { - val amf3Data = when (val type = getMark3Type(input.read())) { - Amf3Type.DOUBLE -> Amf3Double() - Amf3Type.INTEGER -> Amf3Integer() - Amf3Type.STRING -> Amf3String() - Amf3Type.OBJECT -> Amf3Object() - Amf3Type.NULL -> Amf3Null() - Amf3Type.UNDEFINED -> Amf3Undefined() - Amf3Type.ARRAY -> Amf3Array() - Amf3Type.DICTIONARY -> Amf3Dictionary() - Amf3Type.TRUE -> Amf3True() - Amf3Type.FALSE -> Amf3False() - else -> throw IOException("Unimplemented AMF3 data type: ${type.name}") - } - amf3Data.readBody(input) - return amf3Data - } - - fun getMark3Type(type: Int): Amf3Type { - return Amf3Type.entries.find { it.mark.toInt() == type } ?: Amf3Type.STRING - } - } - - @Throws(IOException::class) - fun readHeader(input: InputStream): Amf3Type { - return getMark3Type(input.read()) - } - - @Throws(IOException::class) - fun writeHeader(output: OutputStream) { - output.write(getType().mark.toInt()) - } - - @Throws(IOException::class) - abstract fun readBody(input: InputStream) - - @Throws(IOException::class) - abstract fun writeBody(output: OutputStream) - - abstract fun getType(): Amf3Type - - //Body size without header type - abstract fun getSize(): Int -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Dictionary.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Dictionary.kt deleted file mode 100644 index 1c480ff3dd..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Dictionary.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3Dictionary(private val properties: HashMap = LinkedHashMap()): Amf3Object(properties) { - - override fun readBody(input: InputStream) { - TODO("Not yet implemented") - } - - override fun writeBody(output: OutputStream) { - TODO("Not yet implemented") - } - - override fun getType(): Amf3Type = Amf3Type.DICTIONARY - - override fun getSize(): Int { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Double.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Double.kt deleted file mode 100644 index ac335b2fc3..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Double.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import com.pedro.common.readUntil -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream -import java.nio.ByteBuffer - -/** - * Created by pedro on 29/04/21. - */ -class Amf3Double(var value: Double = 0.0): Amf3Data() { - - @Throws(IOException::class) - override fun readBody(input: InputStream) { - val bytes = ByteArray(getSize()) - input.readUntil(bytes) - val value = ByteBuffer.wrap(bytes).long - this.value = Double.Companion.fromBits(value) - } - - @Throws(IOException::class) - override fun writeBody(output: OutputStream) { - val byteBuffer = ByteBuffer.allocate(getSize()).putLong(value.toRawBits()) - output.write(byteBuffer.array()) - } - - override fun getType(): Amf3Type = Amf3Type.DOUBLE - - override fun getSize(): Int = 8 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3False.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3False.kt deleted file mode 100644 index 0c63883b5c..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3False.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3False: Amf3Data() { - - override fun readBody(input: InputStream) { - //no body to read - } - - override fun writeBody(output: OutputStream) { - //no body to write - } - - override fun getType(): Amf3Type = Amf3Type.FALSE - - override fun getSize(): Int = 0 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Integer.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Integer.kt deleted file mode 100644 index fe908fef16..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Integer.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3Integer(private val value: Int = 0): Amf3Data() { - - override fun readBody(input: InputStream) { - TODO("Not yet implemented") - } - - override fun writeBody(output: OutputStream) { - TODO("Not yet implemented") - } - - override fun getType(): Amf3Type = Amf3Type.INTEGER - - override fun getSize(): Int { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Null.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Null.kt deleted file mode 100644 index abd51842ca..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Null.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3Null: Amf3Data() { - - override fun readBody(input: InputStream) { - //no body to read - } - - override fun writeBody(output: OutputStream) { - //no body to write - } - - override fun getType(): Amf3Type = Amf3Type.NULL - - override fun getSize(): Int = 0 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Object.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Object.kt deleted file mode 100644 index d7109b76b0..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Object.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import com.pedro.rtmp.amf.v0.AmfNull -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -open class Amf3Object(private val properties: HashMap = LinkedHashMap()): Amf3Data() { - - protected var bodySize = 0 - - fun getProperty(name: String): Amf3Data? { - properties.forEach { - if (it.key.value == name) { - return it.value - } - } - return null - } - - open fun setProperty(name: String, data: String) = putProperty(name, Amf3String(data)) - - open fun setProperty(name: String, data: Boolean) = putProperty(name, if (data) Amf3True() else Amf3False()) - - open fun setProperty(name: String, data: Amf3Data) = putProperty(name, data) - - open fun setProperty(name: String) = putProperty(name, Amf3Null()) - - open fun setProperty(name: String, data: Double) = putProperty(name, Amf3Double(data)) - - open fun setProperty(name: String, data: Any) { - val newValue = when (data) { - is String -> Amf3String(data) - is Int -> Amf3Integer(data) - is Double -> Amf3Double(data) - is Float -> Amf3Double(data.toDouble()) - is Boolean -> if (data) Amf3True() else Amf3False() - is Amf3Data -> data - else -> throw IllegalArgumentException("Unsupported value type: ${data::class.java.name}") - } - putProperty(name, newValue) - } - - private fun putProperty(name: String, value: Amf3Data) { - val key = Amf3String(name) - val previous = properties.put(key, value) - bodySize += if (previous != null) { - value.getSize() - previous.getSize() - } else { - key.getSize() + value.getSize() + 1 - } - } - - - override fun readBody(input: InputStream) { - TODO("Not yet implemented") - } - - override fun writeBody(output: OutputStream) { - TODO("Not yet implemented") - } - - override fun getType(): Amf3Type = Amf3Type.OBJECT - - override fun getSize(): Int { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3String.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3String.kt deleted file mode 100644 index 9301d89bfd..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3String.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 8/04/21. - */ -class Amf3String(var value: String = ""): Amf3Data() { - - override fun readBody(input: InputStream) { - TODO("Not yet implemented") - } - - override fun writeBody(output: OutputStream) { - TODO("Not yet implemented") - } - - override fun getType(): Amf3Type = Amf3Type.STRING - - override fun getSize(): Int { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3True.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3True.kt deleted file mode 100644 index 1067bafd46..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3True.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3True: Amf3Data() { - - override fun readBody(input: InputStream) { - //no body to read - } - - override fun writeBody(output: OutputStream) { - //no body to write - } - - override fun getType(): Amf3Type = Amf3Type.TRUE - - override fun getSize(): Int = 0 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Type.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Type.kt deleted file mode 100644 index 7aee78e0c8..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Type.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -/** - * Created by pedro on 29/04/21. - */ -enum class Amf3Type(val mark: Byte) { - UNDEFINED(0x00), NULL(0x01), TRUE(0x02), FALSE(0x03), INTEGER(0x04), - DOUBLE(0x05), STRING(0x06), XML_DOC(0x07), DATE(0x08), ARRAY(0x09), - OBJECT(0x0A), XML(0x0B), BYTE_ARRAY(0x0C), VECTOR_INT(0x0D), VECTOR_UINT(0x0E), - VECTOR_DOUBLE(0x0F), VECTOR_OBJECT(0x10), DICTIONARY(0x11) -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Undefined.kt b/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Undefined.kt deleted file mode 100644 index cb27dbc935..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/amf/v3/Amf3Undefined.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.amf.v3 - -import java.io.InputStream -import java.io.OutputStream - -/** - * Created by pedro on 29/04/21. - */ -class Amf3Undefined: Amf3Data() { - - override fun readBody(input: InputStream) { - //no body to read - } - - override fun writeBody(output: OutputStream) { - //no body to write - } - - override fun getType(): Amf3Type = Amf3Type.UNDEFINED - - override fun getSize(): Int = 0 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerAmf3.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerAmf3.kt deleted file mode 100644 index 6c6fa5b934..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerAmf3.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp - -import android.util.Log -import com.pedro.common.VideoCodec -import com.pedro.rtmp.amf.v3.Amf3Array -import com.pedro.rtmp.amf.v3.Amf3Data -import com.pedro.rtmp.amf.v3.Amf3Dictionary -import com.pedro.rtmp.amf.v3.Amf3Null -import com.pedro.rtmp.amf.v3.Amf3Object -import com.pedro.rtmp.amf.v3.Amf3String -import com.pedro.rtmp.flv.audio.AudioFormat -import com.pedro.rtmp.flv.video.VideoFormat -import com.pedro.rtmp.rtmp.chunk.ChunkStreamId -import com.pedro.rtmp.rtmp.chunk.ChunkType -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.command.CommandAmf3 -import com.pedro.rtmp.rtmp.message.data.DataAmf3 -import com.pedro.rtmp.utils.socket.RtmpSocket - -class CommandsManagerAmf3: CommandsManager() { - override suspend fun sendConnectImp(auth: String, socket: RtmpSocket) { - val connect = CommandAmf3("connect", ++commandId, getCurrentTimestamp(), streamId, - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)) - val connectInfo = Amf3Object() - connectInfo.setProperty("app", appName + auth) - connectInfo.setProperty("flashVer", flashVersion) - connectInfo.setProperty("tcUrl", tcUrl + auth) - if (!videoDisabled) { - if (videoCodec == VideoCodec.H265) { - val list = mutableListOf() - list.add(Amf3String("hvc1")) - val array = Amf3Array(list) - connectInfo.setProperty("fourCcList", array) - } else if (videoCodec == VideoCodec.AV1) { - val list = mutableListOf() - list.add(Amf3String("av01")) - val array = Amf3Array(list) - connectInfo.setProperty("fourCcList", array) - } - } - connectInfo.setProperty("objectEncoding", 3.0) - connect.addData(connectInfo) - - connect.writeHeader(socket) - connect.writeBody(socket, config.writeChunkSize) - sessionHistory.setPacket(commandId, "connect") - Log.i(TAG, "send $connect") - } - - override suspend fun createStreamImp(socket: RtmpSocket) { - val releaseStream = CommandAmf3("releaseStream", ++commandId, getCurrentTimestamp(), streamId, - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) - releaseStream.addData(Amf3Null()) - releaseStream.addData(Amf3String(streamName)) - - releaseStream.writeHeader(socket) - releaseStream.writeBody(socket, config.writeChunkSize) - sessionHistory.setPacket(commandId, "releaseStream") - Log.i(TAG, "send $releaseStream") - - val fcPublish = CommandAmf3("FCPublish", ++commandId, getCurrentTimestamp(), streamId, - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) - fcPublish.addData(Amf3Null()) - fcPublish.addData(Amf3String(streamName)) - - fcPublish.writeHeader(socket) - fcPublish.writeBody(socket, config.writeChunkSize) - sessionHistory.setPacket(commandId, "FCPublish") - Log.i(TAG, "send $fcPublish") - - val createStream = CommandAmf3("createStream", ++commandId, getCurrentTimestamp(), streamId, - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)) - createStream.addData(Amf3Null()) - - createStream.writeHeader(socket) - createStream.writeBody(socket, config.writeChunkSize) - sessionHistory.setPacket(commandId, "createStream") - Log.i(TAG, "send $createStream") - } - - override suspend fun sendMetadataImp(socket: RtmpSocket) { - val name = "@setDataFrame" - val metadata = DataAmf3(name, getCurrentTimestamp(), streamId) - metadata.addData(Amf3String("onMetaData")) - val amfEcmaArray = Amf3Dictionary() - amfEcmaArray.setProperty("duration", 0.0) - if (!videoDisabled) { - amfEcmaArray.setProperty("width", width.toDouble()) - amfEcmaArray.setProperty("height", height.toDouble()) - //few servers don't support it even if it is in the standard rtmp enhanced - //val codecValue = if (videoCodec == VideoCodec.H265) VideoFormat.HEVC.value else VideoFormat.AVC.value - //amfEcmaArray.setProperty("videocodecid", codecValue.toDouble()) - amfEcmaArray.setProperty("videocodecid", VideoFormat.AVC.value.toDouble()) - amfEcmaArray.setProperty("framerate", fps.toDouble()) - amfEcmaArray.setProperty("videodatarate", 0.0) - } - if (!audioDisabled) { - amfEcmaArray.setProperty("audiocodecid", AudioFormat.AAC.value.toDouble()) - amfEcmaArray.setProperty("audiosamplerate", sampleRate.toDouble()) - amfEcmaArray.setProperty("audiosamplesize", 16.0) - amfEcmaArray.setProperty("audiodatarate", 0.0) - amfEcmaArray.setProperty("stereo", isStereo) - } - amfEcmaArray.setProperty("filesize", 0.0) - customMetadata.forEach { (key, value) -> - amfEcmaArray.setProperty(key, value) - } - metadata.addData(amfEcmaArray) - - metadata.writeHeader(socket) - metadata.writeBody(socket, config.writeChunkSize) - Log.i(TAG, "send $metadata") - } - - override suspend fun sendPublishImp(socket: RtmpSocket) { - val name = "publish" - val publish = CommandAmf3(name, ++commandId, getCurrentTimestamp(), streamId, - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) - publish.addData(Amf3Null()) - publish.addData(Amf3String(streamName)) - publish.addData(Amf3String("live")) - - publish.writeHeader(socket) - publish.writeBody(socket, config.writeChunkSize) - sessionHistory.setPacket(commandId, name) - Log.i(TAG, "send $publish") - } - - override suspend fun sendCloseImp(socket: RtmpSocket) { - val name = "closeStream" - val closeStream = CommandAmf3(name, ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) - closeStream.addData(Amf3Null()) - - closeStream.writeHeader(socket) - closeStream.writeBody(socket, config.writeChunkSize) - sessionHistory.setPacket(commandId, name) - Log.i(TAG, "send $closeStream") - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerAmf0.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerImp.kt similarity index 84% rename from rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerAmf0.kt rename to rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerImp.kt index ab44079b02..c640e93ce8 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerAmf0.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/CommandsManagerImp.kt @@ -19,24 +19,24 @@ package com.pedro.rtmp.rtmp import android.util.Log import com.pedro.common.AudioCodec import com.pedro.common.VideoCodec -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfEcmaArray -import com.pedro.rtmp.amf.v0.AmfNull -import com.pedro.rtmp.amf.v0.AmfObject -import com.pedro.rtmp.amf.v0.AmfStrictArray -import com.pedro.rtmp.amf.v0.AmfString +import com.pedro.rtmp.amf.AmfData +import com.pedro.rtmp.amf.AmfEcmaArray +import com.pedro.rtmp.amf.AmfNull +import com.pedro.rtmp.amf.AmfObject +import com.pedro.rtmp.amf.AmfStrictArray +import com.pedro.rtmp.amf.AmfString import com.pedro.rtmp.flv.audio.AudioFormat import com.pedro.rtmp.flv.video.VideoFormat import com.pedro.rtmp.rtmp.chunk.ChunkStreamId import com.pedro.rtmp.rtmp.chunk.ChunkType import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.command.CommandAmf0 -import com.pedro.rtmp.rtmp.message.data.DataAmf0 +import com.pedro.rtmp.rtmp.message.Command +import com.pedro.rtmp.rtmp.message.Data import com.pedro.rtmp.utils.socket.RtmpSocket -class CommandsManagerAmf0: CommandsManager() { +class CommandsManagerImp: CommandsManager() { override suspend fun sendConnectImp(auth: String, socket: RtmpSocket) { - val connect = CommandAmf0("connect", ++commandId, getCurrentTimestamp(), streamId, + val connect = Command("connect", ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)) val connectInfo = AmfObject() connectInfo.setProperty("app", appName + auth) @@ -69,7 +69,7 @@ class CommandsManagerAmf0: CommandsManager() { } override suspend fun createStreamImp(socket: RtmpSocket) { - val releaseStream = CommandAmf0("releaseStream", ++commandId, getCurrentTimestamp(), streamId, + val releaseStream = Command("releaseStream", ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) releaseStream.addData(AmfNull()) releaseStream.addData(AmfString(streamName)) @@ -79,7 +79,7 @@ class CommandsManagerAmf0: CommandsManager() { sessionHistory.setPacket(commandId, "releaseStream") Log.i(TAG, "send $releaseStream") - val fcPublish = CommandAmf0("FCPublish", ++commandId, getCurrentTimestamp(), streamId, + val fcPublish = Command("FCPublish", ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) fcPublish.addData(AmfNull()) fcPublish.addData(AmfString(streamName)) @@ -89,7 +89,7 @@ class CommandsManagerAmf0: CommandsManager() { sessionHistory.setPacket(commandId, "FCPublish") Log.i(TAG, "send $fcPublish") - val createStream = CommandAmf0("createStream", ++commandId, getCurrentTimestamp(), streamId, + val createStream = Command("createStream", ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)) createStream.addData(AmfNull()) @@ -101,7 +101,7 @@ class CommandsManagerAmf0: CommandsManager() { override suspend fun sendMetadataImp(socket: RtmpSocket) { val name = "@setDataFrame" - val metadata = DataAmf0(name, getCurrentTimestamp(), streamId) + val metadata = Data(name, getCurrentTimestamp(), streamId) metadata.addData(AmfString("onMetaData")) val amfEcmaArray = AmfEcmaArray() amfEcmaArray.setProperty("duration", 0.0) @@ -143,7 +143,7 @@ class CommandsManagerAmf0: CommandsManager() { override suspend fun sendPublishImp(socket: RtmpSocket) { val name = "publish" - val publish = CommandAmf0(name, ++commandId, getCurrentTimestamp(), streamId, + val publish = Command(name, ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) publish.addData(AmfNull()) publish.addData(AmfString(streamName)) @@ -157,7 +157,7 @@ class CommandsManagerAmf0: CommandsManager() { override suspend fun sendCloseImp(socket: RtmpSocket) { val name = "closeStream" - val closeStream = CommandAmf0(name, ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) + val closeStream = Command(name, ++commandId, getCurrentTimestamp(), streamId, BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_STREAM.mark)) closeStream.addData(AmfNull()) closeStream.writeHeader(socket) diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/RtmpClient.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/RtmpClient.kt index 50263c4c99..bcbf53c4df 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/RtmpClient.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/RtmpClient.kt @@ -31,7 +31,6 @@ import com.pedro.common.socket.base.SocketType import com.pedro.common.socket.base.StreamSocket import com.pedro.common.toMediaFrameInfo import com.pedro.common.validMessage -import com.pedro.rtmp.amf.AmfVersion import com.pedro.rtmp.rtmp.message.Abort import com.pedro.rtmp.rtmp.message.Acknowledgement import com.pedro.rtmp.rtmp.message.Aggregate @@ -39,11 +38,10 @@ import com.pedro.rtmp.rtmp.message.MessageType import com.pedro.rtmp.rtmp.message.SetChunkSize import com.pedro.rtmp.rtmp.message.SetPeerBandwidth import com.pedro.rtmp.rtmp.message.WindowAcknowledgementSize -import com.pedro.rtmp.rtmp.message.command.Command +import com.pedro.rtmp.rtmp.message.Command import com.pedro.rtmp.rtmp.message.control.Type import com.pedro.rtmp.rtmp.message.control.UserControl import com.pedro.rtmp.utils.AuthUtil -import com.pedro.rtmp.utils.RtmpConfig import com.pedro.rtmp.utils.socket.RtmpSocket import com.pedro.rtmp.utils.socket.TcpSocket import com.pedro.rtmp.utils.socket.TcpTunneledSocket @@ -78,7 +76,7 @@ class RtmpClient(private val connectChecker: ConnectChecker) { private var scopePing = CoroutineScope(Dispatchers.IO) private var job: Job? = null private var jobRetry: Job? = null - private var commandsManager: CommandsManager = CommandsManagerAmf0() + private val commandsManager = CommandsManagerImp() private val rtmpSender = RtmpSender(connectChecker, commandsManager) @Volatile @@ -138,15 +136,6 @@ class RtmpClient(private val connectChecker: ConnectChecker) { } } - fun setAmfVersion(amfVersion: AmfVersion) { - if (!isStreaming) { - commandsManager = when (amfVersion) { - AmfVersion.VERSION_0 -> CommandsManagerAmf0() - AmfVersion.VERSION_3 -> TODO("Not yet implemented") - } - } - } - fun setIgnoredCommandCallback(callback: ((String) -> Unit)?) { ignoredCommandReceived = callback } diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/Command.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/Command.kt new file mode 100644 index 0000000000..d68708ca88 --- /dev/null +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/Command.kt @@ -0,0 +1,94 @@ +package com.pedro.rtmp.rtmp.message + +import com.pedro.rtmp.amf.AmfData +import com.pedro.rtmp.amf.AmfNumber +import com.pedro.rtmp.amf.AmfObject +import com.pedro.rtmp.amf.AmfString +import com.pedro.rtmp.rtmp.chunk.ChunkStreamId +import com.pedro.rtmp.rtmp.chunk.ChunkType +import java.io.ByteArrayOutputStream +import java.io.InputStream + +/** + * Created by pedro on 21/04/21. + */ +class Command(var name: String = "", var commandId: Int = 0, private val timeStamp: Int = 0, private val streamId: Int = 0, basicHeader: BasicHeader = + BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)): RtmpMessage(basicHeader) { + + private var bodySize = 0 + private val data: MutableList = mutableListOf() + + init { + header.timeStamp = timeStamp + header.messageStreamId = streamId + + val amfString = AmfString(name) + bodySize += amfString.getSize() + 1 + val amfNumber = AmfNumber(commandId.toDouble()) + bodySize += amfNumber.getSize() + 1 + header.messageLength = bodySize + } + + fun addData(amfData: AmfData) { + data.add(amfData) + bodySize += amfData.getSize() + 1 + header.messageLength = bodySize + } + + fun getStreamId(): Int { + return (data[1] as AmfNumber).value.toInt() + } + + fun getDescription() = getProperty("description") + + fun getCode() = getProperty("code") + + private fun getProperty(key: String): String { + return data.filterIsInstance().firstNotNullOfOrNull { + it.getProperty(key) as? AmfString + }?.value ?: "" + } + + override fun readBody(input: InputStream) { + data.clear() + bodySize = 0 + + val nameData = AmfData.getAmfData(input) + if (nameData is AmfString) name = nameData.value + bodySize += nameData.getSize() + 1 + if (bodySize >= header.messageLength) return + val commandData = AmfData.getAmfData(input) + if (commandData is AmfNumber) commandId = commandData.value.toInt() + bodySize += commandData.getSize() + 1 + + while (bodySize < header.messageLength) { + val amfData = AmfData.getAmfData(input) + data.add(amfData) + bodySize += amfData.getSize() + 1 + } + header.messageLength = bodySize + } + + override fun storeBody(): ByteArray { + val byteArrayOutputStream = ByteArrayOutputStream() + val amfString = AmfString(name) + amfString.writeHeader(byteArrayOutputStream) + amfString.writeBody(byteArrayOutputStream) + val amfNumber = AmfNumber(commandId.toDouble()) + amfNumber.writeHeader(byteArrayOutputStream) + amfNumber.writeBody(byteArrayOutputStream) + data.forEach { + it.writeHeader(byteArrayOutputStream) + it.writeBody(byteArrayOutputStream) + } + return byteArrayOutputStream.toByteArray() + } + + override fun getSize(): Int = bodySize + + override fun getType(): MessageType = MessageType.COMMAND_AMF0 + + override fun toString(): String { + return "Command(name='$name', transactionId=$commandId, timeStamp=$timeStamp, streamId=$streamId, data=$data, bodySize=$bodySize)" + } +} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/DataAmf0.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/Data.kt similarity index 57% rename from rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/DataAmf0.kt rename to rtmp/src/main/java/com/pedro/rtmp/rtmp/message/Data.kt index 8b8e14b687..c9cc2fe845 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/DataAmf0.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/Data.kt @@ -1,44 +1,28 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.data +package com.pedro.rtmp.rtmp.message -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfString +import com.pedro.rtmp.amf.AmfData +import com.pedro.rtmp.amf.AmfString import com.pedro.rtmp.rtmp.chunk.ChunkStreamId import com.pedro.rtmp.rtmp.chunk.ChunkType -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.MessageType import java.io.ByteArrayOutputStream import java.io.InputStream /** * Created by pedro on 21/04/21. */ -class DataAmf0(private var name: String = "", timeStamp: Int = 0, streamId: Int = 0, basicHeader: BasicHeader = BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)) : - Data(timeStamp, streamId, basicHeader) { +class Data(private var name: String = "", timeStamp: Int = 0, streamId: Int = 0, basicHeader: BasicHeader = BasicHeader( + ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)) : + RtmpMessage(basicHeader) { + private var bodySize = 0 private val data: MutableList = mutableListOf() init { + header.timeStamp = timeStamp + header.messageStreamId = streamId + val amfString = AmfString(name) bodySize += amfString.getSize() + 1 - data.forEach { - bodySize += it.getSize() + 1 - } header.messageLength = bodySize } @@ -75,6 +59,8 @@ class DataAmf0(private var name: String = "", timeStamp: Int = 0, streamId: Int return byteArrayOutputStream.toByteArray() } + override fun getSize(): Int = bodySize + override fun getType(): MessageType = MessageType.DATA_AMF0 override fun toString(): String { diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/RtmpMessage.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/RtmpMessage.kt index 07623a3ba2..a42786ffe0 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/RtmpMessage.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/RtmpMessage.kt @@ -17,15 +17,9 @@ package com.pedro.rtmp.rtmp.message import com.pedro.rtmp.rtmp.chunk.ChunkType -import com.pedro.rtmp.rtmp.message.command.CommandAmf0 -import com.pedro.rtmp.rtmp.message.command.CommandAmf3 import com.pedro.rtmp.rtmp.message.control.UserControl -import com.pedro.rtmp.rtmp.message.data.DataAmf0 -import com.pedro.rtmp.rtmp.message.data.DataAmf3 -import com.pedro.rtmp.rtmp.message.shared.SharedObjectAmf0 -import com.pedro.rtmp.rtmp.message.shared.SharedObjectAmf3 +import com.pedro.rtmp.rtmp.message.shared.SharedObject import com.pedro.rtmp.utils.CommandSessionHistory -import com.pedro.rtmp.utils.RtmpConfig import com.pedro.rtmp.utils.socket.RtmpSocket import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream @@ -61,12 +55,9 @@ abstract class RtmpMessage(basicHeader: BasicHeader) { MessageType.SET_PEER_BANDWIDTH -> SetPeerBandwidth() MessageType.AUDIO -> Audio() MessageType.VIDEO -> Video() - MessageType.DATA_AMF3 -> DataAmf3() - MessageType.SHARED_OBJECT_AMF3 -> SharedObjectAmf3() - MessageType.COMMAND_AMF3 -> CommandAmf3() - MessageType.DATA_AMF0 -> DataAmf0() - MessageType.SHARED_OBJECT_AMF0 -> SharedObjectAmf0() - MessageType.COMMAND_AMF0 -> CommandAmf0() + MessageType.DATA_AMF0 -> Data() + MessageType.SHARED_OBJECT_AMF0 -> SharedObject() + MessageType.COMMAND_AMF0 -> Command() MessageType.AGGREGATE -> Aggregate() else -> throw IOException("Unimplemented message type: ${header.messageType}") } diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/Command.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/Command.kt deleted file mode 100644 index e5c192c175..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/Command.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.command - -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.RtmpMessage - -/** - * Created by pedro on 8/04/21. - * - * Represent packets like connect, createStream, play, pause... - * Can be encoded using AMF0 or AMF3 - * - * TODO use amf3 or amf0 depend of getType method - */ -abstract class Command(var name: String = "", var commandId: Int, private val timeStamp: Int, private val streamId: Int = 0, basicHeader: BasicHeader): RtmpMessage(basicHeader) { - - protected var bodySize = 0 - - init { - header.messageLength = bodySize - header.timeStamp = timeStamp - header.messageStreamId = streamId - } - - abstract fun getStreamId(): Int - abstract fun getDescription(): String - abstract fun getCode(): String - - override fun getSize(): Int = bodySize -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/CommandAmf0.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/CommandAmf0.kt deleted file mode 100644 index 8baf010f43..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/CommandAmf0.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.command - -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfNumber -import com.pedro.rtmp.amf.v0.AmfObject -import com.pedro.rtmp.amf.v0.AmfString -import com.pedro.rtmp.rtmp.chunk.ChunkStreamId -import com.pedro.rtmp.rtmp.chunk.ChunkType -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.MessageType -import java.io.ByteArrayOutputStream -import java.io.InputStream - -/** - * Created by pedro on 21/04/21. - */ -class CommandAmf0(name: String = "", commandId: Int = 0, private val timestamp: Int = 0, private val streamId: Int = 0, basicHeader: BasicHeader = - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)): Command(name, commandId, timestamp, streamId, basicHeader = basicHeader) { - - private val data: MutableList = mutableListOf() - - init { - val amfString = AmfString(name) - data.add(amfString) - bodySize += amfString.getSize() + 1 - val amfNumber = AmfNumber(commandId.toDouble()) - bodySize += amfNumber.getSize() + 1 - data.add(amfNumber) - header.messageLength = bodySize - } - - fun addData(amfData: AmfData) { - data.add(amfData) - bodySize += amfData.getSize() + 1 - header.messageLength = bodySize - } - - override fun getStreamId(): Int { - return (data[3] as AmfNumber).value.toInt() - } - - override fun getDescription(): String { - return ((data[3] as AmfObject).getProperty("description") as AmfString).value - } - - override fun getCode(): String { - return ((data[3] as AmfObject).getProperty("code") as AmfString).value - } - - override fun readBody(input: InputStream) { - data.clear() - var bytesRead = 0 - while (bytesRead < header.messageLength) { - val amfData = AmfData.getAmfData(input) - bytesRead += amfData.getSize() + 1 - data.add(amfData) - } - if (data.isNotEmpty()) { - if (data[0] is AmfString) { - name = (data[0] as AmfString).value - } - if (data.size >= 2 && data[1] is AmfNumber) { - commandId = (data[1] as AmfNumber).value.toInt() - } - } - bodySize = bytesRead - header.messageLength = bodySize - } - - override fun storeBody(): ByteArray { - val byteArrayOutputStream = ByteArrayOutputStream() - data.forEach { - it.writeHeader(byteArrayOutputStream) - it.writeBody(byteArrayOutputStream) - } - return byteArrayOutputStream.toByteArray() - } - - override fun getType(): MessageType = MessageType.COMMAND_AMF0 - - override fun toString(): String { - return "Command(name='$name', transactionId=$commandId, timeStamp=$timestamp, streamId=$streamId, data=$data, bodySize=$bodySize)" - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/CommandAmf3.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/CommandAmf3.kt deleted file mode 100644 index bb919b3ef6..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/command/CommandAmf3.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.command - -import com.pedro.rtmp.amf.v3.Amf3Data -import com.pedro.rtmp.amf.v3.Amf3Double -import com.pedro.rtmp.amf.v3.Amf3Object -import com.pedro.rtmp.amf.v3.Amf3String -import com.pedro.rtmp.rtmp.chunk.ChunkStreamId -import com.pedro.rtmp.rtmp.chunk.ChunkType -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.MessageType -import java.io.ByteArrayOutputStream -import java.io.InputStream - -/** - * Created by pedro on 21/04/21. - */ -class CommandAmf3(name: String = "", commandId: Int = 0, private val timestamp: Int = 0, private val streamId: Int = 0, basicHeader: BasicHeader = - BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)): Command(name, commandId, timestamp, streamId, basicHeader = basicHeader) { - - private val data: MutableList = mutableListOf() - - init { - val amf3String = Amf3String(name) - data.add(amf3String) - bodySize += amf3String.getSize() + 1 - val amf3Double = Amf3Double(commandId.toDouble()) - bodySize += amf3Double.getSize() + 1 - data.add(amf3Double) - header.messageLength = bodySize - } - - fun addData(amf3Data: Amf3Data) { - data.add(amf3Data) - bodySize += amf3Data.getSize() + 1 - header.messageLength = bodySize - } - - override fun getStreamId(): Int { - return (data[3] as Amf3Double).value.toInt() - } - - override fun getDescription(): String { - return ((data[3] as Amf3Object).getProperty("description") as Amf3String).value - } - - override fun getCode(): String { - return ((data[3] as Amf3Object).getProperty("code") as Amf3String).value - } - - override fun readBody(input: InputStream) { - data.clear() - var bytesRead = 0 - while (bytesRead < header.messageLength) { - val amf3Data = Amf3Data.getAmf3Data(input) - bytesRead += amf3Data.getSize() + 1 - data.add(amf3Data) - } - if (data.isNotEmpty()) { - if (data[0] is Amf3String) { - name = (data[0] as Amf3String).value - } - if (data.size >= 2 && data[1] is Amf3Double) { - commandId = (data[1] as Amf3Double).value.toInt() - } - } - bodySize = bytesRead - header.messageLength = bodySize - } - - override fun storeBody(): ByteArray { - val byteArrayOutputStream = ByteArrayOutputStream() - data.forEach { - it.writeHeader(byteArrayOutputStream) - it.writeBody(byteArrayOutputStream) - } - return byteArrayOutputStream.toByteArray() - } - - override fun getType(): MessageType = MessageType.COMMAND_AMF3 - - override fun toString(): String { - return "Command(name='$name', transactionId=$commandId, timeStamp=$timestamp, streamId=$streamId, data=$data, bodySize=$bodySize)" - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/Data.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/Data.kt deleted file mode 100644 index b68ae37396..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/Data.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.data - -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.RtmpMessage - -/** - * Created by pedro on 21/04/21. - */ -abstract class Data(timeStamp: Int, streamId: Int, basicHeader: BasicHeader): RtmpMessage(basicHeader) { - - protected var bodySize = 0 - - init { - header.messageLength = bodySize - header.timeStamp = timeStamp - header.messageStreamId = streamId - } - - override fun getSize(): Int = bodySize -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/DataAmf3.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/DataAmf3.kt deleted file mode 100644 index e2ef45309f..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/data/DataAmf3.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.data - -import com.pedro.rtmp.amf.v3.Amf3Data -import com.pedro.rtmp.amf.v3.Amf3String -import com.pedro.rtmp.rtmp.chunk.ChunkStreamId -import com.pedro.rtmp.rtmp.chunk.ChunkType -import com.pedro.rtmp.rtmp.message.BasicHeader -import com.pedro.rtmp.rtmp.message.MessageType -import java.io.ByteArrayOutputStream -import java.io.InputStream - -/** - * Created by pedro on 21/04/21. - */ -class DataAmf3(private val name: String = "", timeStamp: Int = 0, streamId: Int = 0, basicHeader: BasicHeader = BasicHeader(ChunkType.TYPE_0, ChunkStreamId.OVER_CONNECTION.mark)): - Data(timeStamp, streamId, basicHeader) { - - private val data: MutableList = mutableListOf() - - init { - val amf3String = Amf3String(name) - bodySize += amf3String.getSize() + 1 - data.forEach { - bodySize += it.getSize() + 1 - } - header.messageLength = bodySize - } - - fun addData(amf3Data: Amf3Data) { - data.add(amf3Data) - bodySize += amf3Data.getSize() + 1 - header.messageLength = bodySize - } - - override fun readBody(input: InputStream) { - data.clear() - bodySize = 0 - val amf3String = Amf3String() - amf3String.readHeader(input) - amf3String.readBody(input) - bodySize += amf3String.getSize() + 1 - while (bodySize < header.messageLength) { - val amf3Data = Amf3Data.getAmf3Data(input) - data.add(amf3Data) - bodySize += amf3Data.getSize() + 1 - } - } - - override fun storeBody(): ByteArray { - val byteArrayOutputStream = ByteArrayOutputStream() - val amf3String = Amf3String(name) - amf3String.writeHeader(byteArrayOutputStream) - amf3String.writeBody(byteArrayOutputStream) - data.forEach { - it.writeHeader(byteArrayOutputStream) - it.writeBody(byteArrayOutputStream) - } - return byteArrayOutputStream.toByteArray() - } - - override fun getType(): MessageType = MessageType.DATA_AMF3 - - override fun toString(): String { - return "Data(name='$name', data=$data, bodySize=$bodySize)" - } -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObject.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObject.kt index b6f5b5c19e..d79c37d43d 100644 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObject.kt +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObject.kt @@ -1,37 +1,116 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.pedro.rtmp.rtmp.message.shared +import com.pedro.common.readUInt16 +import com.pedro.common.readUInt32 +import com.pedro.common.readUntil +import com.pedro.common.toUInt64 +import com.pedro.common.writeUInt16 +import com.pedro.common.writeUInt32 +import com.pedro.rtmp.amf.AmfData +import com.pedro.rtmp.amf.AmfString import com.pedro.rtmp.rtmp.chunk.ChunkStreamId import com.pedro.rtmp.rtmp.chunk.ChunkType import com.pedro.rtmp.rtmp.message.BasicHeader +import com.pedro.rtmp.rtmp.message.MessageType import com.pedro.rtmp.rtmp.message.RtmpMessage +import java.io.ByteArrayOutputStream import java.io.InputStream /** * Created by pedro on 21/04/21. */ -abstract class SharedObject: RtmpMessage(BasicHeader(ChunkType.TYPE_0, ChunkStreamId.PROTOCOL_CONTROL.mark)) { +class SharedObject( + private var name: String = "", + private var version: Int = 0, + private var flags: Long = 0L, + private val events: MutableList = mutableListOf() +): RtmpMessage(BasicHeader(ChunkType.TYPE_0, ChunkStreamId.PROTOCOL_CONTROL.mark)) { + + private var bodySize = 0 + + init { + bodySize += 2 + name.toByteArray(Charsets.UTF_8).size + 4 + 8 + events.forEach { addEventSize(it) } + } + + fun addEvent(event: SharedObjectEvent) { + events.add(event) + addEventSize(event) + } + + private fun addEventSize(event: SharedObjectEvent) { + bodySize += 1 + 4 + event.data.forEach { (key, value) -> + bodySize += AmfString(key).getSize() + bodySize += value.getSize() + 1 + } + } + override fun readBody(input: InputStream) { + events.clear() + bodySize = 0 + + val nameLength = input.readUInt16() + bodySize += 2 + val bytes = ByteArray(nameLength) + input.readUntil(bytes) + bodySize += nameLength + name = String(bytes, Charsets.UTF_8) + version = input.readUInt32() + bodySize += 4 + val flagsBytes = ByteArray(8) + input.readUntil(flagsBytes) + flags = flagsBytes.toUInt64() + bodySize += flagsBytes.size + while (bodySize < header.messageLength) { + val typeByte = input.read() + bodySize += 1 + val type = SharedObjectEventType.entries.find { it.value == typeByte } ?: SharedObjectEventType.UNKNOWN + val data = linkedMapOf() + val dataLength = input.readUInt32() + bodySize += 4 + var dataRead = 0 + while (dataRead < dataLength && dataRead + bodySize < header.messageLength) { + val key = AmfString().apply { readBody(input) } + dataRead += key.getSize() + val value = AmfData.getAmfData(input) + dataRead += value.getSize() + 1 + data[key.value] = value + } + bodySize += dataRead + events.add(SharedObjectEvent(type, data)) + } + header.messageLength = bodySize } override fun storeBody(): ByteArray { - TODO("Not yet implemented") + val output = ByteArrayOutputStream() + val nameBytes = name.toByteArray(Charsets.UTF_8) + output.writeUInt16(nameBytes.size) + output.write(nameBytes) + output.writeUInt32(version) + output.write(flags.toUInt64()) + events.forEach { event -> + output.write(event.type.value) + val dataLength = event.data.map { + val keySize = AmfString(it.key).getSize() + keySize + it.value.getSize() + 1 + }.sum() + output.writeUInt32(dataLength) + event.data.forEach { (key, value) -> + AmfString(key).apply { writeBody(output) } + value.writeHeader(output) + value.writeBody(output) + } + } + return output.toByteArray() } - override fun getSize(): Int = 0 + override fun getSize(): Int = bodySize + + override fun getType(): MessageType = MessageType.SHARED_OBJECT_AMF0 + + override fun toString(): String { + return "SharedObject(name='$name', version=$version, flags=$flags, events=$events, bodySize=$bodySize)" + } } \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectAmf0.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectAmf0.kt deleted file mode 100644 index 9e81316bdc..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectAmf0.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.shared - -import com.pedro.rtmp.rtmp.message.MessageType - -/** - * Created by pedro on 21/04/21. - */ -class SharedObjectAmf0: SharedObject() { - override fun getType(): MessageType = MessageType.SHARED_OBJECT_AMF0 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectAmf3.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectAmf3.kt deleted file mode 100644 index ee5c5b8796..0000000000 --- a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectAmf3.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2024 pedroSG94. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pedro.rtmp.rtmp.message.shared - -import com.pedro.rtmp.rtmp.message.MessageType - -/** - * Created by pedro on 21/04/21. - */ -class SharedObjectAmf3: SharedObject() { - override fun getType(): MessageType = MessageType.SHARED_OBJECT_AMF3 -} \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectEvent.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectEvent.kt new file mode 100644 index 0000000000..a399d6022e --- /dev/null +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectEvent.kt @@ -0,0 +1,8 @@ +package com.pedro.rtmp.rtmp.message.shared + +import com.pedro.rtmp.amf.AmfData + +data class SharedObjectEvent( + val type: SharedObjectEventType, + val data: LinkedHashMap +) \ No newline at end of file diff --git a/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectEventType.kt b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectEventType.kt new file mode 100644 index 0000000000..c39a45bee3 --- /dev/null +++ b/rtmp/src/main/java/com/pedro/rtmp/rtmp/message/shared/SharedObjectEventType.kt @@ -0,0 +1,7 @@ +package com.pedro.rtmp.rtmp.message.shared + +enum class SharedObjectEventType(val value: Int) { + USE(1), RELEASE(2), REQUEST_CHANGE(3), CHANGE(4), + SUCCESS(5), SEND_MESSAGE(6), STATUS(7), CLEAR(8), REMOVE(9), + REQUEST_REMOVE(10), USE_SUCCESS(11), UNKNOWN(255); +} \ No newline at end of file diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfBooleanTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfBooleanTest.kt index 4e73ef3e83..b7d75b08f8 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfBooleanTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfBooleanTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfBoolean -import com.pedro.rtmp.amf.v0.AmfData import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfDateTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfDateTest.kt index a537693954..101b2b7224 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfDateTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfDateTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfDate import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfEcmaArrayTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfEcmaArrayTest.kt index 539a740091..c2e90a57f0 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfEcmaArrayTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfEcmaArrayTest.kt @@ -16,10 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfEcmaArray -import com.pedro.rtmp.amf.v0.AmfNumber -import com.pedro.rtmp.amf.v0.AmfString import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfLongStringTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfLongStringTest.kt index efbff7cd95..b2a59c424c 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfLongStringTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfLongStringTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfLongString import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNullTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNullTest.kt index 1855e91163..05c9dc6496 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNullTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNullTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfNull import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertTrue import org.junit.Test diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNumberTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNumberTest.kt index 61addca5c1..89827556c9 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNumberTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfNumberTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfNumber import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfObjectTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfObjectTest.kt index 2ce9bbc636..db14c0dc72 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfObjectTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfObjectTest.kt @@ -16,10 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfNumber -import com.pedro.rtmp.amf.v0.AmfObject -import com.pedro.rtmp.amf.v0.AmfString import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStrictArrayTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStrictArrayTest.kt index 26f0d70e59..abdd4d4c1d 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStrictArrayTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStrictArrayTest.kt @@ -16,10 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfNumber -import com.pedro.rtmp.amf.v0.AmfStrictArray -import com.pedro.rtmp.amf.v0.AmfString import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStringTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStringTest.kt index a35de9c09b..22ea5ec12d 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStringTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfStringTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfString import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUndefinedTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUndefinedTest.kt index 3968ac71df..0bcf925da7 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUndefinedTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUndefinedTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfUndefined import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertTrue import org.junit.Test diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUnsupportedTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUnsupportedTest.kt index 5f72b049f2..028073defa 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUnsupportedTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfUnsupportedTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfUnsupported import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertTrue import org.junit.Test diff --git a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfXmlDocumentTest.kt b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfXmlDocumentTest.kt index b42b356617..c74a01472f 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/amf/AmfXmlDocumentTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/amf/AmfXmlDocumentTest.kt @@ -16,8 +16,6 @@ package com.pedro.rtmp.amf -import com.pedro.rtmp.amf.v0.AmfData -import com.pedro.rtmp.amf.v0.AmfXmlDocument import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/CommandTest.kt b/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/CommandTest.kt index c2e8f5da58..6dfbedde84 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/CommandTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/CommandTest.kt @@ -17,9 +17,8 @@ package com.pedro.rtmp.rtmp.message import com.pedro.rtmp.FakeRtmpSocket -import com.pedro.rtmp.amf.v0.AmfNumber -import com.pedro.rtmp.amf.v0.AmfString -import com.pedro.rtmp.rtmp.message.command.CommandAmf0 +import com.pedro.rtmp.amf.AmfNumber +import com.pedro.rtmp.amf.AmfString import com.pedro.rtmp.utils.CommandSessionHistory import com.pedro.rtmp.utils.RtmpConfig import kotlinx.coroutines.test.runTest @@ -46,21 +45,21 @@ class CommandTest { fun `GIVEN a buffer WHEN read rtmp message THEN get expected command amf0 packet`() = runTest { val buffer = byteArrayOf(3, 0, 0, 0, 0, 0, 34, 20, 0, 0, 0, 0, 2, 0, 4, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 114, 97, 110, 100, 111, 109, 0, 64, 52, 0, 0, 0, 0, 0, 0) socket.setInputBytes(buffer) - val commandAmf0 = CommandAmf0("test") - commandAmf0.addData(AmfString("random")) - commandAmf0.addData(AmfNumber(20.0)) + val command = Command("test") + command.addData(AmfString("random")) + command.addData(AmfNumber(20.0)) val message = RtmpMessage.getRtmpMessage(socket, RtmpConfig.DEFAULT_CHUNK_SIZE, commandSessionHistory) - assertTrue(message is CommandAmf0) - assertEquals(commandAmf0.toString(), (message as CommandAmf0).toString()) + assertTrue(message is Command) + assertEquals(command.toString(), (message as Command).toString()) } @Test fun `GIVEN a command amf0 packet WHEN write into a buffer THEN get expected buffer`() = runTest { val expectedBuffer = byteArrayOf(3, 0, 0, 0, 0, 0, 34, 20, 0, 0, 0, 0, 2, 0, 4, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 114, 97, 110, 100, 111, 109, 0, 64, 52, 0, 0, 0, 0, 0, 0) - val commandAmf0 = CommandAmf0("test") + val commandAmf0 = Command("test") commandAmf0.addData(AmfString("random")) commandAmf0.addData(AmfNumber(20.0)) diff --git a/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/DataTest.kt b/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/DataTest.kt index b0a2577a5b..b8d373709c 100644 --- a/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/DataTest.kt +++ b/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/DataTest.kt @@ -17,9 +17,8 @@ package com.pedro.rtmp.rtmp.message import com.pedro.rtmp.FakeRtmpSocket -import com.pedro.rtmp.amf.v0.AmfNumber -import com.pedro.rtmp.amf.v0.AmfString -import com.pedro.rtmp.rtmp.message.data.DataAmf0 +import com.pedro.rtmp.amf.AmfNumber +import com.pedro.rtmp.amf.AmfString import com.pedro.rtmp.utils.CommandSessionHistory import com.pedro.rtmp.utils.RtmpConfig import kotlinx.coroutines.test.runTest @@ -46,21 +45,21 @@ class DataTest { fun `GIVEN a buffer WHEN read rtmp message THEN get expected data amf0 packet`() = runTest { val buffer = byteArrayOf(3, 0, 0, 0, 0, 0, 25, 18, 0, 0, 0, 0, 2, 0, 4, 116, 101, 115, 116, 2, 0, 6, 114, 97, 110, 100, 111, 109, 0, 64, 52, 0, 0, 0, 0, 0, 0) socket.setInputBytes(buffer) - val dataAmf0 = DataAmf0("test") - dataAmf0.addData(AmfString("random")) - dataAmf0.addData(AmfNumber(20.0)) + val data = Data("test") + data.addData(AmfString("random")) + data.addData(AmfNumber(20.0)) val message = RtmpMessage.getRtmpMessage(socket, RtmpConfig.DEFAULT_CHUNK_SIZE, commandSessionHistory) - assertTrue(message is DataAmf0) - assertEquals(dataAmf0.toString(), (message as DataAmf0).toString()) + assertTrue(message is Data) + assertEquals(data.toString(), (message as Data).toString()) } @Test fun `GIVEN a data amf0 packet WHEN write into a buffer THEN get expected buffer`() = runTest { val expectedBuffer = byteArrayOf(3, 0, 0, 0, 0, 0, 25, 18, 0, 0, 0, 0, 2, 0, 4, 116, 101, 115, 116, 2, 0, 6, 114, 97, 110, 100, 111, 109, 0, 64, 52, 0, 0, 0, 0, 0, 0) - val dataAmf0 = DataAmf0("test") + val dataAmf0 = Data("test") dataAmf0.addData(AmfString("random")) dataAmf0.addData(AmfNumber(20.0)) diff --git a/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/SharedObjectTest.kt b/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/SharedObjectTest.kt new file mode 100644 index 0000000000..5cf2a37e59 --- /dev/null +++ b/rtmp/src/test/java/com/pedro/rtmp/rtmp/message/SharedObjectTest.kt @@ -0,0 +1,60 @@ +package com.pedro.rtmp.rtmp.message + +import com.pedro.rtmp.FakeRtmpSocket +import com.pedro.rtmp.amf.AmfData +import com.pedro.rtmp.amf.AmfNumber +import com.pedro.rtmp.rtmp.message.shared.SharedObject +import com.pedro.rtmp.rtmp.message.shared.SharedObjectEvent +import com.pedro.rtmp.rtmp.message.shared.SharedObjectEventType +import com.pedro.rtmp.utils.CommandSessionHistory +import com.pedro.rtmp.utils.RtmpConfig +import kotlinx.coroutines.test.runTest +import org.junit.Assert +import org.junit.Before +import org.junit.Test + + +class SharedObjectTest { + + private val commandSessionHistory = CommandSessionHistory() + private lateinit var socket: FakeRtmpSocket + + @Before + fun setup() { + socket = FakeRtmpSocket() + } + + private fun createSharedObject(): SharedObject { + val sharedObject = SharedObject("test") + val data = linkedMapOf("random" to AmfNumber(20.0)) + sharedObject.addEvent(SharedObjectEvent(SharedObjectEventType.CHANGE, data)) + return sharedObject + } + + @Test + fun `GIVEN a buffer WHEN read rtmp message THEN get expected shared object amf0 packet`() = + runTest { + val buffer = byteArrayOf(2, 0, 0, 0, 0, 0, 40, 19, 0, 0, 0, 0, 0, 4, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 17, 0, 6, 114, 97, 110, 100, 111, 109, 0, 64, 52, 0, 0, 0, 0, 0, 0) + socket.setInputBytes(buffer) + val sharedObject = createSharedObject() + + val message = + RtmpMessage.getRtmpMessage(socket, RtmpConfig.DEFAULT_CHUNK_SIZE, commandSessionHistory) + + Assert.assertTrue(message is SharedObject) + Assert.assertEquals(sharedObject.toString(), (message as SharedObject).toString()) + } + + @Test + fun `GIVEN a shared object amf0 packet WHEN write into a buffer THEN get expected buffer`() = + runTest { + val expectedBuffer = byteArrayOf(2, 0, 0, 0, 0, 0, 40, 19, 0, 0, 0, 0, 0, 4, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 17, 0, 6, 114, 97, 110, 100, 111, 109, 0, 64, 52, 0, 0, 0, 0, 0, 0) + + val sharedObject = createSharedObject() + + sharedObject.writeHeader(socket) + sharedObject.writeBody(socket, RtmpConfig.DEFAULT_CHUNK_SIZE) + + Assert.assertArrayEquals(expectedBuffer, socket.output.toByteArray()) + } +} \ No newline at end of file