Skip to content

Commit 622305b

Browse files
committed
feat(*): introducing a unique streamer not dependent of the endpoint
1 parent 0cbd458 commit 622305b

File tree

250 files changed

+2745
-4003
lines changed

Some content is hidden

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

250 files changed

+2745
-4003
lines changed

DEVELOPER_README.md

Lines changed: 100 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,44 @@ A class that represents an audio or video encoders. Only Android MediaCodec API
1515
`Endpoint`:
1616
The last element of a live streaming pipeline. It is responsible for handling the frames after the
1717
encoder.
18-
It could be composed of a `Muxer` and a `Sink`.
18+
The endpoint could be a remote server (RTMP, SRT,...) or a file (FLV, MPEG-TS,...).
19+
The main endpoint is `CompositeEndpoint` that is composed of a `Muxer` and a `Sink`.
1920

2021
`Muxer`:
21-
A class that packs audio and video frames to a container (FLV, MPEG-TS, MP4,...).
22+
A process that packs audio and video frames to a container (FLV, MPEG-TS, MP4,...).
23+
The `CompositeEndpoint` is composed of a `IMuxer`.
2224

2325
`Sink`:
24-
A class that sends the container to a remote server (RTMP, SRT,...) or to a file.
26+
A process that sends the container to a remote server (RTMP, SRT,...) or to a file.
27+
The `CompositeEndpoint` is composed of a `ISink`.
2528

