Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #123

Closed
wants to merge 106 commits into from
Closed

Dev #123

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
f4ddb70
refactor(*): move views to a specific package
ThibaultBee Feb 26, 2024
a7a0f6a
feat(*): introducing endpoint component
ThibaultBee Mar 6, 2024
6d3cac1
feat(*): add a media muxer endpoint
ThibaultBee Mar 8, 2024
4079dad
refactor(core): refactor how the encoder are handled. Avoid to recrea…
ThibaultBee Feb 26, 2024
8ec9d22
fix(core): only create codec surface once
ThibaultBee Mar 6, 2024
00cab4c
feat(encoder): properly set their visibility
ThibaultBee Apr 24, 2024
8e449f7
fix(core): silence unchecked cast in camera settings
ThibaultBee Apr 24, 2024
6ad2ceb
feat(*): streamer elements have are accessible and have a public API …
ThibaultBee Apr 24, 2024
a279929
feat(*): rename helpers to info
ThibaultBee Apr 24, 2024
e9f3ba3
feat(*): add public interface for endpoint
ThibaultBee Apr 25, 2024
78690a0
chore(core): move internal source folder
ThibaultBee Apr 25, 2024
fc4d819
refactor(core): rename file writer to file sink
ThibaultBee May 14, 2024
11d0476
refactor(core): remove listener from constructor.
ThibaultBee May 14, 2024
b7af59b
refactor(core): remove listener from constructors
ThibaultBee May 15, 2024
8faf0c3
feat(*): introducing a unique streamer not dependent of the endpoint
ThibaultBee May 23, 2024
87f18cb
refactor(*): move streampack core package to `streampack.core`
ThibaultBee Jun 24, 2024
a11951a
chore(*): move repositories to `streampack`
ThibaultBee Jun 24, 2024
59aa3a7
refactor(*): rename streamer `exception` to `throwable`
ThibaultBee Jun 24, 2024
ca8a913
fix(*): fix exception that happens when the stream is stopped
ThibaultBee Jun 24, 2024
80bb694
feat(srt): use srtdroid coroutine socket
ThibaultBee Jul 10, 2024
d5a4369
chore(rtmp): improve exception
ThibaultBee Jul 10, 2024
7d1197e
refactor(demo): remove runBlocking
ThibaultBee Jul 11, 2024
8c61c9f
refactor(*): use Kotlin DSL instead of groovy
ThibaultBee Jul 17, 2024
3359c72
chore(ci): upgrade actions
ThibaultBee Jul 17, 2024
adc1ec9
feat(services): adapt to streamer open/close mechanism
ThibaultBee Jul 17, 2024
1acad40
feat(srt): make srtdroid available
ThibaultBee Aug 8, 2024
f3e2e90
style(core): remove empty end of line
ThibaultBee Aug 8, 2024
dfb7ace
feat(core): made sink write return written length
ThibaultBee Aug 8, 2024
a08a285
fix(core): synchronize media muxer endpoint
ThibaultBee Aug 8, 2024
3e8fea3
test(core): add test on endpoints
ThibaultBee Aug 8, 2024
ffe60a7
refactor(core): clean and rename few parameters
ThibaultBee Aug 8, 2024
95537d0
fix(core): return when `stopStream` is called on CodecSurface
ThibaultBee Aug 8, 2024
493f16c
fix(core): microphone: isRunning is a getter
ThibaultBee Aug 8, 2024
2956587
refactor(core): endpoint: move release to the interface
ThibaultBee Aug 9, 2024
3117565
chore(demo): fix a typo
ThibaultBee Aug 9, 2024
bf9efc3
feat(core): return a specific exception when we fail to infer from th…
ThibaultBee Aug 9, 2024
9953a5d
fix(core): fix dynamic endpoint isOpened
ThibaultBee Aug 9, 2024
5ab2e79
test(core): add test on dynamic endpoint
ThibaultBee Aug 9, 2024
88422c1
refactor(core): lazify object properties
ThibaultBee Aug 14, 2024
42a58cc
feat(srt): add SrtMediaDescriptor from string
ThibaultBee Aug 16, 2024
5656f6f
fix(srt): add support for stream id with #! format
ThibaultBee Aug 26, 2024
a6f0f5a
feat(core): add possibility to stream without preview
ThibaultBee Aug 28, 2024
8fa9963
test(core): add test on camera streamer
ThibaultBee Aug 28, 2024
7dae435
fix(*): multiple fixes on screen recorder services
ThibaultBee Aug 29, 2024
877b864
refactor(*): use `requireNotNull` instead of `require` != null
ThibaultBee Aug 29, 2024
875b5c9
fix(demos): camera: uncheck live button when application is put to ba…
ThibaultBee Aug 30, 2024
5541c17
fix(core): streamer `close` must stop stream prior to `close`
ThibaultBee Aug 30, 2024
a333d9d
refactor(extension): make srt and rtmp socket nullable
ThibaultBee Aug 30, 2024
dcc7a58
clean(core): remove useless try/catch
ThibaultBee Sep 2, 2024
b1a2906
feat(core): add `String` API for `UriMediaDescriptor`
ThibaultBee Sep 2, 2024
5959ce3
fix(srt): properly handle when srt connection is remotely closed
ThibaultBee Sep 2, 2024
21cc41c
refactor(*): rename `isOpened` to `isOpen`
ThibaultBee Sep 2, 2024
306e49c
refactor(*): catch `Throwable` instead of `Exception`
ThibaultBee Sep 2, 2024
af9bf35
refactor(core): move public extensions to specific package
ThibaultBee Sep 2, 2024
5b0080d
feat(*): introducing `ClosedException`
ThibaultBee Sep 2, 2024
b1df15a
feat(*): add streamer extension to open with Uri and String
ThibaultBee Sep 3, 2024
56ded72
chore(core): improve comment on `DynamicEndpoint`
ThibaultBee Sep 3, 2024
c3eec17
fix(ui): make `getPreviewOutputSize` public for backward compatibility
ThibaultBee Sep 3, 2024
b7b0bcf
chore(core): remove deprecated comment
ThibaultBee Sep 3, 2024
2727569
fix(ci): fix CodeQL workflow due to using custom gradle kts
ThibaultBee Sep 5, 2024
ae40b31
clean(core): refactor chunk output stream
ThibaultBee Sep 5, 2024
7e602d9
docs(core): add comment on `UriMediaDescriptor`
ThibaultBee Sep 5, 2024
52c2d69
fix(demos): camera: fix the part where extension is removed
ThibaultBee Sep 5, 2024
9b1b7a6
test(core): add tests for camera preview
ThibaultBee Sep 9, 2024
f1ae616
chore(ci): get emulator logcat and only test for API 34
ThibaultBee Sep 9, 2024
264ecf5
refactor(core): move streamer extensions to streamer package
ThibaultBee Sep 9, 2024
abbaaac
feat(core): make bitrate and co more readable
ThibaultBee Sep 9, 2024
2ab4763
test(*): add long running live streaming test to api.video
ThibaultBee Sep 9, 2024
0c54c55
feat(core): add an onclose reason for callback streamer
ThibaultBee Sep 10, 2024
24b4046
chore(deps): upgrade srtdroid to fix a crash on close
ThibaultBee Sep 11, 2024
5fb131b
fix(core): mediacodec: do not reconfigure if stream has not been running
ThibaultBee Sep 11, 2024
6e18ce7
feat(core): streamer: add a camera callback streamer
ThibaultBee Sep 11, 2024
e74e9d6
fix(*): sink and endpoint return instead of throwing on `open`
ThibaultBee Sep 12, 2024
8919f0f
fix(ci): do not run test on build workflow
ThibaultBee Sep 12, 2024
3ec77e8
feat(core): rename public and internal interfaces
ThibaultBee Sep 12, 2024
6060f69
feat(core): streamer: use extension for camera streamer startPreview …
ThibaultBee Sep 13, 2024
a249890
refactor(test): use parametrized test instead of inheritance
ThibaultBee Sep 13, 2024
6098db7
feat(test): add test for streamer
ThibaultBee Sep 13, 2024
5ca2bde
feat(test): core: add test for sink and endpoint state
ThibaultBee Sep 16, 2024
5dab5cc
fix(core): source: throw exception if source was running when calling…
ThibaultBee Sep 16, 2024
8bc25f6
feat(core): config: add isEquals and hashcode for config
ThibaultBee Sep 16, 2024
c1d79a1
feat(core): add experimental support of other AAC mime type
ThibaultBee Sep 16, 2024
c8cc417
fix(srt): remove ttl to avoid spurious frame drop
ThibaultBee Sep 17, 2024
f5717e9
refactor(*): move streamer extension to their parent interface
ThibaultBee Sep 18, 2024
7391cfd
fix(srt): fix remote disconnection on SrtSink
ThibaultBee Sep 19, 2024
d9c8b07
chore(deps): upgrade few dependencies
ThibaultBee Sep 19, 2024
4ca058a
docs(*): improve comment for callback streamer
ThibaultBee Sep 23, 2024
4cba439
chore(deps): bump view finder to alpha08
ThibaultBee Sep 23, 2024
6df9f6b
fix(core): streamer: fix camera streamers video source interface
ThibaultBee Sep 23, 2024
46f725b
feat(core): streamer: add a way to pass a specific audio source
ThibaultBee Sep 23, 2024
918b040
refactor(core): source: rename screen source to media projection source
ThibaultBee Sep 24, 2024
f419359
refactor(core): move enable noise suppressor and enable echo cancelle…
ThibaultBee Sep 24, 2024
ad7020b
feat(core): add media projection audio source
ThibaultBee Sep 24, 2024
3fd79d9
feat(core): add an API to get current audio and video config
ThibaultBee Sep 25, 2024
4ccc071
feat(core): camera: add an API to get whether camera is previewing
ThibaultBee Sep 30, 2024
6cc3361
chore(core): make string extension internal
ThibaultBee Oct 2, 2024
50cf4c2
feat(ui): add preview API for camerax CameraViewFinder
ThibaultBee Oct 2, 2024
1b53d73
fix(core): source: camera: replace logger
ThibaultBee Oct 3, 2024
e7586e9
fix(demos): camera: do not release streamer in the lifecycle observer…
ThibaultBee Oct 3, 2024
2144b60
refactor(ui): simplify PreviewView
ThibaultBee Oct 3, 2024
a3bc06b
fix(core): streamer: make dispatcher private
ThibaultBee Oct 9, 2024
253806a
chore(deps): srt: upgrade to srtdroid 1.8.4
ThibaultBee Oct 24, 2024
ef4a2b5
fix(demos): screenrecorder: fix enableAudio flag
ThibaultBee Nov 13, 2024
661ab83
chore(deps): upgrade dependencies
ThibaultBee Nov 14, 2024
8adacbe
fix(demos): camera: avoid to recreate a view model on device rotation
ThibaultBee Nov 15, 2024
ba72195
refactor(core): replace CodecSurface by the SurfaceProcessor
ThibaultBee Oct 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 3 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build
run: ./gradlew build
- name: Assemble
run: ./gradlew assembleDebug
run: ./gradlew assemble
- name: Upload APKs
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: apks
path: |
Expand Down
10 changes: 2 additions & 8 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
matrix:
include:
- language: java-kotlin
build-mode: autobuild
build-mode: manual
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
Expand Down Expand Up @@ -84,13 +84,7 @@ jobs:
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
run: ./gradlew --scan --full-stacktrace -Dorg.gradle.dependency.verification=off compileDebugAndroidTestSources

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'adopt'
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
- name: Setup git config (for patch command)
run: |
git config --global user.name "GitHub Actions Bot"
git config --global user.email "<>"
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Decode the secret key
run: echo $GPG_KEYRING_FILE_CONTENT | base64 --decode > ~/secring.gpg
env:
GPG_KEYRING_FILE_CONTENT: "${{ secrets.GPG_KEYRING_FILE_CONTENT }}"
- name: Publish package
run: ./gradlew publish -Psigning.secretKeyRingFile=$(echo ~/secring.gpg) -Psigning.password=$GPG_PASSPHRASE -Psigning.keyId=$GPG_KEY_ID
run: ./gradlew publish
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
GPG_KEY: ${{ secrets.GPG_KEY }}
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
18 changes: 14 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
Expand All @@ -29,7 +29,7 @@ jobs:
timeout-minutes: 55
strategy:
matrix:
api-level: [ 26, 34 ]
api-level: [ 34 ]
steps:
- name: Enable KVM group perms
run: |
Expand All @@ -51,10 +51,20 @@ jobs:
arch: x86_64
disable-animations: true
emulator-options: -no-snapshot -no-window -no-boot-anim -camera-back emulated -camera-front emulated -gpu swiftshader_indirect
script: ./gradlew connectedCheck
script: |
adb root
adb logcat -c
touch emulator.log
chmod 777 emulator.log
adb logcat >> emulator.log &
./gradlew -Pandroid.testInstrumentationRunnerArguments.INTEGRATION_TESTS_API_KEY=$INTEGRATION_TESTS_API_KEY connectedCheck
env:
INTEGRATION_TESTS_API_KEY: ${{ secrets.INTEGRATION_TESTS_API_KEY }}
- name: Upload test reports
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: test-reports-${{ matrix.api-level }}
path: '**/build/reports/androidTests'
path: |
'**/build/reports/androidTests'
emulator.log
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ build
/captures
.externalNativeBuild
.cxx
.kotlin
145 changes: 111 additions & 34 deletions DEVELOPER_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,64 +12,70 @@ microphone (`AudioSource`).
A class that represents an audio or video encoders. Only Android MediaCodec API is used (
`MediaCodecEncoder`).

