Skip to content

Commit c21b78f

Browse files
committed
fu flv
1 parent a0d45ea commit c21b78f

File tree

121 files changed

+6535
-2701
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+6535
-2701
lines changed

.github/workflows/documentation.yml

Lines changed: 0 additions & 27 deletions
This file was deleted.

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ jobs:
2121
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }}
2222
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }}
2323
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}
24-
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.OSSRH_USERNAME }}
25-
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.OSSRH_TOKEN }}
24+
ORG_GRADLE_PROJECT_centralPortalUsername: ${{ secrets.CENTRAL_PORTAL_USERNAME }}
25+
ORG_GRADLE_PROJECT_centralPortalPassword: ${{ secrets.CENTRAL_PORTAL_PASSWORD }}
2626
- name: Generate documentation
2727
run: ./gradlew dokkaHtmlMultiModule
2828
- name: Deploy API documentation to Github Pages

README.md

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ implementation("io.github.thibaultbee.krtmp:rtmp:1.0.0")
2828

2929
## Usage
3030

31-
Creates a RTMP publish client with the Factory `RtmpClientConnectionFactory`:
31+
### Client
32+
33+
Creates a RTMP client with the Factory `RtmpClient`:
3234

3335
```kotlin
34-
val client = RtmpPublishClientConnectionFactory().create(
36+
val client = RtmpClient(
3537
"rtmp://my.server.com/app/streamkey" // Your RTMP server URL (incl app name and stream key)
3638
)
3739
```
@@ -44,15 +46,6 @@ client.createStream()
4446
client.publish(Command.Publish.Type.LIVE)
4547
```
4648

47-
If you have raw audio and video frames, you need to mux them into FLV tag headers. You can use
48-
the `FlvMuxer` class for that.
49-
50-
```kotlin
51-
val flvMuxer = client.flvMuxer
52-
```
53-
54-
See [FLV](#flv) for more details to write audio and video frames..
55-
5649
If you already have FLV data, write your video/audio data:
5750

5851
```kotlin
@@ -72,7 +65,21 @@ try {
7265
}
7366
```
7467

75-
For advanced configuration, see `RtmpClientSettings`.
68+
See [FLV](#flv) for more details to write audio and video frames..
69+
70+
### Server
71+
72+
Use the `RtmpServer` to create a RTMP server:
73+
74+
```kotlin
75+
val server = RtmpServer("0.0.0.0:1935") // Listening on port 1935
76+
```
77+
78+
Then start the server:
79+
80+
```kotlin
81+
server.listen()
82+
```
7683

7784
# FLV
7885

@@ -84,8 +91,9 @@ Features:
8491
- [x] Demuxer for FLV
8592
- [x] AMF0 metadata
8693
- [ ] AMF3 metadata
87-
- [x] Supported audio codec: AAC
88-
- [x] Supported video codec: AVC/H.264 and enhanced RTMP codecs: HEVC/H.265, VP9, AV1
94+
- [x] Support for legacy RTMP
95+
- [x] Support for enhanced RTMP v1: AV1, HEVC, VP8, VP9
96+
- [x] Support for enhanced RTMP v2: Multitrack, Opus,...
8997

9098
## Installation
9199

@@ -100,36 +108,36 @@ implementation("io.github.thibaultbee.krtmp:flv:1.0.0")
100108
Creates a FLV muxer and add audio/video data:
101109

102110
```kotlin
103-
val muxer = FlvMuxer()
111+
val muxer = FLVMuxer(path = "/path/to/file.flv")
112+
113+
// Write FLV header
114+
flvMuxer.encodeFlvHeader(hasAudio, hasVideo)
104115