2629
`Streamer`:
2730
A class that represent a audio and/or video live streaming pipeline. It manages sources, encoders,
2831
muxers, endpoints,... and have lot of tools. They are the most important class for users.
29-
30-
![streamer.png](https://github.com/ThibaultBee/StreamPack/blob/master/docs/assets/streamer.png)
32+
Unless explicitly stated, the `Endpoint` is inferred from the `MediaDescriptor` object thanks to
33+
the `DynamicEndpoint`.
3134

3235
`Streamer element`:
33-
Could be a `Source`, `Encoder`, `Muxer`, or `Endpoint`. They implement the `Streamable<T>`.
36+
Could be a `Source`, `Encoder`, `Muxer`, or `Endpoint`. They implement the `Streamable<T>` and they
37+
might have a public interface to access specific info.
3438

3539
`Info`:
3640
A class that provides a set of methods to help to `streamer` configuration such as supported
3741
resolutions,... It comes with an instantiated `Streamer` object:
3842

3943
```kotlin
40-
val info = streamer.info
44+
val info = streamer.getInfo(MediaDescriptor(`media uri`))
4145
```
4246

4347
They might be different for each `Streamer` object. For example, a `FlvStreamer` object will not
44-
have the same `Helper` object as a `TsStreamer` object because FLV does not support a wide range of
48+
have the same `Info` object as a `TsStreamer` object because FLV does not support a wide range of
4549
codecs, audio sample rate,...
4650

4751
`Settings`:
48-
Each streamer elements have a public interface `Settings` that allows go have access to specific
49-
information or configurations:
50-
52+
Each streamer elements have a public interface that allows go have access to specific
53+
information or configuration.
54+
For example, the `VideoEncoder` object has a `bitrate` property that allows to get and set the
55+
current video bitrate.
5156
Example:
5257

5358
```kotlin
@@ -57,25 +62,20 @@ val bitrate = streamer.videoEncoder!!.bitrate
5762
streamer.videoEncoder!!.bitrate = 2000000
5863
```
5964

60-
`Extensions`:
61-
A library that adds new features from native libraries. It often comes with a `Streamer elements`
62-
and specific pipelines.
63-
6465
## Streamers
6566

66-
The base streamer class is `BaseStreamer`. All other streamers inherit from it. Then 2 specifics
67+
The streamer implementation is the `DefaultStreamer`. All other streamers inherit from it. Then 2
68+
specifics
6769
base streamers inherit from it:
6870

69-
- `BaseCameraStreamer`: A streamer that streams from a camera and microphone. It adds `startPreview`
71+
- `DefaultCameraStreamer`: A streamer that streams from a camera and microphone. It
72+
adds `startPreview`
7073
, `stopPreview` methods to the `Streamer` object as well as a camera settings.
71-
- `BaseScreenRecorderStreamer`: A streamer that streams from the phone screen and microphone. It
74+
- `DefaultScreenRecorderStreamer`: A streamer that streams from the phone screen and microphone. It
7275
adds specific methods for screen recorder as a API to set activity result.
7376

74-
Then these base streamers are specialized for a File or for a Live:
75-
76-
- `BaseFileStreamer`: A streamer that streams to a file. That means you will find
77-
`BaseFileStreamer` for MPEG-TS and one for FLV.
78-
- `BaseLiveStreamer`: A streamer that streams to a remote server (RTMP or SRT both in `extensions`).
77+
To endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to the `Streamer`
78+
by `open` or `startStream` methods.
7979

8080
## Sources
8181

@@ -87,6 +87,21 @@ There are 2 types of sources:
8787
a `Surface`. Its purpose is to improve encoder performance. For example, it suits camera and
8888
screen recorder. `Surface` sources implement `ISurfaceSource`.
8989

90+
@startuml
91+
interface IVideoSource {
92+
93+
+ hasSurface: Boolean
94+
+ encoderSurface: Surface?
95+
+ getFrame(): ByteBuffer
96+
}
97+
98+
interface IAudioSource {
99+
100+
+ getFrame(): ByteBuffer
101+
}
102+
@enduml
103+
+
104+
90105
To create a new audio source, implements a `IAudioSource`. It inherits from `IFrameSource`.
91106

92107
To create a new video source, implements a `IVideSource`. It inherits from both `IFrameCapture`
@@ -106,13 +121,69 @@ If your video source is a `ByteBuffer` source, set:
106121

107122
## Encoders
108123

109-
Both `AudioMediaCodecEncoder` and `VideoMediaCodecEncoder` inherit from `MediaCodecEncoder`. They
110-
are using Android `MediaCodec` API in asynchronous mode.
111-
112-
## Muxers
124+
The only encoder is based on Android `MediaCodec` API. It implements the `IEncoder` interface.
113125

114-
They implement the `IMuxer` interface.
126+
@startuml
127+
interface IEncoder {
128+
}
129+
@enduml
115130

116131
## Endpoints
117132

118-
They implement the `IEndpoint` interface. Use specific `ILiveEndpoint` for live streaming.
133+
They implement the `IEndpoint` interface.
134+
135+
@startuml
136+
interface IEndpoint {
137+
138+
+ open()
139+
+ close()
140+
+ write()
141+
}
142+
143+
class CompositeEndpoint {
144+
145+
+ muxer: IMuxer
146+
+ sink: ISink
147+
}
148+
@enduml
149+
150+
### Muxers
151+
152+
They implement the `IMuxer` interface.
153+
154+
### Sinks
155+
156+
They implement the `ISink` interface.
157+
158+
### Streamers
159+
160+
The implement the `ICoroutineStreamer` interface.
161+
162+
@startuml
163+
class DefaultStreamer {
164+
165+
+ videoSource: IVideoSource
166+
+ audioSource: IAudioSource
167+
+ endoint: IEndpoint
168+
169+
- videoEncoder: IEncoder
170+
- audioEncoder: IEncoder
171+
}
172+
@enduml
173+
174+
@startuml
175+
rectangle DefaultCameraStreamer {
176+
[CameraSource] as VideoSource
177+
[MicrophoneSource] as AudioSource
178+
[Encoder] as VideoEncoder
179+
[Encoder] as AudioEncoder
180+
[Endpoint] as Endpoint
181+
VideoSource -r-> VideoEncoder
182+
AudioSource -r-> AudioEncoder
183+
VideoEncoder -r-> Endpoint
184+
AudioEncoder -r-> Endpoint
185+
AudioSource -d[hidden]-> VideoSource
186+
AudioEncoder -d[hidden]-> VideoEncoder
187+
}
188+
}
189+
@enduml