`Endpoint`:
The last element of a live streaming pipeline. It is responsible for handling the frames after the
encoder.
The endpoint could be a remote server (RTMP, SRT,...) or a file (FLV, MPEG-TS,...).
The main endpoint is `CompositeEndpoint` that is composed of a `Muxer` and a `Sink`.

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

`Endpoint`:
The last element of a live streaming pipeline. It is responsible for sending the audio and video
streams somewhere For example, a file (`FileWriter`), or a remote RTMP server (`RtmpProducer`).
`Sink`:
A process that sends the container to a remote server (RTMP, SRT,...) or to a file.
The `CompositeEndpoint` is composed of a `ISink`.

`Streamer`:
A class that represent a audio and/or video live streaming pipeline. It manages sources, encoders,
muxers, endpoints,... and have lot of tools. They are the most important class for users.

![streamer.png](https://github.com/ThibaultBee/StreamPack/blob/master/docs/assets/streamer.png)
Unless explicitly stated, the `Endpoint` is inferred from the `MediaDescriptor` object thanks to
the `DynamicEndpoint`.

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

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

```kotlin
val helper = streamer.helper
val info = streamer.getInfo(MediaDescriptor(`media uri`))
```

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

`Settings`:
A class that adds settings to the `Streamer` object. For example, you can access camera settings,
encoders bitrate,... It comes with an instantiated `Streamer` object:
Each streamer elements have a public interface that allows go have access to specific
information or configuration.
For example, the `VideoEncoder` object has a `bitrate` property that allows to get and set the
current video bitrate.
Example:

```kotlin
val settings = streamer.settings
// Get video bitrate
val bitrate = streamer.videoEncoder!!.bitrate
// Set video bitrate on the fly
streamer.videoEncoder!!.bitrate = 2000000
```

They might be different for each `Streamer` object. For example, only `CameraStreamer` have a camera
settings.

`Extensions`:
A library that adds new features from native libraries. It often comes with a `Streamer elements`
and specific pipelines.

## Streamers

The base streamer class is `BaseStreamer`. All other streamers inherit from it. Then 2 specifics
The streamer implementation is the `DefaultStreamer`. All other streamers inherit from it. Then 2
specifics
base streamers inherit from it:

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

Then these base streamers are specialized for a File or for a Live:

- `BaseFileStreamer`: A streamer that streams to a file. That means you will find
`BaseFileStreamer` for MPEG-TS and one for FLV.
- `BaseLiveStreamer`: A streamer that streams to a remote server (RTMP or SRT both in `extensions`).
To endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to the `Streamer`
by `open` or `startStream` methods.

## Sources

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

@startuml
interface IVideoSource {

+ hasSurface: Boolean
+ encoderSurface: Surface?
+ getFrame(): ByteBuffer
}

interface IAudioSource {

+ getFrame(): ByteBuffer
}
@enduml
+

To create a new audio source, implements a `IAudioSource`. It inherits from `IFrameSource`.

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

## Encoders

Both `AudioMediaCodecEncoder` and `VideoMediaCodecEncoder` inherit from `MediaCodecEncoder`. They
are using Android `MediaCodec` API in asynchronous mode.
The only encoder is based on Android `MediaCodec` API. It implements the `IEncoder` interface.

## Muxers

They implement the `IMuxer` interface.
@startuml
interface IEncoder {
}
@enduml

## Endpoints

They implement the `IEndpoint` interface. Use specific `ILiveEndpoint` for live streaming.
They implement the `IEndpoint` interface.

@startuml
interface IEndpoint {

+ open()
+ close()
+ write()
}

class CompositeEndpoint {

+ muxer: IMuxer
+ sink: ISink
}
@enduml

### Muxers

They implement the `IMuxer` interface.

### Sinks

They implement the `ISink` interface.

### Streamers

The implement the `ICoroutineStreamer` interface.

@startuml
class DefaultStreamer {

+ videoSource: IVideoSource
+ audioSource: IAudioSource
+ endoint: IEndpoint

- videoEncoder: IEncoder
- audioEncoder: IEncoder
}
@enduml

@startuml
rectangle DefaultCameraStreamer {
[CameraSource] as VideoSource
[MicrophoneSource] as AudioSource
[Encoder] as VideoEncoder
[Encoder] as AudioEncoder
[Endpoint] as Endpoint
VideoSource -r-> VideoEncoder
AudioSource -r-> AudioEncoder
VideoEncoder -r-> Endpoint
AudioEncoder -r-> Endpoint
AudioSource -d[hidden]-> VideoSource
AudioEncoder -d[hidden]-> VideoEncoder
}
}
@enduml
Loading