105116
// Register audio configurations (if any)
106-
val audioConfig = FlvAudioConfig(
117+
val audioConfig = FLVAudioConfig(
107118
FlvAudioConfig.SoundFormat.AAC,
108119
FlvAudioConfig.SoundRate.KHZ44,
109120
FlvAudioConfig.SoundSize.SND8BIT,
110121
FlvAudioConfig.SoundType.STEREO
111122
)
112-
val audioId = muxer.addStream(audioConfig)
113-
114-
// Register audio configurations (if any)
115-
val videoConfig = FlvVideoConfig(
116-
123+
// Register video configurations (if any)
124+
val videoConfig = FLVVideoConfig(
117125
)
118-
val videoId = muxer.addStream(videoConfig)
119126

120-
// Start the muxer (write FlvTag (if needed) and onMetaData)
121-
muxer.startStream()
127+
// Write onMetadata
128+
muxer.encode(0, OnMetadata(audioConfig, videoConfig))
122129

123130
// Write audio/video data
124-
muxer.write(audioFrame)
125-
muxer.write(videoFrame)
126-
muxer.write(audioFrame)
127-
muxer.write(videoFrame)
128-
// till you're done
131+
muxer.encode(audioFrame)
132+
muxer.encode(videoFrame)
133+
muxer.encode(audioFrame)
134+
muxer.encode(videoFrame)
129135

130-
// Stop the muxer
131-
muxer.stopStream()
136+
// Till you're done, then
137+
muxer.flush()
132138

139+
// Close the output
140+
muxer.close()
133141
```
134142

135143
# AMF
@@ -140,7 +148,7 @@ Features:
140148

141149
- [x] Serializer for AMF0
142150
- [ ] Serializer for AMF3
143-
- [ ] Deserializer for AMF0
151+
- [x] Deserializer for AMF0
144152
- [ ] Deserializer for AMF3
145153

146154
## Installation
@@ -172,7 +180,7 @@ val array = Amf.encodeToByteArray(MyData.serializer(), data)
172180

173181
# TODO
174182

175-
- [x] A FLV/RTMP parameter for supported level: (legacy, enhanced v1, enhanced v2,...)
183+
- [ ] More tests (missing tests samples)
176184

177185
# Licence
178186

amf/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ kotlin {
2727
compilations.all {
2828
compileTaskProvider.configure {
2929
compilerOptions {
30-
jvmTarget.set(JvmTarget.JVM_1_8)
30+
jvmTarget.set(JvmTarget.JVM_18)
3131
}
3232
}
3333
}
@@ -68,7 +68,7 @@ kotlin {
6868

6969
android {
7070
namespace = "io.github.thibaultbee.krtmp.amf"
71-
compileSdk = 34
71+
compileSdk = 36
7272
defaultConfig {
7373
minSdk = 21
7474
}

amf/src/commonMain/kotlin/io/github/thibaultbee/krtmp/amf/elements/containers/AmfContainer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,5 @@ class AmfContainer internal constructor(private val elements: MutableList<AmfEle
6464
override fun equals(other: Any?): Boolean = elements == other
6565
override fun hashCode(): Int = elements.hashCode()
6666
override fun toString(): String =
67-
elements.joinToString(prefix = "[", postfix = "]", separator = ",")
67+
elements.joinToString(prefix = "[", postfix = "]", separator = ", ")
6868
}

amf/src/commonMain/kotlin/io/github/thibaultbee/krtmp/amf/elements/containers/AmfEcmaArray.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ class AmfEcmaArray internal constructor(private val elements: MutableMap<String,
8383
override fun hashCode(): Int = elements.hashCode()
8484
override fun toString(): String {
8585
return elements.entries.joinToString(
86-
separator = ",",
86+
separator = ", ",
8787
prefix = "{",
8888
postfix = "}",
8989
transform = { (k, v) ->
9090
buildString {
9191
append(k)
92-
append(':')
92+
append('=')
9393
append(v)
9494
}
9595
}

amf/src/commonMain/kotlin/io/github/thibaultbee/krtmp/amf/elements/containers/AmfObject.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ class AmfObject internal constructor(private val elements: MutableMap<String, Am
7676
override fun hashCode(): Int = elements.hashCode()
7777
override fun toString(): String {
7878
return elements.entries.joinToString(
79-
separator = ",",
79+
separator = ", ",
8080
prefix = "{",
8181
postfix = "}",
8282
transform = { (k, v) ->
8383
buildString {
8484
append(k)
85-
append(':')
85+
append('=')
8686
append(v)
8787
}
8888
}

amf/src/commonMain/kotlin/io/github/thibaultbee/krtmp/amf/elements/containers/AmfStrictArray.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ fun amf0StrictArrayFrom(source: Source): AmfStrictArray {
3434
return amf0StrictArray
3535
}
3636

37-
fun amfStrictArrayOf(initialElements: List<Any?>) = AmfStrictArray().apply { addAll(initialElements) }
37+
fun amfStrictArrayOf(initialElements: List<Any?>) =
38+
AmfStrictArray().apply { addAll(initialElements) }
3839

3940
class AmfStrictArray internal constructor(private val elements: MutableList<AmfElement> = mutableListOf()) :
4041
AmfElement(), MutableList<AmfElement> by elements {
@@ -59,5 +60,5 @@ class AmfStrictArray internal constructor(private val elements: MutableList<AmfE
5960
override fun equals(other: Any?): Boolean = elements == other
6061
override fun hashCode(): Int = elements.hashCode()
6162
override fun toString(): String =
62-
elements.joinToString(prefix = "[", postfix = "]", separator = ",")
63+
elements.joinToString(prefix = "[", postfix = "]", separator = ", ")
6364
}

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ kover {
6363
reports {
6464
verify {
6565
rule {
66-
minBound(65, CoverageUnit.LINE)
66+
minBound(35, CoverageUnit.LINE)
6767

6868
// we allow lower branch coverage, because not all checks in the internal code lead to errors
69-
minBound(45, CoverageUnit.BRANCH)
69+
minBound(30, CoverageUnit.BRANCH)
7070
}
7171
}
7272
}

buildSrc/src/main/kotlin/Utils.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
import org.gradle.api.Project
2-
import java.util.Locale
32

43
fun Project.loadProperty(
54
projectPropertyName: String,
65
envName: String = projectPropertyName.uppercase()
7-
): String {
6+
): String? {
87
val envValue = System.getenv(envName)?.toString()
98
if (envValue != null) return envValue
109

1110
val projectPropertiesValue = project.properties[projectPropertyName]?.toString()
1211
if (projectPropertiesValue != null) return projectPropertiesValue
1312

14-
return ""
13+
return null
1514
}
1615

1716
fun Project.loadFileContents(
1817
projectPropertyName: String,
1918
envName: String = projectPropertyName.uppercase()
20-
): String {
19+
): String? {
2120
val decodeIfNeeded: (String) -> String = {
2221
if (it.startsWith("~/")) {
2322
// the value is a path to file on disk. Read its contents
@@ -35,5 +34,5 @@ fun Project.loadFileContents(
3534
val projectPropertiesValue = project.properties[projectPropertyName]?.toString()
3635
if (projectPropertiesValue != null) return decodeIfNeeded(projectPropertiesValue)
3736

38-
return ""
37+
return null
3938
}

0 commit comments

Comments
 (0)