Skip to content

Commit 17df2ed

Browse files
committed
fu flv
1 parent 4325714 commit 17df2ed

File tree

16 files changed

+355
-193
lines changed

16 files changed

+355
-193
lines changed

amf/src/commonMain/kotlin/io/github/thibaultbee/krtmp/amf/elements/primitives/AmfInt.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import io.github.thibaultbee.krtmp.amf.elements.AmfPrimitive
1919
import kotlinx.io.Sink
2020

2121
class AmfInt(override val value: Int) : AmfPrimitive<Int>() {
22-
override val size0 = -1
22+
override val size0 = throw NotImplementedError("Int not supported in AMF0")
2323

2424
override val size3: Int
2525
get() {

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/config/FLVAudioConfig.kt

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,112 @@
1616
package io.github.thibaultbee.krtmp.flv.models.config
1717

1818
class FLVAudioConfig(
19-
override val mediaType: MediaType,
19+
override val mediaType: AudioMediaType,
2020
override val bitrateBps: Int,
2121
val soundRate: SoundRate,
2222
val soundSize: SoundSize,
2323
val soundType: SoundType,
24-
) : FLVConfig {
25-
val soundFormat = SoundFormat.fromMediaType(mediaType)
26-
27-
init {
28-
require(mediaType.type == MediaType.Type.AUDIO) { "MimeType must be an audio type" }
29-
}
24+
) : FLVConfig<AudioMediaType> {
25+
val soundFormat = mediaType.soundFormat
26+
val fourCC = mediaType.fourCCs
27+
val metadataType = soundFormat?.value?.toInt() ?: fourCC!!.value.code
3028
}
3129

32-
enum class SoundFormat(val value: Byte, val mediaType: MediaType? = null) {
33-
PCM(0, MediaType.AUDIO_RAW),
30+
enum class SoundFormat(val value: Byte) {
31+
PCM(0),
3432
ADPCM(1),
3533
MP3(2),
3634
PCM_LE(3),
3735
NELLYMOSER_16KHZ(4),
3836
NELLYMOSER_8KHZ(5),
3937
NELLYMOSER(6),
40-
G711_ALAW(7, MediaType.AUDIO_G711A),
41-
G711_MLAW(8, MediaType.AUDIO_G711U),
42-
AAC(10, MediaType.AUDIO_AAC),
38+
G711_ALAW(7),
39+
G711_MLAW(8),
40+
AAC(10),
4341
SPEEX(11),
4442
MP3_8K(14),
4543
DEVICE_SPECIFIC(15);
4644

4745
companion object {
48-
fun fromMediaType(mediaType: MediaType) = entries.firstOrNull { it.mediaType == mediaType }
49-
?: throw IllegalArgumentException("Invalid MediaType: $mediaType")
50-
5146
fun entryOf(value: Byte) =
5247
entries.firstOrNull { it.value == value } ?: throw IllegalArgumentException(
5348
"Invalid SoundFormat value: $value"
5449
)
5550
}
5651
}
5752

53+
54+
/**
55+
* FourCC object
56+
*
57+
* Only enhanced RTMP FourCC exists.
58+
*/
59+
enum class AudioFourCC(val value: FourCC) {
60+
AC3(
61+
FourCC(
62+
'a', 'c', '-', '3'
63+
)
64+
),
65+
EAC3(FourCC('e', 'c', '-', '3')),
66+
OPUS(
67+
FourCC(
68+
'O', 'p', 'u', 's'
69+
)
70+
),
71+
MP3(
72+
FourCC(
73+
'.', 'm', 'p', '3'
74+
)
75+
),
76+
FLAC(FourCC('f', 'L', 'a', 'C')),
77+
AAC(
78+
FourCC(
79+
'm', 'p', '4', 'a'
80+
)
81+
);
82+
83+
companion object {
84+
fun codeOf(value: Int) = entries.firstOrNull { it.value.code == value }
85+
?: throw IllegalArgumentException("Invalid audio FourCC code: $value")
86+
}
87+
}
88+
89+
90+
/**
91+
* A meta class for [SoundFormat] and [AudioFourCC].
92+
*/
93+
enum class AudioMediaType(val soundFormat: SoundFormat?, val fourCCs: AudioFourCC?) {
94+
PCM(SoundFormat.PCM, null),
95+
ADPCM(SoundFormat.ADPCM, null),
96+
MP3(SoundFormat.MP3, AudioFourCC.MP3),
97+
PCM_LE(SoundFormat.PCM_LE, null),
98+
NELLYMOSER_16KHZ(SoundFormat.NELLYMOSER_16KHZ, null),
99+
NELLYMOSER_8KHZ(SoundFormat.NELLYMOSER_8KHZ, null),
100+
NELLYMOSER(SoundFormat.NELLYMOSER, null),
101+
G711_ALAW(SoundFormat.G711_ALAW, AudioFourCC.AC3),
102+
G711_MLAW(SoundFormat.G711_MLAW, AudioFourCC.EAC3),
103+
AAC(SoundFormat.AAC, AudioFourCC.AAC),
104+
SPEEX(SoundFormat.SPEEX, null),
105+
MP3_8K(SoundFormat.MP3_8K, null),
106+
DEVICE_SPECIFIC(SoundFormat.DEVICE_SPECIFIC, null),
107+
AC3(null, AudioFourCC.AC3),
108+
EAC3(null, AudioFourCC.EAC3),
109+
OPUS(null, AudioFourCC.OPUS),
110+
FLAC(null, AudioFourCC.FLAC);
111+
112+
113+
companion object {
114+
fun fromFourCC(fourCC: AudioFourCC) =
115+
entries.firstOrNull { it.fourCCs == fourCC } ?: throw IllegalArgumentException(
116+
"Invalid audio FourCC: $fourCC"
117+
)
118+
119+
fun fromSoundFormat(soundFormat: SoundFormat) =
120+
entries.firstOrNull { it.soundFormat == soundFormat }
121+
?: throw IllegalArgumentException("Invalid SoundFormat: $soundFormat")
122+
}
123+
}
124+
58125
enum class SoundRate(val value: Byte, val sampleRate: Int) {
59126
F_5500HZ(0, 5500),
60127
F_11025HZ(1, 11025),

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/config/FLVConfig.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ package io.github.thibaultbee.krtmp.flv.models.config
1818
/**
1919
* Interface for FLV configuration.
2020
*/
21-
sealed interface FLVConfig {
21+
sealed interface FLVConfig<T> {
2222
/**
2323
* The media type of the configuration.
2424
*/
25-
val mediaType: MediaType
25+
val mediaType: T
2626

2727
/**
2828
* The bitrate in bits per second.

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/config/FLVVideoConfig.kt

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,84 @@
1616
package io.github.thibaultbee.krtmp.flv.models.config
1717

1818
class FLVVideoConfig(
19-
override val mediaType: MediaType,
19+
override val mediaType: VideoMediaType,
2020
override val bitrateBps: Int,
2121
val width: Int,
2222
val height: Int,
2323
val frameRate: Int,
24-
) : FLVConfig {
25-
val codecID = if (CodecID.isSupported(mediaType)) {
26-
CodecID.fromMediaType(mediaType)
27-
} else {
28-
null
29-
}
30-
31-
init {
32-
require(mediaType.type == MediaType.Type.VIDEO) { "MimeType must be a video type" }
33-
}
24+
) : FLVConfig<VideoMediaType> {
25+
val codecID = mediaType.codecID
26+
val fourCC = mediaType.fourCCs
27+
val metadataType = codecID?.value?.toInt() ?: fourCC!!.value.code
3428
}
3529

3630

37-
enum class CodecID(val value: Byte, val mediaType: MediaType? = null) {
38-
SORENSON_H263(2, MediaType.VIDEO_H263),
31+
enum class CodecID(val value: Byte) {
32+
SORENSON_H263(2),
3933
SCREEN_1(3),
4034
VP6(4),
4135
VP6_ALPHA(5),
4236
SCREEN_2(6),
43-
AVC(7, MediaType.VIDEO_AVC);
37+
AVC(7);
4438

4539
companion object {
4640
fun entryOf(value: Byte) = entries.firstOrNull { it.value == value }
4741
?: throw IllegalArgumentException("Unsupported CodecID: $value")
42+
}
43+
}
4844

49-
fun isSupported(mediaType: MediaType): Boolean {
50-
return entries.any { it.mediaType == mediaType }
45+
/**
46+
* FourCC object
47+
*
48+
* Only enhanced RTMP FourCC exists.
49+
*/
50+
enum class VideoFourCC(val value: FourCC) {
51+
VP8(
52+
FourCC(
53+
'v', 'p', '0', '8'
54+
)
55+
),
56+
VP9(FourCC('v', 'p', '0', '9')),
57+
AV1(
58+
FourCC(
59+
'a', 'v', '0', '1'
60+
)
61+
),
62+
AVC(
63+
AVCHEVCFourCC(
64+
'a', 'v', 'c', '1'
65+
)
66+
),
67+
HEVC(AVCHEVCFourCC('h', 'v', 'c', '1'));
68+
69+
companion object {
70+
fun codeOf(value: Int) = entries.firstOrNull { it.value.code == value }
71+
?: throw IllegalArgumentException("Unsupported video FourCC: $value")
72+
}
73+
}
74+
75+
class AVCHEVCFourCC(
76+
a: Char, b: Char, c: Char, d: Char
77+
) : FourCC(a, b, c, d)
78+
79+
/**
80+
* A meta class for [CodecID] and [VideoFourCC].
81+
*/
82+
enum class VideoMediaType(val codecID: CodecID?, val fourCCs: VideoFourCC?) {
83+
H263(CodecID.SORENSON_H263, null),
84+
AVC(CodecID.AVC, VideoFourCC.AVC),
85+
HEVC(null, VideoFourCC.HEVC),
86+
VP8(null, VideoFourCC.VP8),
87+
VP9(null, VideoFourCC.VP9),
88+
AV1(null, VideoFourCC.AV1);
89+
90+
companion object {
91+
fun fromFourCC(fourCC: VideoFourCC): VideoMediaType? {
92+
return entries.firstOrNull { it.fourCCs == fourCC }
5193
}
5294

53-
fun fromMediaType(mediaType: MediaType): CodecID {
54-
return entries.firstOrNull { it.mediaType == mediaType }
55-
?: throw IllegalArgumentException("Unsupported MediaType: $mediaType")
95+
fun fromCodecID(codecID: CodecID): VideoMediaType? {
96+
return entries.firstOrNull { it.codecID == codecID }
5697
}
5798
}
5899
}
59-

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/config/FourCC.kt

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,57 +15,15 @@
1515
*/
1616
package io.github.thibaultbee.krtmp.flv.models.config
1717

18-
/**
19-
* FourCC object
20-
*
21-
* Just AV1, VP9 and HEVC are described because these are the only FourCC required for enhanced RTMP.
22-
*/
23-
24-
enum class FourCCs(val value: FourCC) {
25-
VP8(
26-
FourCC(
27-
'v', 'p', '0', '8', MediaType.VIDEO_VP8
28-
)
29-
),
30-
VP9(FourCC('v', 'p', '0', '9', MediaType.VIDEO_VP9)),
31-
AV1(
32-
FourCC(
33-
'a', 'v', '0', '1', MediaType.VIDEO_AV1
34-
)
35-
),
36-
AVC(
37-
AVCHEVCFourCC(
38-
'a', 'v', 'c', '1', MediaType.VIDEO_AVC
39-
)
40-
),
41-
HEVC(AVCHEVCFourCC('h', 'v', 'c', '1', MediaType.VIDEO_HEVC));
42-
43-
companion object {
44-
fun mimeTypeOf(mediaType: MediaType) =
45-
entries.first { it.value.mediaType == mediaType }
46-
47-
fun mimeTypeOf(mimeType: String) =
48-
entries.first { it.value.mediaType.value == mimeType }
49-
50-
fun codeOf(value: Int) = entries.first { it.value.code == value }
51-
}
52-
}
53-
54-
class AVCHEVCFourCC(
55-
a: Char, b: Char, c: Char, d: Char, mediaType: MediaType
56-
) : FourCC(a, b, c, d, mediaType)
57-
5818
/**
5919
* FourCC is a 4 bytes code used to identify a codec.
6020
*/
6121
open class FourCC internal constructor(
6222
val a: Char,
6323
val b: Char,
6424
val c: Char,
65-
val d: Char,
66-
val mediaType: MediaType
25+
val d: Char
6726
) {
68-
6927
/**
7028
* FourCC code
7129
*/

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/config/MediaType.kt

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

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/tags/AudioData.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class AudioData(
5050
body.encode(output)
5151
}
5252

53+
override fun toString(): String {
54+
return "AudioData(soundFormat=$soundFormat, soundRate=$soundRate, soundSize=$soundSize, soundType=$soundType, body=$body)"
55+
}
56+
5357
companion object {
5458
fun decode(source: Source, sourceSize: Int, isEncrypted: Boolean): AudioData {
5559
val byte = source.readByte()

flv/src/commonMain/kotlin/io/github/thibaultbee/krtmp/flv/models/tags/FLVAudioDatas.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,11 @@ package io.github.thibaultbee.krtmp.flv.models.tags
1818
import io.github.thibaultbee.krtmp.flv.models.av.util.AudioSpecificConfig
1919
import io.github.thibaultbee.krtmp.flv.models.av.util.aac.AAC
2020
import io.github.thibaultbee.krtmp.flv.models.av.util.aac.ADTS
21-
import io.github.thibaultbee.krtmp.flv.models.av.util.avc.AVCDecoderConfigurationRecord
22-
import io.github.thibaultbee.krtmp.flv.models.av.util.hevc.HEVCDecoderConfigurationRecord
2321
import io.github.thibaultbee.krtmp.flv.models.av.util.readBuffer
24-
import io.github.thibaultbee.krtmp.flv.models.config.CodecID
25-
import io.github.thibaultbee.krtmp.flv.models.config.FourCCs
2622
import io.github.thibaultbee.krtmp.flv.models.config.SoundFormat
2723
import io.github.thibaultbee.krtmp.flv.models.config.SoundRate
2824
import io.github.thibaultbee.krtmp.flv.models.config.SoundSize
2925
import io.github.thibaultbee.krtmp.flv.models.config.SoundType
30-
import io.github.thibaultbee.krtmp.flv.models.sources.NaluRawSource
3126
import kotlinx.io.RawSource
3227

3328
/**

0 commit comments

Comments
 (0)