README.md

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ dependencies {
1414
implementation 'io.github.thibaultbee:streampack:2.6.0'
1515
// For UI (incl. PreviewView)
1616
implementation 'io.github.thibaultbee:streampack-ui:2.6.0'
17+
// For ScreenRecorder service
18+
implementation 'io.github.thibaultbee:streampack-services:2.6.0'
1719
// For RTMP
1820
implementation 'io.github.thibaultbee:streampack-extension-rtmp:2.6.0'
1921
// For SRT
@@ -108,10 +110,9 @@ If you want to create a new application, you should use the
108110
template [StreamPack boilerplate](https://github.com/ThibaultBee/StreamPack-boilerplate). In 5
109111
minutes, you will be able to stream live video to your server.
110112

111-
1. Add [permissions](#permissions) to your `AndroidManifest.xml` and request them in your
112-
Activity/Fragment.
113+
1. Request the required permissions in your Activity/Fragment.
113114

114-
2. Create a `SurfaceView` to display camera preview in your layout
115+
2. Creates a `SurfaceView` to display camera preview in your layout
115116

116117
As a camera preview, you can use a `SurfaceView`, a `TextureView` or any
117118
`View` where that can provide a `Surface`.
@@ -129,13 +130,13 @@ To simplify integration, StreamPack provides an `PreviewView`.
129130

130131
`app:enableZoomOnPinch` is a boolean to enable zoom on pinch gesture.
131132

132-
3. Instantiate the streamer (main live streaming class)
133+
3. Instantiates the streamer (main live streaming class)
133134

134135
```kotlin
135-
val streamer = CameraSrtLiveStreamer(context = requireContext())
136+
val streamer = DefaultCameraStreamer(context = requireContext())
136137
```
137138

138-
4. Configure audio and video settings
139+
4. Configures audio and video settings
139140

140141
```kotlin
141142
val audioConfig = AudioConfig(
@@ -153,7 +154,7 @@ val videoConfig = VideoConfig(
153154
streamer.configure(audioConfig, videoConfig)
154155
```
155156

156-
5. Inflate the camera preview with the streamer
157+
5. Inflates the camera preview with the streamer
157158

158159
```kotlin
159160
/**
@@ -166,17 +167,25 @@ preview.streamer = streamer
166167
streamer.startPreview(preview)
167168
```
168169

169-
6. Start the live streaming
170+
6. Starts the live streaming
170171

171172
```kotlin
172-
streamer.startStream(ip, port)
173+
val descriptor =
174+
UriMediaDescriptor("rtmps://serverip:1935/s/streamKey") // For RTMP/RTMPS. Uri also supports SRT url, file, content path,...
175+
/**
176+
* Alternatively, you can use object syntax:
177+
* - RtmpConnectionDescriptor("rtmps", "serverip", 1935, "s", "streamKey") // For RTMP/RTMPS
178+
* - SrtConnectionDescriptor("serverip", 1234) // For SRT
179+
*/
180+
181+
streamer.startStream()
173182
```
174183

175-
7. Stop and release the streamer
184+
7. Stops and releases the streamer
176185

177186
```kotlin
178187
streamer.stopStream()
179-
streamer.disconnect()
188+
streamer.close() // Disconnect from server or close the file
180189
streamer.stopPreview() // The StreamerSurfaceView will be automatically stop the preview
181190
streamer.release()
182191
```
@@ -242,7 +251,7 @@ You will also have to declare the `Service`,
242251
```xml
243252

244253
<application>
245-
<!-- YourScreenRecorderService extends ScreenRecorderRtmpLiveService or ScreenRecorderSrtLiveService -->
254+
<!-- YourScreenRecorderService extends DefaultScreenRecorderService -->
246255
<service android:name=".services.YourScreenRecorderService" android:exported="false"
247256
android:foregroundServiceType="mediaProjection" />
248257
</application>
@@ -267,30 +276,34 @@ It is easy: if your server has SRT support, use SRT otherwise use RTMP.
267276

268277
### Streamers
269278

270-
Let's start with some definitions! `Streamers` are classes that represent a live streaming pipeline:
271-
capture, encode, mux and send. They comes in multiple flavours: with different audio and video
272-
source, with different endpoints and functionalities... 3 types of base streamers are available:
273-
274-
- `CameraStreamers`: for streaming from camera
275-
- `ScreenRecorderStreamers`: for streaming from screen
276-
- `AudioOnlyStreamers`: for streaming audio only
277-
278-
You can find specific streamers for File or for Live. Currently, there are 2 main endpoints:
279+
Let's start with some definitions! `Streamers` are classes that represent a streaming pipeline:
280+
capture, encode, mux and send.
281+
They comes in multiple flavours: with different audio and video source. 3 types of base streamers
282+
are available:
279283

280-
- `FileStreamer`: for streaming to file
281-
- `LiveStreamer`: for streaming to a RTMP or a SRT live streaming server
284+
- `DefaultCameraStreamer`: for streaming from camera
285+
- `DefaultScreenRecorderStreamer`: for streaming from screen
286+
- `DefaultAudioOnlyStreamer`: for streaming audio only
282287

283-
For example, you can use `AudioOnlyFlvFileStreamer` to stream from microphone only to a FLV file.
284-
Another example, you can use `CameraRtmpLiveStreamer` to stream from camera to a RTMP server.
288+
Since 3.0.0, the endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to
289+
the `open` or `startStream` methods. It is possible to limit the possibility of the endpoint by
290+
implementing your own `DynamicEndpoint.Factory` or passing a endpoint as the `Streamer` `endpoint`
291+
parameter.
285292

286-
If a streamer is missing, of course, you can also create your own. You should definitely submit it
287-
in a [pull request](https://github.com/ThibaultBee/StreamPack/pulls).
293+
To create a `Streamer` for a new source, you have to create a new `Streamer` class that inherits
294+
from `DefaultStreamer`.
288295

289296
### Get device capabilities
290297

291298
Have you ever wonder: "What are the supported resolution of my cameras?" or "What is the supported
292299
sample rate of my audio codecs?"? `Info` classes are made for this. All `Streamer` comes with a
293-
specific `Info` object (I am starting to have the feeling I repeat myself):
300+
specific `Info` object:
301+
302+
```kotlin
303+
val info = streamer.getInfo(MediaDescriptor("rtmps://serverip:1935/s/streamKey"))
304+
```
305+
306+
For static endpoint or an opened dynamic endpoint, you can directly get the info:
294307

295308
```kotlin
296309
val info = streamer.info
@@ -299,32 +312,34 @@ val info = streamer.info
299312
### Get extended settings
300313

301314
If you are looking for more settings on streamer, like the exposure compensation of your camera, you
302-
must have a look on `Settings` class. All together: "All `Streamer` comes with a specific `Settings`
303-
object":
315+
must have a look on `Settings` class. Each `Streamer` elements (such
316+
as `VideoSource`, `AudioSource`,...)
317+
comes with a public interface that allows to have access to specific information or configuration.
304318

305319
```kotlin
306-
streamer.settings
320+
(streamer.videoSource as IPublicCameraSource).settings
307321
```
308322

309323
For example, if you want to change the exposure compensation of your camera, on a `CameraStreamers`
310324
you can do it like this:
311325

312326
```kotlin
313-
streamer.settings.camera.exposure.compensation = value
327+
(streamer.videoSource as IPublicCameraSource).settings.exposure.compensation = value
314328
```
315329

316330
Moreover you can check exposure range and step with:
317331

318332
```kotlin
319-
streamer.settings.camera.exposure.availableCompensationRange
320-
streamer.settings.camera.exposure.availableCompensationStep
333+
(streamer.videoSource as IPublicCameraSource).settings.exposure.availableCompensationRange
334+
(streamer.videoSource as IPublicCameraSource).settings.exposure.availableCompensationStep
321335
```
322336

323337
### Screen recorder Service
324338

325-
To record the screen, you have to use one of the `ScreenRecorderStreamers` inside
339+
To record the screen, you have to use the `DefaultScreenRecorderStreamer` inside
326340
an [Android Service](https://developer.android.com/guide/components/services). To simplify this
327-
integration, StreamPack provides several `ScreenRecorderService` classes. Extends one of these class
341+
integration, StreamPack provides the `DefaultScreenRecorderService` classes. Extends one of these
342+
class
328343
and overrides `onNotification` to customise the notification.
329344

330345
### Android SDK version

core/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ dependencies {
1818
testImplementation 'androidx.test:rules:1.5.0'
1919
testImplementation 'junit:junit:4.13.2'
2020
testImplementation 'io.mockk:mockk:1.12.2'
21+
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1'
22+
testImplementation "org.robolectric:robolectric:4.12.2"
2123

2224
androidTestImplementation 'androidx.test:rules:1.5.0'
2325
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
2426
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
27+
androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1'
2528
}

0 commit comments

Comments
 (0)